Clean out some bugs in sender
This commit is contained in:
@@ -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
|
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
|
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
|
repos = templates.rpo
|
||||||
executables = parse termemu ntester encrypt decrypt
|
executables = parse termemu ntester encrypt decrypt
|
||||||
|
|
||||||
CXX = g++
|
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
|
LIBS = -lutil -lssl -lrt
|
||||||
|
|
||||||
all: $(executables)
|
all: $(executables)
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "keystroke.hpp"
|
||||||
|
|
||||||
|
void KeyStroke::subtract( KeyStroke * const prefix )
|
||||||
|
{
|
||||||
|
for ( deque<char>::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<char>::iterator my_it = user_bytes.begin();
|
||||||
|
|
||||||
|
for ( deque<char>::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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
+12
-4
@@ -1,6 +1,7 @@
|
|||||||
#ifndef KEYSTROKE_HPP
|
#ifndef KEYSTROKE_HPP
|
||||||
#define KEYSTROKE_HPP
|
#define KEYSTROKE_HPP
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
@@ -9,10 +10,17 @@ using namespace std;
|
|||||||
class KeyStroke
|
class KeyStroke
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void subtract( KeyStroke * const ) {}
|
deque<char> user_bytes;
|
||||||
string diff_from( KeyStroke const &, int ) { return ""; }
|
|
||||||
void apply_string( string ) {}
|
KeyStroke() : user_bytes() {}
|
||||||
bool operator==( KeyStroke const & ) const { return true; }
|
|
||||||
|
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
|
#endif
|
||||||
|
|||||||
+1
-1
@@ -30,7 +30,7 @@ string Packet::tostring( Session *session )
|
|||||||
{
|
{
|
||||||
uint64_t direction_seq = (uint64_t( direction == TO_CLIENT ) << 63) | (seq & 0x7FFFFFFFFFFFFFFF);
|
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 )
|
Packet Connection::new_packet( string &s_payload )
|
||||||
|
|||||||
+2
-1
@@ -76,8 +76,9 @@ namespace Network {
|
|||||||
void send( string &s );
|
void send( string &s );
|
||||||
string recv( void );
|
string recv( void );
|
||||||
int fd( void ) { return sock; }
|
int fd( void ) { return sock; }
|
||||||
int port( void );
|
|
||||||
int get_MTU( void ) { return MTU; }
|
int get_MTU( void ) { return MTU; }
|
||||||
|
|
||||||
|
int port( void );
|
||||||
string get_key( void ) { return key.printable_key(); }
|
string get_key( void ) { return key.printable_key(); }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
#include <endian.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
+35
-25
@@ -1,4 +1,5 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include "networktransport.hpp"
|
#include "networktransport.hpp"
|
||||||
|
|
||||||
@@ -47,20 +48,16 @@ Transport<MyState, RemoteState>::Transport( MyState &initial_state,
|
|||||||
/* client */
|
/* client */
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class MyState, class RemoteState>
|
|
||||||
void Transport<MyState, RemoteState>::new_state( MyState &s )
|
|
||||||
{
|
|
||||||
current_state = s;
|
|
||||||
|
|
||||||
tick();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class MyState, class RemoteState>
|
template <class MyState, class RemoteState>
|
||||||
void Transport<MyState, RemoteState>::tick( void )
|
void Transport<MyState, RemoteState>::tick( void )
|
||||||
{
|
{
|
||||||
/* Update assumed receiver state */
|
/* Update assumed receiver state */
|
||||||
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 */
|
/* Cut out common prefix of all states */
|
||||||
rationalize_states();
|
rationalize_states();
|
||||||
|
|
||||||
@@ -74,20 +71,6 @@ void Transport<MyState, RemoteState>::tick( void )
|
|||||||
template <class MyState, class RemoteState>
|
template <class MyState, class RemoteState>
|
||||||
void Transport<MyState, RemoteState>::send_to_receiver( void )
|
void Transport<MyState, RemoteState>::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
|
/* We don't want to assume that this sequence of diffs will
|
||||||
necessarily bring the receiver to the _actual_ current
|
necessarily bring the receiver to the _actual_ current
|
||||||
state. That requires perfect round-trip stability of the diff
|
state. That requires perfect round-trip stability of the diff
|
||||||
@@ -101,11 +84,31 @@ void Transport<MyState, RemoteState>::send_to_receiver( void )
|
|||||||
MyState target_receiver_state( assumed_receiver_state->state );
|
MyState target_receiver_state( assumed_receiver_state->state );
|
||||||
target_receiver_state.apply_string( current_state.diff_from( target_receiver_state, -1 ) );
|
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) ) {
|
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,
|
current_state.diff_from( assumed_receiver_state->state,
|
||||||
connection.get_MTU() - HEADER_LEN ),
|
connection.get_MTU() - HEADER_LEN ) );
|
||||||
highest_state_received );
|
|
||||||
MyState new_state = assumed_receiver_state->state;
|
MyState new_state = assumed_receiver_state->state;
|
||||||
new_state.apply_string( inst.diff );
|
new_state.apply_string( inst.diff );
|
||||||
|
|
||||||
@@ -133,6 +136,11 @@ void Transport<MyState, RemoteState>::send_to_receiver( void )
|
|||||||
string s = inst.tostring();
|
string s = inst.tostring();
|
||||||
|
|
||||||
try {
|
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 );
|
connection.send( s );
|
||||||
} catch ( MTUException m ) {
|
} catch ( MTUException m ) {
|
||||||
continue;
|
continue;
|
||||||
@@ -174,4 +182,6 @@ void Transport<MyState, RemoteState>::rationalize_states( void )
|
|||||||
i++ ) {
|
i++ ) {
|
||||||
i->state.subtract( known_receiver_state );
|
i->state.subtract( known_receiver_state );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
current_state.subtract( known_receiver_state );
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-6
@@ -15,15 +15,15 @@ namespace Network {
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
uint64_t old_num, new_num;
|
uint64_t old_num, new_num;
|
||||||
string diff;
|
|
||||||
|
|
||||||
uint64_t ack_num;
|
uint64_t ack_num;
|
||||||
|
|
||||||
Instruction( uint64_t s_old_num, uint64_t s_new_num, string s_diff, uint64_t s_ack_num )
|
string diff;
|
||||||
: old_num( s_old_num ), new_num( s_new_num ), diff( s_diff ), ack_num( s_ack_num )
|
|
||||||
|
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 <class State>
|
template <class State>
|
||||||
@@ -76,8 +76,12 @@ namespace Network {
|
|||||||
Transport( MyState &initial_state );
|
Transport( MyState &initial_state );
|
||||||
Transport( MyState &initial_state, const char *key_str, const char *ip, int port );
|
Transport( MyState &initial_state, const char *key_str, const char *ip, int port );
|
||||||
|
|
||||||
void new_state( MyState &s );
|
|
||||||
void tick( void );
|
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; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-6
@@ -1,8 +1,8 @@
|
|||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "network.hpp"
|
|
||||||
#include "keystroke.hpp"
|
#include "keystroke.hpp"
|
||||||
|
#include "networktransport.hpp"
|
||||||
|
|
||||||
int main( int argc, char *argv[] )
|
int main( int argc, char *argv[] )
|
||||||
{
|
{
|
||||||
@@ -11,7 +11,9 @@ int main( int argc, char *argv[] )
|
|||||||
char *ip;
|
char *ip;
|
||||||
int port;
|
int port;
|
||||||
|
|
||||||
Network::Connection *n;
|
KeyStroke user;
|
||||||
|
|
||||||
|
Network::Transport<KeyStroke, KeyStroke> *n;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if ( argc > 1 ) {
|
if ( argc > 1 ) {
|
||||||
@@ -22,9 +24,9 @@ int main( int argc, char *argv[] )
|
|||||||
ip = argv[ 2 ];
|
ip = argv[ 2 ];
|
||||||
port = atoi( argv[ 3 ] );
|
port = atoi( argv[ 3 ] );
|
||||||
|
|
||||||
n = new Network::Connection( key, ip, port );
|
n = new Network::Transport<KeyStroke, KeyStroke>( user, key, ip, port );
|
||||||
} else {
|
} else {
|
||||||
n = new Network::Connection();
|
n = new Network::Transport<KeyStroke, KeyStroke>( user );
|
||||||
}
|
}
|
||||||
} catch ( CryptoException e ) {
|
} catch ( CryptoException e ) {
|
||||||
fprintf( stderr, "Fatal error: %s\n", e.text.c_str() );
|
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() );
|
fprintf( stderr, "Port bound is %d, key is %s\n", n->port(), n->get_key().c_str() );
|
||||||
|
|
||||||
if ( server ) {
|
if ( server ) {
|
||||||
|
/*
|
||||||
while ( true ) {
|
while ( true ) {
|
||||||
try {
|
try {
|
||||||
string s = n->recv();
|
string s = n->recv();
|
||||||
@@ -43,6 +46,8 @@ int main( int argc, char *argv[] )
|
|||||||
fprintf( stderr, "Cryptographic error: %s\n", e.text.c_str() );
|
fprintf( stderr, "Cryptographic error: %s\n", e.text.c_str() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
sleep( 6000 );
|
||||||
} else {
|
} else {
|
||||||
struct termios saved_termios;
|
struct termios saved_termios;
|
||||||
struct termios the_termios;
|
struct termios the_termios;
|
||||||
@@ -64,10 +69,10 @@ int main( int argc, char *argv[] )
|
|||||||
while( true ) {
|
while( true ) {
|
||||||
char x = getchar();
|
char x = getchar();
|
||||||
|
|
||||||
string prefix = "Key(" + string( &x, 1 ) + ")";
|
n->get_current_state().key_hit( x );
|
||||||
|
|
||||||
try {
|
try {
|
||||||
n->send( prefix );
|
n->tick();
|
||||||
} catch ( Network::NetworkException e ) {
|
} catch ( Network::NetworkException e ) {
|
||||||
fprintf( stderr, "%s: %s\r\n", e.function.c_str(), strerror( e.the_errno ) );
|
fprintf( stderr, "%s: %s\r\n", e.function.c_str(), strerror( e.the_errno ) );
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -24,5 +24,6 @@ template class vector<wchar_t>;
|
|||||||
template class vector<int>;
|
template class vector<int>;
|
||||||
template class map<string, Function>;
|
template class map<string, Function>;
|
||||||
template class vector<bool>;
|
template class vector<bool>;
|
||||||
|
template class deque<char>;
|
||||||
|
|
||||||
template class Network::Transport<KeyStroke, KeyStroke>;
|
template class Network::Transport<KeyStroke, KeyStroke>;
|
||||||
|
|||||||
Reference in New Issue
Block a user