| 1748 | } |
| 1749 | |
| 1750 | static ReliablePacket* sendPacket(TransportData* self, |
| 1751 | Reference<Peer> peer, |
| 1752 | ISerializeSource const& what, |
| 1753 | const Endpoint& destination, |
| 1754 | bool reliable) { |
| 1755 | const bool checksumEnabled = !destination.getPrimaryAddress().isTLS(); |
| 1756 | ++self->countPacketsGenerated; |
| 1757 | |
| 1758 | // If there isn't an open connection, a public address, or the peer isn't compatible, we can't send |
| 1759 | if (!peer || (peer->outgoingConnectionIdle && !destination.getPrimaryAddress().isPublic()) || |
| 1760 | (!peer->compatible && destination.token != Endpoint::wellKnownToken(WLTOKEN_PING_PACKET))) { |
| 1761 | CODE_PROBE(true, "Can't send to private address without a compatible open connection"); |
| 1762 | return nullptr; |
| 1763 | } |
| 1764 | |
| 1765 | bool firstUnsent = peer->unsent.empty(); |
| 1766 | |
| 1767 | PacketBuffer* pb = peer->unsent.getWriteBuffer(); |
| 1768 | ReliablePacket* rp = reliable ? new ReliablePacket : 0; |
| 1769 | |
| 1770 | int prevBytesWritten = pb->bytes_written; |
| 1771 | PacketBuffer* checksumPb = pb; |
| 1772 | |
| 1773 | PacketWriter wr(pb, |
| 1774 | rp, |
| 1775 | AssumeVersion(g_network->protocolVersion())); // SOMEDAY: Can we downgrade to talk to older peers? |
| 1776 | |
| 1777 | // Reserve some space for packet length and checksum, write them after serializing data |
| 1778 | SplitBuffer packetInfoBuffer; |
| 1779 | uint32_t len; |
| 1780 | |
| 1781 | // This is technically abstraction breaking but avoids XXH3_createState() and XXH3_freeState() which are just |
| 1782 | // malloc/free |
| 1783 | XXH3_state_t checksumState; |
| 1784 | // Checksum will be calculated with buffer API if contiguous, else using stream API. Mode is tracked here. |
| 1785 | bool checksumStream = false; |
| 1786 | XXH64_hash_t checksum; |
| 1787 | |
| 1788 | int packetInfoSize = PACKET_LEN_WIDTH; |
| 1789 | if (checksumEnabled) { |
| 1790 | packetInfoSize += sizeof(checksum); |
| 1791 | } |
| 1792 | |
| 1793 | wr.writeAhead(packetInfoSize, &packetInfoBuffer); |
| 1794 | wr << destination.token; |
| 1795 | what.serializePacketWriter(wr); |
| 1796 | pb = wr.finish(); |
| 1797 | len = wr.size() - packetInfoSize; |
| 1798 | |
| 1799 | if (checksumEnabled) { |
| 1800 | // Find the correct place to start calculating checksum |
| 1801 | uint32_t checksumUnprocessedLength = len; |
| 1802 | prevBytesWritten += packetInfoSize; |
| 1803 | if (prevBytesWritten >= checksumPb->bytes_written) { |
| 1804 | prevBytesWritten -= checksumPb->bytes_written; |
| 1805 | checksumPb = checksumPb->nextPacketBuffer(); |
| 1806 | } |
| 1807 |
no test coverage detected