Line data Source code
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 : namespace Network { 47 : using std::list; 48 : using std::pair; 49 : using namespace TransportBuffers; 50 : 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 */ 130 3659 : void set_data_ack( void ) { pending_data_ack = true; } 131 : 132 : /* Received something */ 133 5109 : void remote_heard( uint64_t ts ) { last_heard = ts; } 134 : 135 : /* Starts shutdown sequence */ 136 452 : 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 */ 140 1675 : MyState &get_current_state( void ) { assert( !shutdown_in_progress ); return current_state; } 141 23153 : void set_current_state( const MyState &x ) 142 : { 143 23153 : assert( !shutdown_in_progress ); 144 23153 : current_state = x; 145 23153 : current_state.reset_input(); 146 23153 : } 147 900 : void set_verbose( unsigned int s_verbose ) { verbose = s_verbose; } 148 : 149 117685 : bool get_shutdown_in_progress( void ) const { return shutdown_in_progress; } 150 1473 : bool get_shutdown_acknowledged( void ) const { return sent_states.front().num == uint64_t(-1); } 151 32680 : bool get_counterparty_shutdown_acknowledged( void ) const { return fragmenter.last_ack_sent() == uint64_t(-1); } 152 8614 : uint64_t get_sent_state_acked_timestamp( void ) const { return sent_states.front().timestamp; } 153 3333 : uint64_t get_sent_state_acked( void ) const { return sent_states.front().num; } 154 659 : uint64_t get_sent_state_last( void ) const { return sent_states.back().num; } 155 : 156 : bool shutdown_ack_timed_out( void ) const; 157 : 158 448 : 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