diff options
| author | bitflash-maintainer <noreply@bitflash.invalid> | 2026-09-05 22:46:52 +0000 |
|---|---|---|
| committer | bitflash-maintainer <noreply@bitflash.invalid> | 2026-09-05 22:46:52 +0000 |
| commit | ceae3d076b5ad11ee84729ae43f14e9312896646 (patch) | |
| tree | 7e9132aa871fdc01cb95268d2f5ea3bb11853ddf /src/net.h | |
| parent | be63e83d79e7e00e6b8ca889a70e6a19886aa1d8 (diff) | |
| parent | 66e0b9158d050c46b1ff2509faeee3f4573cac1c (diff) | |
Bring main onto the line this project actually ships
main had drifted to a history with no ancestor in common with the tree we
build and deploy. It sat at be63e83 (2026-08-09) with 28 commits; the shipped
line, deploy/soak-2026-08-21, had 383. The two shared nothing -- git
merge-base returns no result at all -- so anyone cloning this repository
landed on a default branch that was neither current nor related to the
running node.
The 28 commits on main were audited before this merge: every one is already
present in the tree by content, including the two that are hardest to see
because they were rewritten afterwards -- the payout reorg-safety work
(PayoutBlockStillOnChain, since evolved to re-check on every retry rather
than once at maturity) and the nostr relay certificate verification
(SSL_set1_host, now with a Windows root-store path). Nothing on main is lost
by this merge.
Recorded as a merge rather than a force-push: main only ever moves forward,
its old history stays reachable as the first parent, and this is revertible.
The tree is taken wholesale from the merged branch, so main's content is now
exactly what was built and tested.
What this brings onto main:
- compactblock: BIP152-style compact block relay ported from upstream 1.2.23,
primitives and unit test only, with the RAND_bytes failure path closed and
the reconstruction allocation bounded.
- upstream/main 17741d9: isolated testnet parameters and genesis, optional
2 MB large pages for RandomX. Mainnet genesis verified byte-identical
through upstream's BuildGenesisBlock() refactor.
- deploy: every image built on bookworm so binaries run on Debian 12, and the
container build now honours the RandomX and libsecp256k1 pins it had been
silently ignoring since before 1.2.15.
Gates at this tree: 15/15 selftests, compactblock's 17 checks, consensus
constants unchanged against e4f898c apart from the pre-existing
MAX_BLOCK_SIZE_GEN, mainnet genesis intact, money-log check ok.
Diffstat (limited to 'src/net.h')
| -rw-r--r-- | src/net.h | 150 |
1 files changed, 117 insertions, 33 deletions
| @@ -12,7 +12,13 @@ class CBlockIndex; | |||
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | 14 | ||
| 15 | static const unsigned short DEFAULT_PORT = htons(8433); | 15 | // Held in host byte order, unlike the DEFAULT_PORT constant these replace, |
| 16 | // which was htons(8433). Nothing is lost: net.cpp's GetDefaultPort() applies | ||
| 17 | // htons() itself and is what every caller now uses, so the value that reaches | ||
| 18 | // a sockaddr is byte-for-byte what it was. Mainnet stays on 8433. | ||
| 19 | static const unsigned short MAINNET_PORT = 8433; | ||
| 20 | static const unsigned short TESTNET_PORT = 18433; | ||
| 21 | static const unsigned int PUBLISH_HOPS = 5; | ||
| 16 | enum | 22 | enum |
| 17 | { | 23 | { |
| 18 | NODE_NETWORK = (1 << 0), | 24 | NODE_NETWORK = (1 << 0), |
| @@ -23,13 +29,24 @@ enum | |||
| 23 | 29 | ||
| 24 | 30 | ||
| 25 | 31 | ||
| 32 | // Defined in main.cpp. True while this node is tracking the tip rather than | ||
| 33 | // still catching up, measured off the age of our own best block -- see there | ||
| 34 | // for why that and not a peer-reported height. Declared here because net.h is | ||
| 35 | // parsed before main.h and CNode::AskFor needs it. | ||
| 36 | bool IsBlockFetchNearTip(); | ||
| 37 | |||
| 26 | bool GetMyExternalIP(unsigned int& ipRet); | 38 | bool GetMyExternalIP(unsigned int& ipRet); |
| 39 | bool IsTestNet(); | ||
| 40 | unsigned short GetDefaultPort(); | ||
| 41 | void SelectNetworkParams(bool fTestNetIn); | ||
| 27 | CNode* ConnectNodeBtf(const string& strBtfAddr); | 42 | CNode* ConnectNodeBtf(const string& strBtfAddr); |
| 28 | CNode* ConnectNodeBtfResolved(const string& strBtfAddr, const string& strMeeting, | 43 | CNode* ConnectNodeBtfResolved(const string& strBtfAddr, const string& strMeeting, |
| 29 | const unsigned char enc_pub[32]); | 44 | const string& strOnion, const unsigned char enc_pub[32], |
| 45 | const string& strDesc=string()); | ||
| 30 | void ThreadBtfAccept(void* parg); | 46 | void ThreadBtfAccept(void* parg); |
| 31 | void ThreadBtfConnect(void* parg); | 47 | void ThreadBtfConnect(void* parg); |
| 32 | extern string strBtfConnect; | 48 | extern string strBtfConnect; |
| 49 | extern bool fBtfOnionOnly; | ||
| 33 | // Bootstrap seeds added at runtime with /btfseed=ADDRESS:ENCHEX (repeatable). | 50 | // Bootstrap seeds added at runtime with /btfseed=ADDRESS:ENCHEX (repeatable). |
| 34 | // The compiled-in list lives in net.cpp; these are appended to it. | 51 | // The compiled-in list lives in net.cpp; these are appended to it. |
| 35 | extern std::vector<std::pair<std::string, std::string> > vBtfExtraSeeds; | 52 | extern std::vector<std::pair<std::string, std::string> > vBtfExtraSeeds; |
| @@ -87,30 +104,52 @@ static const int BTF_RECV_TIMEOUT_SECS = 30 * 60; | |||
| 87 | static const int BTF_SEND_STALL_SECS = 10 * 60; | 104 | static const int BTF_SEND_STALL_SECS = 10 * 60; |
| 88 | static const int BTF_HANDSHAKE_GRACE_SECS = 60; | 105 | static const int BTF_HANDSHAKE_GRACE_SECS = 60; |
| 89 | 106 | ||
| 107 | // How long a requested block gets before it is asked for again, in seconds. | ||
| 108 | // Used twice: CNode::AskFor spaces the queued per-announcer block retries this | ||
| 109 | // far apart instead of the two minutes transactions get, and the failover | ||
| 110 | // sweep in main.cpp re-issues a getdata to a different peer once a sent | ||
| 111 | // request has gone unanswered this long. A block body is at most 1 MB and | ||
| 112 | // somebody demonstrably has it -- they announced it -- so on this timescale | ||
| 113 | // "not here yet" means "not coming from that peer", not "still in transit". | ||
| 114 | static const int BLOCK_FETCH_RETRY_SECS = 15; | ||
| 115 | |||
| 90 | // A serialized object cannot be larger than MAX_SIZE, so no valid network | 116 | // A serialized object cannot be larger than MAX_SIZE, so no valid network |
| 91 | // message needs the old 256 MB header allowance. Keep the wire cap aligned with | 117 | // message needs the old 256 MB header allowance. Keep the wire cap aligned with |
| 92 | // what the deserializer can accept and bound how long one peer may sit on a | 118 | // what the deserializer can accept. How long a peer may sit on a partial |
| 93 | // partial payload after a complete header has arrived. | 119 | // payload after a complete header has arrived is BTF_MSG_WAIT_MAX_SECS, below. |
| 94 | static const unsigned int MAX_PROTOCOL_MESSAGE_SIZE = MAX_SIZE; | 120 | static const unsigned int MAX_PROTOCOL_MESSAGE_SIZE = MAX_SIZE; |
| 95 | static const int BTF_INCOMPLETE_MESSAGE_TIMEOUT_SECS = 2 * 60; | ||
| 96 | 121 | ||
| 97 | // Ceiling on simultaneous connections. | 122 | // Ceiling on simultaneous connections. |
| 98 | // | 123 | // |
| 99 | // ThreadSocketHandler watches every peer through one select(), and select() | 124 | // ThreadSocketHandler watches every peer in one socket loop. This used to be a |
| 100 | // cannot watch more descriptors than FD_SETSIZE. On Windows FD_SET simply | 125 | // select() loop, which made FD_SETSIZE the real limit and silently starved |
| 101 | // stops adding once the set is full -- no error, no log -- so every socket | 126 | // sockets past that bitmap. It is now poll()/WSAPoll(), so the ceiling below is |
| 102 | // past the limit stays open and is never read again. Nothing capped vNodes, | 127 | // a deliberate resource bound rather than a descriptor-set accident. |
| 103 | // so a node accepted connections it had no way to service, and because new | ||
| 104 | // entries go on the end of vNodes it was always the newest connection that | ||
| 105 | // starved, including the ones dialed to fix connectivity. | ||
| 106 | // | 128 | // |
| 107 | // Measured on two nodes before this ceiling existed: 277 and 90 CNode objects | 129 | // Measured on two nodes before this ceiling existed: 277 and 90 CNode objects |
| 108 | // against 93 and 90 live sockets, and a status bar reporting hundreds of | 130 | // against 93 and 90 live sockets, and a status bar reporting hundreds of |
| 109 | // peers for a node that was really talking to thirty. | 131 | // peers for a node that was really talking to thirty. |
| 110 | // | 132 | // |
| 111 | // 125 is Bitcoin's number and sits far below FD_SETSIZE on both platforms. | 133 | // 125 is Bitcoin's number and remains a conservative public-node default. |
| 112 | static const unsigned int MAX_CONNECTIONS = 125; | 134 | static const unsigned int MAX_CONNECTIONS = 125; |
| 113 | 135 | ||
| 136 | // Cap inbound connections from any single address. Without it one source can | ||
| 137 | // hold every slot up to MAX_CONNECTIONS -- exactly what happened to the | ||
| 138 | // rendezvous relays, where a single IP parked hundreds of connections and | ||
| 139 | // starved real peers. A legitimate peer, even a relay talking to a relay, | ||
| 140 | // needs only a handful; 32 leaves generous room while denying any one address | ||
| 141 | // more than a quarter of the table. The firewall connlimit on the relays does | ||
| 142 | // the same thing a layer lower; this makes every build carry the defense. | ||
| 143 | // | ||
| 144 | // Loopback (127.0.0.0/8) is exempt in the accept path. A managed-Tor node | ||
| 145 | // receives every inbound onion peer over its local hidden-service listener, so | ||
| 146 | // they all appear as 127.0.0.1 -- capping loopback would cap onion peers as a | ||
| 147 | // group, which is exactly wrong for a network moving toward onion-only. The | ||
| 148 | // global MAX_CONNECTIONS still bounds the total; a per-onion-identity limit, | ||
| 149 | // applied once identity is known after accept(), is the right future tool for | ||
| 150 | // onion floods. | ||
| 151 | static const unsigned int MAX_CONNECTIONS_PER_IP = 32; | ||
| 152 | |||
| 114 | // A node marked for disconnect is normally held until its buffers drain, so | 153 | // A node marked for disconnect is normally held until its buffers drain, so |
| 115 | // a last message still goes out. But vSend cannot drain through a socket | 154 | // a last message still goes out. But vSend cannot drain through a socket |
| 116 | // whose far end is gone, and that made such a node immortal: it stayed in | 155 | // whose far end is gone, and that made such a node immortal: it stayed in |
| @@ -176,7 +215,7 @@ static const int BTF_BEHIND_WARN_INTERVAL_SECS = 5 * 60; | |||
| 176 | // | 215 | // |
| 177 | // These counters exist so it can. Cheap to keep, and they name the failures | 216 | // These counters exist so it can. Cheap to keep, and they name the failures |
| 178 | // that actually happened rather than the ones that sound impressive. | 217 | // that actually happened rather than the ones that sound impressive. |
| 179 | extern int nPeersWatched; // peers in the last select() set | 218 | extern int nPeersWatched; // peers in the last poll() set |
| 180 | extern int64 nBlocksReceived; // blocks handed to ProcessBlock | 219 | extern int64 nBlocksReceived; // blocks handed to ProcessBlock |
| 181 | extern int64 nBlocksWithoutParent; // ...of those, how many arrived orphaned | 220 | extern int64 nBlocksWithoutParent; // ...of those, how many arrived orphaned |
| 182 | 221 | ||
| @@ -236,15 +275,17 @@ void CheckForShutdown(int n); | |||
| 236 | // The message start string is designed to be unlikely to occur in normal data. | 275 | // The message start string is designed to be unlikely to occur in normal data. |
| 237 | // The characters are rarely used upper ascii, not valid as UTF-8, and produce | 276 | // The characters are rarely used upper ascii, not valid as UTF-8, and produce |
| 238 | // a large 4-byte int at any alignment. | 277 | // a large 4-byte int at any alignment. |
| 239 | // Magic bytes unique to the Bitflash network (0xbf = "BF"). Second byte bumped | 278 | // Magic bytes unique to the selected Bitflash network. Mainnet uses 0xbf = |
| 240 | // to 0x20 for the 2026 stable relaunch so the old test chain can't interfere. | 279 | // "BF"; testnet swaps the whole sequence so a test node cannot handshake with |
| 241 | static const char pchMessageStart[4] = { 0xbf, 0x20, 0x5c, 0xfd }; | 280 | // mainnet before consensus-level testnet activation exists. |
| 281 | extern char pchMessageStart[4]; | ||
| 242 | 282 | ||
| 243 | class CMessageHeader | 283 | class CMessageHeader |
| 244 | { | 284 | { |
| 245 | public: | 285 | public: |
| 246 | enum { COMMAND_SIZE=12 }; | 286 | enum { COMMAND_SIZE=12 }; |
| 247 | char pchMessageStart[sizeof(::pchMessageStart)]; | 287 | enum { MESSAGE_START_SIZE=4 }; |
| 288 | char pchMessageStart[MESSAGE_START_SIZE]; | ||
| 248 | char pchCommand[COMMAND_SIZE]; | 289 | char pchCommand[COMMAND_SIZE]; |
| 249 | unsigned int nMessageSize; | 290 | unsigned int nMessageSize; |
| 250 | 291 | ||
| @@ -335,7 +376,7 @@ public: | |||
| 335 | nServices = 0; | 376 | nServices = 0; |
| 336 | memcpy(pchReserved, pchIPv4, sizeof(pchReserved)); | 377 | memcpy(pchReserved, pchIPv4, sizeof(pchReserved)); |
| 337 | ip = 0; | 378 | ip = 0; |
| 338 | port = DEFAULT_PORT; | 379 | port = GetDefaultPort(); |
| 339 | nTime = GetAdjustedTime(); | 380 | nTime = GetAdjustedTime(); |
| 340 | nLastFailed = 0; | 381 | nLastFailed = 0; |
| 341 | } | 382 | } |
| @@ -365,7 +406,7 @@ public: | |||
| 365 | nServices = nServicesIn; | 406 | nServices = nServicesIn; |
| 366 | memcpy(pchReserved, pchIPv4, sizeof(pchReserved)); | 407 | memcpy(pchReserved, pchIPv4, sizeof(pchReserved)); |
| 367 | ip = 0; | 408 | ip = 0; |
| 368 | port = DEFAULT_PORT; | 409 | port = GetDefaultPort(); |
| 369 | nTime = GetAdjustedTime(); | 410 | nTime = GetAdjustedTime(); |
| 370 | nLastFailed = 0; | 411 | nLastFailed = 0; |
| 371 | 412 | ||
| @@ -656,9 +697,6 @@ public: | |||
| 656 | int64 nLastSend; | 697 | int64 nLastSend; |
| 657 | int64 nLastRecv; | 698 | int64 nLastRecv; |
| 658 | int64 nLastSendEmpty; | 699 | int64 nLastSendEmpty; |
| 659 | int64 nIncompleteMessageStart; | ||
| 660 | unsigned int nIncompleteMessageSize; | ||
| 661 | string strIncompleteMessageCommand; | ||
| 662 | string strBtfAddr; | 700 | string strBtfAddr; |
| 663 | string strBtfMeeting; | 701 | string strBtfMeeting; |
| 664 | 702 | ||
| @@ -699,11 +737,13 @@ public: | |||
| 699 | nLastSend = 0; | 737 | nLastSend = 0; |
| 700 | nLastRecv = 0; | 738 | nLastRecv = 0; |
| 701 | nLastSendEmpty = GetTime(); | 739 | nLastSendEmpty = GetTime(); |
| 702 | nIncompleteMessageStart = 0; | ||
| 703 | nIncompleteMessageSize = 0; | ||
| 704 | strIncompleteMessageCommand.clear(); | ||
| 705 | strBtfAddr.clear(); | 740 | strBtfAddr.clear(); |
| 706 | strBtfMeeting.clear(); | 741 | strBtfMeeting.clear(); |
| 742 | // Not waiting on anything yet. Left indeterminate, the first partial | ||
| 743 | // message this peer sends is measured against whatever was in this | ||
| 744 | // memory, and ProcessMessages drops it as unreadable on first contact. | ||
| 745 | nMsgWaitSince = 0; | ||
| 746 | nMsgWaitSize = 0; | ||
| 707 | nStartingHeight = -1; | 747 | nStartingHeight = -1; |
| 708 | 748 | ||
| 709 | // Push a version message | 749 | // Push a version message |
| @@ -798,13 +838,51 @@ public: | |||
| 798 | static int64 nLastTime; | 838 | static int64 nLastTime; |
| 799 | nLastTime = nNow = max(nNow, ++nLastTime); | 839 | nLastTime = nNow = max(nNow, ++nLastTime); |
| 800 | 840 | ||
| 801 | // Each retry is 2 minutes after the last | 841 | // Each retry is 2 minutes after the last -- and because nRequestTime |
| 802 | nRequestTime = max(nRequestTime + 2 * 60 * 1000000, nNow); | 842 | // is shared across peers, the same spacing is what strings requests |
| 843 | // for one inv across its announcers. For transactions that is pacing; | ||
| 844 | // for a new block it was the stall of issue #33: nine peers announce | ||
| 845 | // the block, the first one asked does not serve it, and the ninth | ||
| 846 | // candidate is not even asked until sixteen minutes in, with the pool | ||
| 847 | // mining on the stale tip the whole time. | ||
| 848 | // | ||
| 849 | // Blocks retry on the fetch timescale, but only while we are at the | ||
| 850 | // tip. That is where the stall costs something -- the pool keeps | ||
| 851 | // handing out jobs against a dead tip -- and it is also where the | ||
| 852 | // spacing is nearly free: one block is in flight, and its body has | ||
| 853 | // almost always arrived before the second announcer's turn comes | ||
| 854 | // round, so AlreadyHave drops the duplicate before a getdata is sent. | ||
| 855 | // | ||
| 856 | // While catching up neither half holds. A peer working through a | ||
| 857 | // 500-deep queue can be minutes away from block N without anything | ||
| 858 | // being wrong, so at 15s the second announcer is asked at +15s, the | ||
| 859 | // third at +30s, and the bulk download arrives once per announcer -- | ||
| 860 | // up to eight times over. Nothing caps that: the eight-entry cap is on | ||
| 861 | // mapBlockFetch, which is a different mechanism from this spacing. | ||
| 862 | // Two minutes is the right number there, and it is what this line did | ||
| 863 | // before. Failover at the tip does not depend on this being 15s in any | ||
| 864 | // case: mapBlockFetch re-issues a stalled getdata to the next peer on | ||
| 865 | // its own timer, which is what actually fixes #33. | ||
| 866 | bool fFast = (inv.type == MSG_BLOCK && IsBlockFetchNearTip()); | ||
| 867 | int64 nRetryUsecs = (fFast ? BLOCK_FETCH_RETRY_SECS : 2 * 60) * 1000000LL; | ||
| 868 | nRequestTime = max(nRequestTime + nRetryUsecs, nNow); | ||
| 803 | mapAskFor.insert(make_pair(nRequestTime, inv)); | 869 | mapAskFor.insert(make_pair(nRequestTime, inv)); |
| 804 | } | 870 | } |
| 805 | 871 | ||
| 806 | 872 | ||
| 807 | 873 | ||
| 874 | // "sending: tx (N bytes)" alone was ~71% of a 13-hour production | ||
| 875 | // debug.log (issue #35), so tx sends are demoted to the /debugrelay-gated | ||
| 876 | // "relay" category; every other command's send trace stays on "net". | ||
| 877 | // The line is emitted in pieces across BeginMessage/EndMessage/ | ||
| 878 | // AbortMessage, so all three must agree on the category or orphaned | ||
| 879 | // "(N bytes)" fragments would leak into a plain -debug log. | ||
| 880 | // Valid only mid-message (nPushPos != -1). | ||
| 881 | const char* SendLogCategory() const | ||
| 882 | { | ||
| 883 | return strcmp(GetMessageCommand(), "tx") == 0 ? "relay" : "net"; | ||
| 884 | } | ||
| 885 | |||
| 808 | void BeginMessage(const char* pszCommand) | 886 | void BeginMessage(const char* pszCommand) |
| 809 | { | 887 | { |
| 810 | EnterCriticalSection(&cs_vSend); | 888 | EnterCriticalSection(&cs_vSend); |
| @@ -812,17 +890,19 @@ public: | |||
| 812 | AbortMessage(); | 890 | AbortMessage(); |
| 813 | nPushPos = vSend.size(); | 891 | nPushPos = vSend.size(); |
| 814 | vSend << CMessageHeader(pszCommand, 0); | 892 | vSend << CMessageHeader(pszCommand, 0); |
| 815 | if (LogAcceptsCategory("net")) printf("sending: %-12s ", pszCommand); | 893 | if (LogAcceptsCategory(SendLogCategory())) printf("sending: %-12s ", pszCommand); |
| 816 | } | 894 | } |
| 817 | 895 | ||
| 818 | void AbortMessage() | 896 | void AbortMessage() |
| 819 | { | 897 | { |
| 820 | if (nPushPos == -1) | 898 | if (nPushPos == -1) |
| 821 | return; | 899 | return; |
| 900 | // Capture before nPushPos is cleared; GetMessageCommand() needs it. | ||
| 901 | const char* pszCategory = SendLogCategory(); | ||
| 822 | vSend.resize(nPushPos); | 902 | vSend.resize(nPushPos); |
| 823 | nPushPos = -1; | 903 | nPushPos = -1; |
| 824 | LeaveCriticalSection(&cs_vSend); | 904 | LeaveCriticalSection(&cs_vSend); |
| 825 | if (LogAcceptsCategory("net")) printf("(aborted)\n"); | 905 | if (LogAcceptsCategory(pszCategory)) printf("(aborted)\n"); |
| 826 | } | 906 | } |
| 827 | 907 | ||
| 828 | void EndMessage() | 908 | void EndMessage() |
| @@ -830,7 +910,11 @@ public: | |||
| 830 | extern int nDropMessagesTest; | 910 | extern int nDropMessagesTest; |
| 831 | if (nDropMessagesTest > 0 && GetRand(nDropMessagesTest) == 0) | 911 | if (nDropMessagesTest > 0 && GetRand(nDropMessagesTest) == 0) |
| 832 | { | 912 | { |
| 833 | if (LogAcceptsCategory("net")) printf("dropmessages DROPPING SEND MESSAGE\n"); | 913 | // Same category as the "sending: " this line interrupts, so a tx |
| 914 | // does not announce its own drop under "net" having been gated | ||
| 915 | // off under "relay". nPushPos can be -1 here, and then | ||
| 916 | // GetMessageCommand() returns "" and this is "net" as before. | ||
| 917 | if (LogAcceptsCategory(SendLogCategory())) printf("dropmessages DROPPING SEND MESSAGE\n"); | ||
| 834 | AbortMessage(); | 918 | AbortMessage(); |
| 835 | return; | 919 | return; |
| 836 | } | 920 | } |
| @@ -842,10 +926,10 @@ public: | |||
| 842 | unsigned int nSize = vSend.size() - nPushPos - sizeof(CMessageHeader); | 926 | unsigned int nSize = vSend.size() - nPushPos - sizeof(CMessageHeader); |
| 843 | memcpy((char*)&vSend[nPushPos] + offsetof(CMessageHeader, nMessageSize), &nSize, sizeof(nSize)); | 927 | memcpy((char*)&vSend[nPushPos] + offsetof(CMessageHeader, nMessageSize), &nSize, sizeof(nSize)); |
| 844 | 928 | ||
| 845 | if (LogAcceptsCategory("net")) printf("(%d bytes) ", nSize); | 929 | if (LogAcceptsCategory(SendLogCategory())) printf("(%d bytes) ", nSize); |
| 846 | //for (int i = nPushPos+sizeof(CMessageHeader); i < min(vSend.size(), nPushPos+sizeof(CMessageHeader)+20U); i++) | 930 | //for (int i = nPushPos+sizeof(CMessageHeader); i < min(vSend.size(), nPushPos+sizeof(CMessageHeader)+20U); i++) |
| 847 | // printf("%02x ", vSend[i] & 0xff); | 931 | // printf("%02x ", vSend[i] & 0xff); |
| 848 | if (LogAcceptsCategory("net")) printf("\n"); | 932 | if (LogAcceptsCategory(SendLogCategory())) printf("\n"); |
| 849 | 933 | ||
| 850 | nPushPos = -1; | 934 | nPushPos = -1; |
| 851 | LeaveCriticalSection(&cs_vSend); | 935 | LeaveCriticalSection(&cs_vSend); |