From 10b7805b0f46ed1007068473879747f7d60d49fc Mon Sep 17 00:00:00 2001 From: Michal Berger Date: Fri, 21 May 2021 19:50:08 +0200 Subject: [PATCH] scripts/rpc: Make sure address argument is properly interpreted In case the addr argument was not an existing unix socket file the rpc client would consider it to be an actual ip address. As a result connect() would be called with improper set of arguments. This could cause the rpc.py to block for undesired amount of time until connect() finally decided to return (seen on some fedora33 builds). This was affecting sh wrapper functions like waitforlisten() which use rpc.py to determine if given app is ready to be talk to blocking execution of the tests for way too long then intendent. To avoid such a scenario determine the format of the address and use routines proper for given address family. Signed-off-by: Michal Berger Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7777 (master) (cherry picked from commit 6c1a1a3dcac557f7bce0267f59311ea98e435eef) Change-Id: Iaac701d72c772629fa7c6478ff4781b0c5d485d5 Signed-off-by: Krzysztof Karas Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8018 Reviewed-by: Karol Latecki Reviewed-by: Michal Berger Reviewed-by: Tomasz Zawadzki Reviewed-by: Changpeng Liu Tested-by: SPDK CI Jenkins --- scripts/rpc/client.py | 43 ++++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/scripts/rpc/client.py b/scripts/rpc/client.py index f84a1cf00c..caecda1448 100644 --- a/scripts/rpc/client.py +++ b/scripts/rpc/client.py @@ -14,6 +14,22 @@ def print_json(s): print(json.dumps(s, indent=2).strip('"')) +def get_addr_type(addr): + try: + socket.inet_pton(socket.AF_INET, addr) + return socket.AF_INET + except Exception as e: + pass + try: + socket.inet_pton(socket.AF_INET6, addr) + return socket.AF_INET6 + except Exception as e: + pass + if os.path.exists(addr): + return socket.AF_UNIX + return None + + class JSONRPCException(Exception): def __init__(self, message): self.message = message @@ -54,23 +70,24 @@ class JSONRPCClient(object): def _connect(self, addr, port): try: - if os.path.exists(addr): + addr_type = get_addr_type(addr) + + if addr_type == socket.AF_UNIX: self._logger.debug("Trying to connect to UNIX socket: %s", addr) self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) self.sock.connect(addr) - elif port: - if ':' in addr: - self._logger.debug("Trying to connect to IPv6 address addr:%s, port:%i", addr, port) - for res in socket.getaddrinfo(addr, port, socket.AF_INET6, socket.SOCK_STREAM, socket.SOL_TCP): - af, socktype, proto, canonname, sa = res - self.sock = socket.socket(af, socktype, proto) - self.sock.connect(sa) - else: - self._logger.debug("Trying to connect to IPv4 address addr:%s, port:%i'", addr, port) - self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.sock.connect((addr, port)) + elif addr_type == socket.AF_INET6: + self._logger.debug("Trying to connect to IPv6 address addr:%s, port:%i", addr, port) + for res in socket.getaddrinfo(addr, port, socket.AF_INET6, socket.SOCK_STREAM, socket.SOL_TCP): + af, socktype, proto, canonname, sa = res + self.sock = socket.socket(af, socktype, proto) + self.sock.connect(sa) + elif addr_type == socket.AF_INET: + self._logger.debug("Trying to connect to IPv4 address addr:%s, port:%i'", addr, port) + self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.sock.connect((addr, port)) else: - raise socket.error("Unix socket '%s' does not exist" % addr) + raise socket.error("Invalid or non-existing address: '%s'" % addr) except socket.error as ex: raise JSONRPCException("Error while connecting to %s\n" "Is SPDK application running?\n"