| 136 | |
| 137 | |
| 138 | void message_oriented_connection_impl::read_loop() |
| 139 | { |
| 140 | VERIFY_CORRECT_THREAD(); |
| 141 | const int BUFFER_SIZE = 16; |
| 142 | const int LEFTOVER = BUFFER_SIZE - sizeof(message_header); |
| 143 | static_assert(BUFFER_SIZE >= sizeof(message_header), "insufficient buffer"); |
| 144 | |
| 145 | _connected_time = fc::time_point::now(); |
| 146 | |
| 147 | fc::oexception exception_to_rethrow; |
| 148 | bool call_on_connection_closed = false; |
| 149 | |
| 150 | try |
| 151 | { |
| 152 | message m; |
| 153 | while( true ) |
| 154 | { |
| 155 | char buffer[BUFFER_SIZE]; |
| 156 | _sock.read(buffer, BUFFER_SIZE); |
| 157 | _bytes_received += BUFFER_SIZE; |
| 158 | memcpy((char*)&m, buffer, sizeof(message_header)); |
| 159 | |
| 160 | FC_ASSERT( m.size <= MAX_MESSAGE_SIZE, "", ("m.size",m.size)("MAX_MESSAGE_SIZE",MAX_MESSAGE_SIZE) ); |
| 161 | |
| 162 | size_t remaining_bytes_with_padding = 16 * ((m.size - LEFTOVER + 15) / 16); |
| 163 | m.data.resize(LEFTOVER + remaining_bytes_with_padding); //give extra 16 bytes to allow for padding added in send call |
| 164 | std::copy(buffer + sizeof(message_header), buffer + sizeof(buffer), m.data.begin()); |
| 165 | if (remaining_bytes_with_padding) |
| 166 | { |
| 167 | _sock.read(&m.data[LEFTOVER], remaining_bytes_with_padding); |
| 168 | _bytes_received += remaining_bytes_with_padding; |
| 169 | } |
| 170 | m.data.resize(m.size); // truncate off the padding bytes |
| 171 | |
| 172 | _last_message_received_time = fc::time_point::now(); |
| 173 | |
| 174 | try |
| 175 | { |
| 176 | // message handling errors are warnings... |
| 177 | _delegate->on_message(_self, m); |
| 178 | } |
| 179 | /// Dedicated catches needed to distinguish from general fc::exception |
| 180 | catch ( const fc::canceled_exception& e ) { throw e; } |
| 181 | catch ( const fc::eof_exception& e ) { throw e; } |
| 182 | catch ( const fc::exception& e) |
| 183 | { |
| 184 | /// Here loop should be continued so exception should be just caught locally. |
| 185 | wlog( "message transmission failed ${er}", ("er", e.to_detail_string() ) ); |
| 186 | throw; |
| 187 | } |
| 188 | } |
| 189 | } |
| 190 | catch ( const fc::canceled_exception& e ) |
| 191 | { |
| 192 | wlog( "caught a canceled_exception in read_loop. this should mean we're in the process of deleting this object already, so there's no need to notify the delegate: ${e}", ("e", e.to_detail_string() ) ); |
| 193 | throw; |
| 194 | } |
| 195 | catch ( const fc::eof_exception& e ) |
nothing calls this directly
no test coverage detected