Skip to content

Commit 2b7dbba

Browse files
committed
Refactor and simplify socket_read_until_newline() to ReadUntil()
Do socket reads in chunks of 1024 bytes, split at first occurence of separator and return up to that first occurence while keeping the remains of the read chunk for further invocations of ReadUntil(), and do utilise that cached data until drained, then re-read the socket. Also, there's no need to keep track of timeouts, this is handled by utilising socket.settimeout().
1 parent 2a3db31 commit 2b7dbba

File tree

1 file changed

+16
-26
lines changed

1 file changed

+16
-26
lines changed

resources/lib/lcdproc.py

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ def __init__(self, settings):
3232
self.m_initRetryInterval = INIT_RETRY_INTERVAL
3333
self.m_used = True
3434
self.m_socket = None
35+
self.m_sockreadbuf = b''
3536
self.m_timeLastSockAction = time.time()
3637
self.m_timeSocketIdleTimeout = 2
3738
self.m_strLineText = [None]*MAX_ROWS
@@ -48,33 +49,19 @@ def __init__(self, settings):
4849

4950
LcdBase.__init__(self, settings)
5051

51-
def socket_read_until_newline(self, searchstr, timeout):
52+
def ReadUntil(self, separator):
5253
if not self.m_socket:
5354
return b""
5455

55-
data = bytearray()
56-
start_time = time.time()
56+
while separator not in self.m_sockreadbuf:
57+
data = self.m_socket.recv(1024)
58+
if not data:
59+
raise EOFError
60+
self.m_sockreadbuf += data
5761

58-
while True:
59-
# Return current data on timeout
60-
elapsed_time = time.time() - start_time
61-
if elapsed_time > timeout:
62-
break
62+
line, tmp, self.m_sockreadbuf = self.m_sockreadbuf.partition(separator)
6363

64-
# Read new data and break on disconnect (empty bytes object returned; timeout for recv is set on connect)
65-
try:
66-
chunk = self.m_socket.recv(1)
67-
except TimeoutError:
68-
chunk = b''
69-
if not chunk:
70-
break
71-
data += chunk
72-
73-
# Break if searchstr is found
74-
if searchstr in data:
75-
break
76-
77-
return data
64+
return line + b"\n"
7865

7966
def SendCommand(self, strCmd, bCheckRet):
8067
countcmds = strCmd.count(b'\n')
@@ -104,7 +91,7 @@ def SendCommand(self, strCmd, bCheckRet):
10491
while True:
10592
try:
10693
# Read server reply
107-
reply = self.socket_read_until_newline(b"\n", timeout=3)
94+
reply = self.ReadUntil(b"\n")
10895
except:
10996
# (Re)read failed, abort
11097
log(LOGERROR, "SendCommand: Telnet exception - reread")
@@ -241,7 +228,7 @@ def DetermineExtraSupport(self):
241228
try:
242229
# Retrieve driver name for additional functionality
243230
self.m_socket.send(b"info\n")
244-
reply = self.socket_read_until_newline(b"\n", timeout=3).strip().decode("ascii")
231+
reply = self.ReadUntil(b"\n").strip().decode("ascii")
245232

246233
# When the LCDd driver doesn't supply a valid string, inform and return
247234
if reply == "":
@@ -282,13 +269,15 @@ def Connect(self):
282269
log(LOGDEBUG,"Open " + str(ip) + ":" + str(port))
283270

284271
self.m_socket = socket(AF_INET, SOCK_STREAM)
272+
self.m_socket.settimeout(15)
285273
self.m_socket.connect((ip, port))
286-
self.m_socket.settimeout(1)
274+
self.m_socket.settimeout(3)
275+
287276
# Start a new session
288277
self.m_socket.send(b"hello\n")
289278

290279
# Receive LCDproc data to determine row and column information
291-
reply = self.socket_read_until_newline(b"\n", timeout=3).decode("ascii")
280+
reply = self.ReadUntil(b"\n").decode("ascii")
292281
log(LOGDEBUG,"Reply: " + reply)
293282

294283
# parse reply by regex
@@ -357,6 +346,7 @@ def CloseSocket(self):
357346
del self.m_cExtraIcons
358347
self.m_cExtraIcons = None
359348

349+
self.m_sockreadbuf = b''
360350
self.m_socket = None
361351

362352
def IsConnected(self):

0 commit comments

Comments
 (0)