diff --git a/Makefile b/Makefile index 5791349..6d745f0 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,10 @@ -source = parse.cpp parserstate.cpp parser.cpp templates.cpp terminal.cpp termemu.cpp parseraction.cpp terminalfunctions.cpp swrite.cpp terminalframebuffer.cpp terminaldispatcher.cpp terminaluserinput.cpp terminaldisplay.cpp network.cpp ntester.cpp ocb.cpp base64.cpp encrypt.cpp decrypt.cpp crypto.cpp networktransport.cpp -objects = parserstate.o parser.o templates.o terminal.o parseraction.o terminalfunctions.o swrite.o terminalframebuffer.o terminaldispatcher.o terminaluserinput.o terminaldisplay.o network.o ocb.o base64.o crypto.o networktransport.o +source = parse.cpp parserstate.cpp parser.cpp templates.cpp terminal.cpp termemu.cpp parseraction.cpp terminalfunctions.cpp swrite.cpp terminalframebuffer.cpp terminaldispatcher.cpp terminaluserinput.cpp terminaldisplay.cpp network.cpp ntester.cpp ocb.cpp base64.cpp encrypt.cpp decrypt.cpp crypto.cpp networktransport.cpp networkinstruction.cpp keystroke.cpp +objects = parserstate.o parser.o templates.o terminal.o parseraction.o terminalfunctions.o swrite.o terminalframebuffer.o terminaldispatcher.o terminaluserinput.o terminaldisplay.o network.o ocb.o base64.o crypto.o networktransport.o networkinstruction.o keystroke.o repos = templates.rpo executables = parse termemu ntester encrypt decrypt CXX = g++ -CXXFLAGS = -g --std=c++0x -pedantic -Werror -Wall -Wextra -Weffc++ -fno-implicit-templates -fno-default-inline -pipe -D_FILE_OFFSET_BITS=64 -D_XOPEN_SOURCE=500 -D_GNU_SOURCE +CXXFLAGS = -g --std=c++0x -pedantic -Werror -Wall -Wextra -Weffc++ -fno-implicit-templates -fno-default-inline -pipe -D_FILE_OFFSET_BITS=64 -D_XOPEN_SOURCE=500 -D_GNU_SOURCE -D_BSD_SOURCE LIBS = -lutil -lssl -lrt all: $(executables) diff --git a/keystroke.cpp b/keystroke.cpp new file mode 100644 index 0000000..8d5b129 --- /dev/null +++ b/keystroke.cpp @@ -0,0 +1,44 @@ +#include + +#include "keystroke.hpp" + +void KeyStroke::subtract( KeyStroke * const prefix ) +{ + for ( deque::iterator i = prefix->user_bytes.begin(); + i != prefix->user_bytes.end(); + i++ ) { + assert( *i == user_bytes.front() ); + user_bytes.pop_front(); + } +} + +string KeyStroke::diff_from( KeyStroke const & existing, int length_limit ) +{ + string ret; + + deque::iterator my_it = user_bytes.begin(); + + for ( deque::const_iterator i = existing.user_bytes.begin(); + i != existing.user_bytes.end(); + i++ ) { + assert( *i == *my_it ); + my_it++; + } + + while ( (my_it != user_bytes.end()) + && ( (length_limit < 0) ? true : (int(ret.size()) < length_limit) ) ) { + ret += string( &( *my_it ), 1 ); + my_it++; + } + + return ret; +} + +void KeyStroke::apply_string( string diff ) +{ + for ( string::iterator i = diff.begin(); + i != diff.end(); + i++ ) { + user_bytes.push_back( *i ); + } +} diff --git a/keystroke.hpp b/keystroke.hpp index e9177d1..2836827 100644 --- a/keystroke.hpp +++ b/keystroke.hpp @@ -1,6 +1,7 @@ #ifndef KEYSTROKE_HPP #define KEYSTROKE_HPP +#include #include #include @@ -9,10 +10,17 @@ using namespace std; class KeyStroke { public: - void subtract( KeyStroke * const ) {} - string diff_from( KeyStroke const &, int ) { return ""; } - void apply_string( string ) {} - bool operator==( KeyStroke const & ) const { return true; } + deque user_bytes; + + KeyStroke() : user_bytes() {} + + void key_hit( char x ) { user_bytes.push_back( x ); } + + /* interface for Network::Transport */ + void subtract( KeyStroke * const prefix ); + string diff_from( KeyStroke const & existing, int length_limit ); + void apply_string( string diff ); + bool operator==( KeyStroke const &x ) const { return user_bytes == x.user_bytes; } }; #endif diff --git a/network.cpp b/network.cpp index f22dbb8..3e20491 100644 --- a/network.cpp +++ b/network.cpp @@ -30,7 +30,7 @@ string Packet::tostring( Session *session ) { uint64_t direction_seq = (uint64_t( direction == TO_CLIENT ) << 63) | (seq & 0x7FFFFFFFFFFFFFFF); - return session->encrypt( Message( direction_seq, payload ) ); + return session->encrypt( Message( Nonce( direction_seq ), payload ) ); } Packet Connection::new_packet( string &s_payload ) diff --git a/network.hpp b/network.hpp index a430615..1c03a81 100644 --- a/network.hpp +++ b/network.hpp @@ -76,8 +76,9 @@ namespace Network { void send( string &s ); string recv( void ); int fd( void ) { return sock; } - int port( void ); int get_MTU( void ) { return MTU; } + + int port( void ); string get_key( void ) { return key.printable_key(); } }; } diff --git a/networkinstruction.cpp b/networkinstruction.cpp new file mode 100644 index 0000000..906488b --- /dev/null +++ b/networkinstruction.cpp @@ -0,0 +1,23 @@ +#include + +#include "networktransport.hpp" + +using namespace Network; + +static string network_order_string( uint64_t host_order ) +{ + uint64_t net_int = htobe64( host_order ); + return string( (char *)&net_int, sizeof( net_int ) ); +} + +string Instruction::tostring( void ) +{ + string ret; + + ret += network_order_string( old_num ); + ret += network_order_string( new_num ); + ret += network_order_string( ack_num ); + ret += diff; + + return ret; +} diff --git a/networktransport.cpp b/networktransport.cpp index 4620d45..9e85d36 100644 --- a/networktransport.cpp +++ b/networktransport.cpp @@ -1,4 +1,5 @@ #include +#include #include "networktransport.hpp" @@ -47,20 +48,16 @@ Transport::Transport( MyState &initial_state, /* client */ } -template -void Transport::new_state( MyState &s ) -{ - current_state = s; - - tick(); -} - template void Transport::tick( void ) { /* Update assumed receiver state */ update_assumed_receiver_state(); + fprintf( stderr, "Assumed receiver state: %d/%d\r\n", + int(assumed_receiver_state->num), + int(sent_states.back().num) ); + /* Cut out common prefix of all states */ rationalize_states(); @@ -74,20 +71,6 @@ void Transport::tick( void ) template void Transport::send_to_receiver( void ) { - if ( assumed_receiver_state->state == sent_states.back().state ) { - /* send empty ack */ - Instruction inst( assumed_receiver_state->num, - assumed_receiver_state->num, - "", - highest_state_received ); - string s = inst.tostring(); - connection.send( s ); - sent_states.back().timestamp = timestamp(); - return; - } - - /* Otherwise, send sequence of diffs between assumed receiver state and current state */ - /* We don't want to assume that this sequence of diffs will necessarily bring the receiver to the _actual_ current state. That requires perfect round-trip stability of the diff @@ -101,11 +84,31 @@ void Transport::send_to_receiver( void ) MyState target_receiver_state( assumed_receiver_state->state ); target_receiver_state.apply_string( current_state.diff_from( target_receiver_state, -1 ) ); + if ( assumed_receiver_state->state == target_receiver_state ) { + /* send empty ack */ + Instruction inst( assumed_receiver_state->num, + assumed_receiver_state->num, + highest_state_received, + "" ); + string s = inst.tostring(); + connection.send( s ); + assumed_receiver_state->timestamp = timestamp(); + + fprintf( stderr, "Empty ack.\r\n" ); + + return; + } + + int tries = 0; while ( !(assumed_receiver_state->state == target_receiver_state) ) { - Instruction inst( assumed_receiver_state->num, -1, + if ( tries++ > 1024 ) { + fprintf( stderr, "BUG: Convergence limit exceeded.\n" ); + exit( 1 ); + } + + Instruction inst( assumed_receiver_state->num, -1, highest_state_received, current_state.diff_from( assumed_receiver_state->state, - connection.get_MTU() - HEADER_LEN ), - highest_state_received ); + connection.get_MTU() - HEADER_LEN ) ); MyState new_state = assumed_receiver_state->state; new_state.apply_string( inst.diff ); @@ -133,6 +136,11 @@ void Transport::send_to_receiver( void ) string s = inst.tostring(); try { + fprintf( stderr, "Sending: " ); + for ( size_t i = 0; i < s.size(); i++ ) { + fprintf( stderr, "%c", s[ i ] ); + } + fprintf( stderr, "\r\n" ); connection.send( s ); } catch ( MTUException m ) { continue; @@ -174,4 +182,6 @@ void Transport::rationalize_states( void ) i++ ) { i->state.subtract( known_receiver_state ); } + + current_state.subtract( known_receiver_state ); } diff --git a/networktransport.hpp b/networktransport.hpp index 5a8a7cb..48580c5 100644 --- a/networktransport.hpp +++ b/networktransport.hpp @@ -15,15 +15,15 @@ namespace Network { { public: uint64_t old_num, new_num; - string diff; - uint64_t ack_num; - Instruction( uint64_t s_old_num, uint64_t s_new_num, string s_diff, uint64_t s_ack_num ) - : old_num( s_old_num ), new_num( s_new_num ), diff( s_diff ), ack_num( s_ack_num ) + string diff; + + Instruction( uint64_t s_old_num, uint64_t s_new_num, uint64_t s_ack_num, string s_diff ) + : old_num( s_old_num ), new_num( s_new_num ), ack_num( s_ack_num ), diff( s_diff ) {} - string tostring( void ) { return ""; } + string tostring( void ); }; template @@ -76,8 +76,12 @@ namespace Network { Transport( MyState &initial_state ); Transport( MyState &initial_state, const char *key_str, const char *ip, int port ); - void new_state( MyState &s ); void tick( void ); + + int port( void ) { return connection.port(); } + string get_key( void ) { return connection.get_key(); } + + MyState &get_current_state( void ) { return current_state; } }; } diff --git a/ntester.cpp b/ntester.cpp index 28f23b1..45e383f 100644 --- a/ntester.cpp +++ b/ntester.cpp @@ -1,8 +1,8 @@ #include #include -#include "network.hpp" #include "keystroke.hpp" +#include "networktransport.hpp" int main( int argc, char *argv[] ) { @@ -11,7 +11,9 @@ int main( int argc, char *argv[] ) char *ip; int port; - Network::Connection *n; + KeyStroke user; + + Network::Transport *n; try { if ( argc > 1 ) { @@ -22,9 +24,9 @@ int main( int argc, char *argv[] ) ip = argv[ 2 ]; port = atoi( argv[ 3 ] ); - n = new Network::Connection( key, ip, port ); + n = new Network::Transport( user, key, ip, port ); } else { - n = new Network::Connection(); + n = new Network::Transport( user ); } } catch ( CryptoException e ) { fprintf( stderr, "Fatal error: %s\n", e.text.c_str() ); @@ -34,6 +36,7 @@ int main( int argc, char *argv[] ) fprintf( stderr, "Port bound is %d, key is %s\n", n->port(), n->get_key().c_str() ); if ( server ) { + /* while ( true ) { try { string s = n->recv(); @@ -43,6 +46,8 @@ int main( int argc, char *argv[] ) fprintf( stderr, "Cryptographic error: %s\n", e.text.c_str() ); } } + */ + sleep( 6000 ); } else { struct termios saved_termios; struct termios the_termios; @@ -64,10 +69,10 @@ int main( int argc, char *argv[] ) while( true ) { char x = getchar(); - string prefix = "Key(" + string( &x, 1 ) + ")"; + n->get_current_state().key_hit( x ); try { - n->send( prefix ); + n->tick(); } catch ( Network::NetworkException e ) { fprintf( stderr, "%s: %s\r\n", e.function.c_str(), strerror( e.the_errno ) ); break; diff --git a/templates.cpp b/templates.cpp index 5044399..c2d8575 100644 --- a/templates.cpp +++ b/templates.cpp @@ -24,5 +24,6 @@ template class vector; template class vector; template class map; template class vector; +template class deque; template class Network::Transport;