]>
git.proxmox.com Git - mirror_qemu.git/blob - python/qemu/console_socket.py
3 # This python module implements a ConsoleSocket object which is
4 # designed always drain the socket itself, and place
5 # the bytes into a in memory buffer for later processing.
7 # Optionally a file path can be passed in and we will also
8 # dump the characters to this file for debug.
10 # Copyright 2020 Linaro
13 # Robert Foley <robert.foley@linaro.org>
15 # This code is licensed under the GPL version 2 or later. See
16 # the COPYING file in the top-level directory.
24 from collections
import deque
28 class ConsoleSocket(asyncore
.dispatcher
):
30 def __init__(self
, address
, file=None):
31 self
._recv
_timeout
_sec
= 300
32 self
._buffer
= deque()
33 self
._asyncore
_thread
= None
34 self
._sock
= socket
.socket(socket
.AF_UNIX
, socket
.SOCK_STREAM
)
35 self
._sock
.connect(address
)
38 self
._logfile
= open(file, "w")
39 asyncore
.dispatcher
.__init
__(self
, sock
=self
._sock
)
43 def _thread_start(self
):
44 """Kick off a thread to wait on the asyncore.loop"""
45 if self
._asyncore
_thread
is not None:
47 self
._asyncore
_thread
= threading
.Thread(target
=asyncore
.loop
,
49 self
._asyncore
_thread
.daemon
= True
50 self
._asyncore
_thread
.start()
52 def handle_close(self
):
53 """redirect close to base class"""
54 # Call the base class close, but not self.close() since
55 # handle_close() occurs in the context of the thread which
56 # self.close() attempts to join.
57 asyncore
.dispatcher
.close(self
)
60 """Close the base object and wait for the thread to terminate"""
63 asyncore
.dispatcher
.close(self
)
64 if self
._asyncore
_thread
is not None:
65 thread
, self
._asyncore
_thread
= self
._asyncore
_thread
, None
71 def handle_read(self
):
72 """process arriving characters into in memory _buffer"""
74 data
= asyncore
.dispatcher
.recv(self
, 1)
75 # latin1 is needed since there are some chars
76 # we are receiving that cannot be encoded to utf-8
77 # such as 0xe2, 0x80, 0xA6.
78 string
= data
.decode("latin1")
80 print("Exception seen.")
84 self
._logfile
.write("{}".format(string
))
87 self
._buffer
.extend(c
)
89 def recv(self
, n
=1, sleep_delay_s
=0.1):
90 """Return chars from in memory buffer"""
91 start_time
= time
.time()
92 while len(self
._buffer
) < n
:
93 time
.sleep(sleep_delay_s
)
94 elapsed_sec
= time
.time() - start_time
95 if elapsed_sec
> self
._recv
_timeout
_sec
:
97 chars
= ''.join([self
._buffer
.popleft() for i
in range(n
)])
98 # We choose to use latin1 to remain consistent with
99 # handle_read() and give back the same data as the user would
100 # receive if they were reading directly from the
101 # socket w/o our intervention.
102 return chars
.encode("latin1")
104 def set_blocking(self
):
105 """Maintain compatibility with socket API"""
108 def settimeout(self
, seconds
):
109 """Set current timeout on recv"""
110 self
._recv
_timeout
_sec
= seconds