| 38 | max_message_length_(_max_message_length), buffer_shrink_threshold_(_buffer_shrink_threshold), mem_(initial_buffer_size_) { } |
| 39 | |
| 40 | bool local_receive_buffer::next_message(next_message_result& _result) { |
| 41 | uint32_t length = 0; |
| 42 | if (size_t bytes = end_ - start_; bytes >= protocol::COMMAND_POSITION_SIZE + sizeof(length)) { |
| 43 | memcpy(&length, &mem_[start_] + protocol::COMMAND_POSITION_SIZE, sizeof(length)); |
| 44 | if (length > max_message_length_) { |
| 45 | VSOMEIP_ERROR_P << "Message length: " << length << " exceeded allowed max message size"; |
| 46 | VSOMEIP_ERROR_P << "Message: " << utility::dump(&mem_[start_], bytes); |
| 47 | if (start_ > 0) { |
| 48 | auto const previous = start_ > 512 ? start_ - 512 : 0; |
| 49 | VSOMEIP_ERROR_P << "Previous Message: " << utility::dump(&mem_[previous], start_ - previous); |
| 50 | } |
| 51 | |
| 52 | _result.set_error(); |
| 53 | return false; |
| 54 | } |
| 55 | auto const size = length + protocol::COMMAND_HEADER_SIZE; |
| 56 | if (size > bytes) { |
| 57 | if (size > mem_.size()) { |
| 58 | // capacity is only missing if the shifted buffer is not sufficient |
| 59 | if (!add_capacity(size - mem_.size())) { |
| 60 | _result.set_error(); |
| 61 | return false; |
| 62 | } |
| 63 | } |
| 64 | _result.clear(); |
| 65 | return false; |
| 66 | } |
| 67 | if (size <= std::numeric_limits<uint32_t>::max()) { |
| 68 | _result.set_message(&mem_[start_], static_cast<uint32_t>(size)); |
| 69 | start_ += size; |
| 70 | // Shrink heuristic: Only shrink if we're consistently processing small messages. |
| 71 | // Large messages (> capacity/2) indicate we might need the extra space, |
| 72 | // so reset the counter. Small messages increment it, and when the threshold |
| 73 | // is reached, we shrink back to the initial size (happens in the next call |
| 74 | // when buffer is empty). |
| 75 | if (size > mem_.capacity() / 2) { |
| 76 | shrink_ct_ = 0; // Large message - don't shrink yet |
| 77 | } else { |
| 78 | shrink_ct_++; // Small message - increment shrink counter |
| 79 | } |
| 80 | return true; |
| 81 | } |
| 82 | VSOMEIP_ERROR_P << "Message size: " << size << " exceeded numerical limits"; |
| 83 | _result.set_error(); |
| 84 | return false; |
| 85 | } |
| 86 | if (auto const free_bytes = mem_.size() - (end_ - start_); free_bytes < protocol::COMMAND_POSITION_SIZE + sizeof(length)) { |
| 87 | // only capacity missing, if the shifted buffer is not sufficient |
| 88 | if (!add_capacity(protocol::COMMAND_POSITION_SIZE + sizeof(length) - free_bytes)) { |
| 89 | _result.set_error(); |
| 90 | return false; |
| 91 | } |
| 92 | } else if (end_ == start_ && buffer_shrink_threshold_ > 0 && shrink_ct_ >= buffer_shrink_threshold_ |
| 93 | && mem_.size() > initial_buffer_size_) { |
| 94 | shrink(); |
| 95 | } |
| 96 | _result.clear(); |
| 97 | return false; |
no test coverage detected