Called for each incoming RESOURCE-context packet on the receiver side. Looks the packet up in the in-flight window via its map_hash, files it into parts[], and either kicks off assemble() when all parts have arrived or requests the next window. Mirror Python Resource.py:828. */
| 832 | requests the next window. Mirror Python Resource.py:828. |
| 833 | */ |
| 834 | void Resource::receive_part(const Packet& packet) { |
| 835 | TRACE("Resource::receive_part: Received resource part"); |
| 836 | assert(_object); |
| 837 | if (_object->_receive_lock) return; |
| 838 | _object->_receive_lock = true; |
| 839 | |
| 840 | _object->_receiving_part = true; |
| 841 | _object->_last_activity = Utilities::OS::time(); |
| 842 | _object->_retries_left = _object->_max_retries; |
| 843 | |
| 844 | if (_object->_req_resp == 0.0) { |
| 845 | _object->_req_resp = _object->_last_activity; |
| 846 | const double rtt = _object->_req_resp - _object->_req_sent; |
| 847 | |
| 848 | _object->_part_timeout_factor = Type::Resource::PART_TIMEOUT_FACTOR_AFTER_RTT; |
| 849 | if (_object->_rtt == 0.0) { |
| 850 | _object->_rtt = _object->_link.rtt(); |
| 851 | watchdog_job(); |
| 852 | } |
| 853 | else if (rtt < _object->_rtt) { |
| 854 | _object->_rtt = std::max(_object->_rtt - _object->_rtt * 0.05, rtt); |
| 855 | } |
| 856 | else if (rtt > _object->_rtt) { |
| 857 | _object->_rtt = std::min(_object->_rtt + _object->_rtt * 0.05, rtt); |
| 858 | } |
| 859 | |
| 860 | if (rtt > 0) { |
| 861 | const double req_resp_cost = static_cast<double>(packet.raw().size() + _object->_req_sent_bytes); |
| 862 | _object->_req_resp_rtt_rate = req_resp_cost / rtt; |
| 863 | |
| 864 | if (_object->_req_resp_rtt_rate > Type::Resource::RATE_FAST |
| 865 | && _object->_fast_rate_rounds < Type::Resource::FAST_RATE_THRESHOLD) { |
| 866 | _object->_fast_rate_rounds++; |
| 867 | if (_object->_fast_rate_rounds == Type::Resource::FAST_RATE_THRESHOLD) { |
| 868 | _object->_window_max = Type::Resource::WINDOW_MAX_FAST; |
| 869 | } |
| 870 | } |
| 871 | } |
| 872 | } |
| 873 | |
| 874 | if (_object->_status == Type::Resource::FAILED) { |
| 875 | _object->_receiving_part = false; |
| 876 | _object->_receive_lock = false; |
| 877 | return; |
| 878 | } |
| 879 | |
| 880 | _object->_status = Type::Resource::TRANSFERRING; |
| 881 | const Bytes part_data = packet.data(); |
| 882 | const Bytes part_hash = get_map_hash(part_data); |
| 883 | |
| 884 | const int32_t cci = (_object->_consecutive_completed_height >= 0) ? _object->_consecutive_completed_height : 0; |
| 885 | const size_t maphash_len = Type::Resource::MAPHASH_LEN; |
| 886 | int32_t i = cci; |
| 887 | const size_t window_end = std::min(static_cast<size_t>(cci) + _object->_window, |
| 888 | static_cast<size_t>(_object->_total_parts)); |
| 889 | |
| 890 | for (size_t j = static_cast<size_t>(cci); j < window_end; ++j) { |
| 891 | Bytes map_hash_j = _object->_hashmap.mid(j * maphash_len, maphash_len); |