| 676 | #undef X |
| 677 | |
| 678 | bool CNode::ReceiveMsgBytes(Span<const uint8_t> msg_bytes, bool& complete) |
| 679 | { |
| 680 | complete = false; |
| 681 | const auto time = GetTime<std::chrono::microseconds>(); |
| 682 | LOCK(cs_vRecv); |
| 683 | m_last_recv = std::chrono::duration_cast<std::chrono::seconds>(time); |
| 684 | nRecvBytes += msg_bytes.size(); |
| 685 | while (msg_bytes.size() > 0) { |
| 686 | // absorb network data |
| 687 | int handled = m_deserializer->Read(msg_bytes); |
| 688 | if (handled < 0) { |
| 689 | // Serious header problem, disconnect from the peer. |
| 690 | return false; |
| 691 | } |
| 692 | |
| 693 | if (m_deserializer->Complete()) { |
| 694 | // decompose a transport agnostic CNetMessage from the deserializer |
| 695 | bool reject_message{false}; |
| 696 | CNetMessage msg = m_deserializer->GetMessage(time, reject_message); |
| 697 | if (reject_message) { |
| 698 | // Message deserialization failed. Drop the message but don't disconnect the peer. |
| 699 | // store the size of the corrupt message |
| 700 | mapRecvBytesPerMsgCmd.at(NET_MESSAGE_COMMAND_OTHER) += msg.m_raw_message_size; |
| 701 | continue; |
| 702 | } |
| 703 | |
| 704 | // Store received bytes per message command |
| 705 | // to prevent a memory DOS, only allow valid commands |
| 706 | auto i = mapRecvBytesPerMsgCmd.find(msg.m_type); |
| 707 | if (i == mapRecvBytesPerMsgCmd.end()) { |
| 708 | i = mapRecvBytesPerMsgCmd.find(NET_MESSAGE_COMMAND_OTHER); |
| 709 | } |
| 710 | assert(i != mapRecvBytesPerMsgCmd.end()); |
| 711 | i->second += msg.m_raw_message_size; |
| 712 | |
| 713 | // push the message to the process queue, |
| 714 | vRecvMsg.push_back(std::move(msg)); |
| 715 | |
| 716 | complete = true; |
| 717 | } |
| 718 | } |
| 719 | |
| 720 | return true; |
| 721 | } |
| 722 | |
| 723 | int V1TransportDeserializer::readHeader(Span<const uint8_t> msg_bytes) |
| 724 | { |