]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Maintain a sseparate inPos and inWanted, this should fix partial reads,
authorOtto <otto.moerbeek@open-xchange.com>
Mon, 14 Jun 2021 09:54:05 +0000 (11:54 +0200)
committerOtto <otto.moerbeek@open-xchange.com>
Fri, 18 Jun 2021 06:47:43 +0000 (08:47 +0200)
make the code more clear and also allow less resizing.

pdns/pdns_recursor.cc
pdns/syncres.hh

index bf7a0d4dbaee63049bdddaaac19c240707e01703..1aeaf0b223dca3fb13d16c890a116a9d5d645f3a 100644 (file)
@@ -485,9 +485,9 @@ LWResult::Result arecvtcp(PacketBuffer& data, const size_t len, shared_ptr<TCPIO
   pident->tcphandler = handler;
   pident->tcpsock = handler->getDescriptor();
   // We might have a partial result
-  data.resize(pos);
   pident->inMSG = data;
-  pident->inNeeded = len;
+  pident->inPos = pos;
+  pident->inWanted = len;
   pident->inIncompleteOkay = incompleteOkay;
   pident->highState = TCPAction::DoingRead;
 
@@ -4157,23 +4157,21 @@ static void TCPIOHandlerIO(int fd, FDMultiplexer::funcparam_t& var)
 
   // In the code below, we want to update the state of the fd before calling sendEvent
   // a sendEvent might close the fd, and some poll multiplexers do not like to manipulate a closed fd
-  
+
   switch (pid->highState) {
   case TCPAction::DoingRead:
     TCPLOG("highState: Reading" << endl);
+    // In arecvtcp, the buffer was resized already so inWanted bytes will fit
     // try reading
     try {
-      size_t pos = pid->inMSG.size();
-      pid->inMSG.resize(pos + pid->inNeeded); // make room for what we'll read
-      newstate = pid->tcphandler->tryRead(pid->inMSG, pos, pid->inNeeded);
+      newstate = pid->tcphandler->tryRead(pid->inMSG, pid->inPos, pid->inWanted - pid->inPos);
       switch (newstate) {
       case IOState::Done:
       case IOState::NeedRead:
-        TCPLOG("tryRead: Done or NeedRead " << int(newstate) << ' ' << pos << '/' << pid->inNeeded << endl);
-        pid->inMSG.resize(pos); // old content (if there) + new bytes read
-        pid->inNeeded -= pos;
-        TCPLOG("TCPIOHandlerIO " << pid->inNeeded << ' ' << pid->inIncompleteOkay << endl);
-        if (pid->inNeeded == 0 || pid->inIncompleteOkay) {
+        TCPLOG("tryRead: Done or NeedRead " << int(newstate) << ' ' << pid->inPos << '/' << pid->inWanted << endl);
+        TCPLOG("TCPIOHandlerIO " << pid->inWanted << ' ' << pid->inIncompleteOkay << endl);
+        if (pid->inPos == pid->inWanted || (pid->inIncompleteOkay && pid->inPos > 0)) {
+          pid->inMSG.resize(pid->inPos); // old content (if there) + new bytes read, only relevant for the inIncompleteOkay case
           newstate = IOState::Done;
           TCPIOHandlerStateChange(pid->lowState, newstate, pid);
           MT->sendEvent(*pid, &pid->inMSG);
@@ -5930,3 +5928,4 @@ int main(int argc, char **argv)
   return ret;
 }
 
+
index a67a0ab216eb7b502e9633b64c0ab9330ccea9da..1bcdf712e9e8ebfb9dc50b60f98d5d341edf38fb 100644 (file)
@@ -946,7 +946,8 @@ struct PacketID
   typedef set<uint16_t > chain_t;
   mutable chain_t chain;
   shared_ptr<TCPIOHandler> tcphandler{nullptr};
-  size_t inNeeded{0}; // if this is set, we'll read until inNeeded bytes are read
+  string::size_type inPos{0};   // how for are we along in the inMSG
+  size_t inWanted{0}; // if this is set, we'll read until inWanted bytes are read
   string::size_type outPos{0};    // how far we are along in the outMSG
   mutable uint32_t nearMisses{0}; // number of near misses - host correct, id wrong
   int fd{-1};