1 /* 2 Mosh: the mobile shell 3 Copyright 2012 Keith Winstein 4 5 This program is free software: you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation, either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 In addition, as a special exception, the copyright holders give 19 permission to link the code of portions of this program with the 20 OpenSSL library under certain conditions as described in each 21 individual source file, and distribute linked combinations including 22 the two. 23 24 You must obey the GNU General Public License in all respects for all 25 of the code used other than OpenSSL. If you modify file(s) with this 26 exception, you may extend this exception to your version of the 27 file(s), but you are not obligated to do so. If you do not wish to do 28 so, delete this exception statement from your version. If you delete 29 this exception statement from all source files in the program, then 30 also delete it here. 31 */ 32 33 34 #ifndef TRANSPORT_SENDER_HPP 35 #define TRANSPORT_SENDER_HPP 36 37 #include <string> 38 #include <list> 39 40 #include "network.h" 41 #include "transportinstruction.pb.h" 42 #include "transportstate.h" 43 #include "transportfragment.h" 44 #include "prng.h" 45 46 using std::list; 47 using std::pair; 48 using namespace TransportBuffers; 49 50 namespace Network { 51 /* timing parameters */ 52 const int SEND_INTERVAL_MIN = 20; /* ms between frames */ 53 const int SEND_INTERVAL_MAX = 250; /* ms between frames */ 54 const int ACK_INTERVAL = 3000; /* ms between empty acks */ 55 const int ACK_DELAY = 100; /* ms before delayed ack */ 56 const int SHUTDOWN_RETRIES = 16; /* number of shutdown packets to send before giving up */ 57 const int ACTIVE_RETRY_TIMEOUT = 10000; /* attempt to resend at frame rate */ 58 59 template <class MyState> 60 class TransportSender 61 { 62 private: 63 /* helper methods for tick() */ 64 void update_assumed_receiver_state( void ); 65 void attempt_prospective_resend_optimization( string &proposed_diff ); 66 void rationalize_states( void ); 67 void send_to_receiver( const string & diff ); 68 void send_empty_ack( void ); 69 void send_in_fragments( const string & diff, uint64_t new_num ); 70 void add_sent_state( uint64_t the_timestamp, uint64_t num, MyState &state ); 71 72 /* state of sender */ 73 Connection *connection; 74 75 MyState current_state; 76 77 typedef list< TimestampedState<MyState> > sent_states_type; 78 sent_states_type sent_states; 79 /* first element: known, acknowledged receiver state */ 80 /* last element: last sent state */ 81 82 /* somewhere in the middle: the assumed state of the receiver */ 83 typename sent_states_type::iterator assumed_receiver_state; 84 85 /* for fragment creation */ 86 Fragmenter fragmenter; 87 88 /* timing state */ 89 uint64_t next_ack_time; 90 uint64_t next_send_time; 91 92 void calculate_timers( void ); 93 94 unsigned int verbose; 95 bool shutdown_in_progress; 96 int shutdown_tries; 97 uint64_t shutdown_start; 98 99 /* information about receiver state */ 100 uint64_t ack_num; 101 bool pending_data_ack; 102 103 unsigned int SEND_MINDELAY; /* ms to collect all input */ 104 105 uint64_t last_heard; /* last time received new state */ 106 107 /* chaff to disguise instruction length */ 108 PRNG prng; 109 const string make_chaff( void ); 110 111 uint64_t mindelay_clock; /* time of first pending change to current state */ 112 113 public: 114 /* constructor */ 115 TransportSender( Connection *s_connection, MyState &initial_state ); 116 117 /* Send data or an ack if necessary */ 118 void tick( void ); 119 120 /* Returns the number of ms to wait until next possible event. */ 121 int wait_time( void ); 122 123 /* Executed upon receipt of ack */ 124 void process_acknowledgment_through( uint64_t ack_num ); 125 126 /* Executed upon entry to new receiver state */ 127 void set_ack_num( uint64_t s_ack_num ); 128 129 /* Accelerate reply ack */ set_data_ack(void)130 void set_data_ack( void ) { pending_data_ack = true; } 131 132 /* Received something */ remote_heard(uint64_t ts)133 void remote_heard( uint64_t ts ) { last_heard = ts; } 134 135 /* Starts shutdown sequence */ start_shutdown(void)136 void start_shutdown( void ) { if ( !shutdown_in_progress ) { shutdown_start = timestamp(); shutdown_in_progress = true; } } 137 138 /* Misc. getters and setters */ 139 /* Cannot modify current_state while shutdown in progress */ get_current_state(void)140 MyState &get_current_state( void ) { assert( !shutdown_in_progress ); return current_state; } set_current_state(const MyState & x)141 void set_current_state( const MyState &x ) 142 { 143 assert( !shutdown_in_progress ); 144 current_state = x; 145 current_state.reset_input(); 146 } set_verbose(unsigned int s_verbose)147 void set_verbose( unsigned int s_verbose ) { verbose = s_verbose; } 148 get_shutdown_in_progress(void)149 bool get_shutdown_in_progress( void ) const { return shutdown_in_progress; } get_shutdown_acknowledged(void)150 bool get_shutdown_acknowledged( void ) const { return sent_states.front().num == uint64_t(-1); } get_counterparty_shutdown_acknowledged(void)151 bool get_counterparty_shutdown_acknowledged( void ) const { return fragmenter.last_ack_sent() == uint64_t(-1); } get_sent_state_acked_timestamp(void)152 uint64_t get_sent_state_acked_timestamp( void ) const { return sent_states.front().timestamp; } get_sent_state_acked(void)153 uint64_t get_sent_state_acked( void ) const { return sent_states.front().num; } get_sent_state_last(void)154 uint64_t get_sent_state_last( void ) const { return sent_states.back().num; } 155 156 bool shutdown_ack_timed_out( void ) const; 157 set_send_delay(int new_delay)158 void set_send_delay( int new_delay ) { SEND_MINDELAY = new_delay; } 159 160 unsigned int send_interval( void ) const; 161 162 /* nonexistent methods to satisfy -Weffc++ */ 163 TransportSender( const TransportSender &x ); 164 TransportSender & operator=( const TransportSender &x ); 165 }; 166 } 167 168 #endif 169