|
1 |
| -#!/usr/bin/env python3 |
2 |
| -# |
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. |
6 |
| -# |
7 |
| -# Optionally a file path can be passed in and we will also |
8 |
| -# dump the characters to this file for debug. |
9 |
| -# |
| 1 | +""" |
| 2 | +QEMU Console Socket Module: |
| 3 | +
|
| 4 | +This python module implements a ConsoleSocket object, |
| 5 | +which can drain a socket and optionally dump the bytes to file. |
| 6 | +""" |
10 | 7 | # Copyright 2020 Linaro
|
11 | 8 | #
|
12 | 9 | # Authors:
|
|
15 | 12 | # This code is licensed under the GPL version 2 or later. See
|
16 | 13 | # the COPYING file in the top-level directory.
|
17 | 14 | #
|
| 15 | + |
18 | 16 | import asyncore
|
19 | 17 | import socket
|
20 | 18 | import threading
|
21 |
| -import io |
22 |
| -import os |
23 |
| -import sys |
24 | 19 | from collections import deque
|
25 | 20 | import time
|
26 |
| -import traceback |
| 21 | + |
27 | 22 |
|
28 | 23 | class ConsoleSocket(asyncore.dispatcher):
|
| 24 | + """ |
| 25 | + ConsoleSocket represents a socket attached to a char device. |
29 | 26 |
|
| 27 | + Drains the socket and places the bytes into an in memory buffer |
| 28 | + for later processing. |
| 29 | +
|
| 30 | + Optionally a file path can be passed in and we will also |
| 31 | + dump the characters to this file for debugging purposes. |
| 32 | + """ |
30 | 33 | def __init__(self, address, file=None):
|
31 | 34 | self._recv_timeout_sec = 300
|
| 35 | + self._sleep_time = 0.5 |
32 | 36 | self._buffer = deque()
|
33 | 37 | self._asyncore_thread = None
|
34 | 38 | self._sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
@@ -70,31 +74,28 @@ def close(self):
|
70 | 74 |
|
71 | 75 | def handle_read(self):
|
72 | 76 | """process arriving characters into in memory _buffer"""
|
73 |
| - try: |
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") |
79 |
| - except: |
80 |
| - print("Exception seen.") |
81 |
| - traceback.print_exc() |
82 |
| - return |
| 77 | + data = asyncore.dispatcher.recv(self, 1) |
| 78 | + # latin1 is needed since there are some chars |
| 79 | + # we are receiving that cannot be encoded to utf-8 |
| 80 | + # such as 0xe2, 0x80, 0xA6. |
| 81 | + string = data.decode("latin1") |
83 | 82 | if self._logfile:
|
84 | 83 | self._logfile.write("{}".format(string))
|
85 | 84 | self._logfile.flush()
|
86 | 85 | for c in string:
|
87 | 86 | self._buffer.extend(c)
|
88 | 87 |
|
89 |
| - def recv(self, n=1, sleep_delay_s=0.1): |
90 |
| - """Return chars from in memory buffer""" |
| 88 | + def recv(self, buffer_size=1): |
| 89 | + """Return chars from in memory buffer. |
| 90 | + Maintains the same API as socket.socket.recv. |
| 91 | + """ |
91 | 92 | start_time = time.time()
|
92 |
| - while len(self._buffer) < n: |
93 |
| - time.sleep(sleep_delay_s) |
| 93 | + while len(self._buffer) < buffer_size: |
| 94 | + time.sleep(self._sleep_time) |
94 | 95 | elapsed_sec = time.time() - start_time
|
95 | 96 | if elapsed_sec > self._recv_timeout_sec:
|
96 | 97 | raise socket.timeout
|
97 |
| - chars = ''.join([self._buffer.popleft() for i in range(n)]) |
| 98 | + chars = ''.join([self._buffer.popleft() for i in range(buffer_size)]) |
98 | 99 | # We choose to use latin1 to remain consistent with
|
99 | 100 | # handle_read() and give back the same data as the user would
|
100 | 101 | # receive if they were reading directly from the
|
|
0 commit comments