aboutsummaryrefslogtreecommitdiffstats
path: root/src/vpp-api/python/vpp_papi
diff options
context:
space:
mode:
authorVratko Polak <vrpolak@cisco.com>2019-10-11 16:53:08 +0200
committerOle Trøan <otroan@employees.org>2019-10-11 18:48:21 +0000
commit6df2c7954126a316f86908526c3bb4d649f06597 (patch)
tree2c7eff780b432d8761f6ebe1f1a3814466103a84 /src/vpp-api/python/vpp_papi
parent11b40e7ead069eecac51eeed0b7effbf4d53ecf4 (diff)
papi: harden socket handling
In the previous implementation of socket transport for PAPI, socket methods .send and .recv_into were used. But they are not guaranteed to send/receive all the data for the full message. The receive part contained a loop, but it handled only the main message, not the header. This patch replaces .send with .sendall and uses newly defined _read_fixed method. Also, removed Paul from maintainers, as he is not active much, lately. Type: fix Change-Id: Iae1a68bf8f9e666856b7c7d62ebfe22defc5dfe1 Signed-off-by: Vratko Polak <vrpolak@cisco.com>
Diffstat (limited to 'src/vpp-api/python/vpp_papi')
-rw-r--r--src/vpp-api/python/vpp_papi/vpp_transport_socket.py42
1 files changed, 24 insertions, 18 deletions
diff --git a/src/vpp-api/python/vpp_papi/vpp_transport_socket.py b/src/vpp-api/python/vpp_papi/vpp_transport_socket.py
index 3c3c8e514db..3c1ea326198 100644
--- a/src/vpp-api/python/vpp_papi/vpp_transport_socket.py
+++ b/src/vpp-api/python/vpp_papi/vpp_transport_socket.py
@@ -188,31 +188,37 @@ class VppTransport(object):
# Send header
header = self.header.pack(0, len(buf), 0)
- n = self.socket.send(header)
- n = self.socket.send(buf)
- if n == 0:
- raise VppTransportSocketIOError(1, 'Not connected')
+ if self.socket.sendall(header) is None:
+ raise VppTransportSocketIOError(1, 'Failed to send')
+ if self.socket.sendall(buf) is None:
+ raise VppTransportSocketIOError(1, 'Failed to send')
+
+ def _read_fixed(self, size):
+ """Repeat receive until fixed size is read. Return empty on error."""
+ buf = bytearray(size)
+ view = memoryview(buf)
+ left = size
+ while 1:
+ got = self.socket.recv_into(view, left)
+ if got <= 0:
+ # Read error.
+ return ""
+ if got >= left:
+ # TODO: Raise if got > left?
+ break
+ left -= got
+ view = view[got:]
+ return buf
def _read(self):
- hdr = self.socket.recv(16)
+ """Read single complete message, return it or empty on error."""
+ hdr = self._read_fixed(16)
if not hdr:
return
(_, hdrlen, _) = self.header.unpack(hdr) # If at head of message
# Read rest of message
- msg = self.socket.recv(hdrlen)
- if hdrlen > len(msg):
- nbytes = len(msg)
- buf = bytearray(hdrlen)
- view = memoryview(buf)
- view[:nbytes] = msg
- view = view[nbytes:]
- left = hdrlen - nbytes
- while left:
- nbytes = self.socket.recv_into(view, left)
- view = view[nbytes:]
- left -= nbytes
- return buf
+ msg = self._read_fixed(hdrlen)
if hdrlen == len(msg):
return msg
raise VppTransportSocketIOError(1, 'Unknown socket read error')