diff --git a/nselib/rpc.lua b/nselib/rpc.lua
index 8d8dfa350..9f7c03e2e 100644
--- a/nselib/rpc.lua
+++ b/nselib/rpc.lua
@@ -287,8 +287,11 @@ Comm = {
self.program_id = progid
end,
- --- Checks if data contains enough bytes to read the needed amount
- -- If it doesn't it attempts to read the remaining amount of bytes from the socket
+ --- Checks if data contains enough bytes to read the needed amount
+ --
+ -- If it doesn't it attempts to read the remaining amount of bytes from the
+ -- socket. Unlike socket.receive_bytes, reading less than
+ -- needed is treated as an error.
--
-- @param data string containing the current buffer
-- @param pos number containing the current offset into the buffer
@@ -296,16 +299,19 @@ Comm = {
-- @return status success or failure
-- @return data string containing the data passed to the function and the additional data appended to it or error message on failure
GetAdditionalBytes = function( self, data, pos, needed )
- local status, tmp
-
- if data:len() - pos + 1 < needed then
- local toread = needed - ( data:len() - pos + 1 )
- status, tmp = self.socket:receive_bytes( toread )
+ local toread = needed - ( data:len() - pos + 1 )
+ -- Do the loop ourselves instead of receive_bytes. Pathological case:
+ -- * read less than needed and timeout
+ -- * receive_bytes returns short but we don't know if it's eof or timeout
+ -- * Try again. If it was timeout, we've doubled the timeout waiting for bytes that aren't coming.
+ while toread > 0 do
+ local status, tmp = self.socket:receive()
if status then
+ toread = toread - #tmp
data = data .. tmp
else
- return false, string.format("getAdditionalBytes() failed to read: %d bytes from the socket",
- needed - ( data:len() - pos ) )
+ return false, string.format("getAdditionalBytes read %d bytes before error: %s",
+ needed - toread, tmp)
end
end
return true, data