Skip to content

Commit 3583a2b

Browse files
Fix socket not close issue when error
1 parent 34a1b1e commit 3583a2b

File tree

7 files changed

+79
-84
lines changed

7 files changed

+79
-84
lines changed

opengsq/protocols/gamespy1.py

+5-7
Original file line numberDiff line numberDiff line change
@@ -115,14 +115,12 @@ async def __get_packets_response(self, sock):
115115

116116
async def __connect_and_send(self, data) -> BinaryReader:
117117
# Connect to remote host
118-
sock = SocketAsync()
119-
sock.settimeout(self._timeout)
120-
await sock.connect((self._address, self._query_port))
118+
with SocketAsync() as sock:
119+
sock.settimeout(self._timeout)
120+
await sock.connect((self._address, self._query_port))
121121

122-
sock.send(data)
123-
br = BinaryReader(await self.__get_packets_response(sock))
124-
125-
sock.close()
122+
sock.send(data)
123+
br = BinaryReader(await self.__get_packets_response(sock))
126124

127125
return br
128126

opengsq/protocols/gamespy2.py

+7-9
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,15 @@ def __init__(self, address: str, query_port: int, timeout: float = 5.0):
2121
async def get_status(self, request: Request = Request.INFO | Request.PLAYERS | Request.TEAMS) -> dict:
2222
"""Retrieves information about the server including, Info, Players, and Teams."""
2323
# Connect to remote host
24-
sock = SocketAsync()
25-
sock.settimeout(self._timeout)
26-
await sock.connect((self._address, self._query_port))
24+
with SocketAsync() as sock:
25+
sock.settimeout(self._timeout)
26+
await sock.connect((self._address, self._query_port))
2727

28-
# Send Request
29-
sock.send(b'\xFE\xFD\x00\x04\x05\x06\x07' + self.__get_request_bytes(request))
28+
# Send Request
29+
sock.send(b'\xFE\xFD\x00\x04\x05\x06\x07' + self.__get_request_bytes(request))
3030

31-
# Server response
32-
response = await sock.recv()
33-
34-
sock.close()
31+
# Server response
32+
response = await sock.recv()
3533

3634
# Remove the first 5 bytes { 0x00, 0x04, 0x05, 0x06, 0x07 }
3735
br = BinaryReader(response[5:])

opengsq/protocols/gamespy3.py

+24-26
Original file line numberDiff line numberDiff line change
@@ -17,39 +17,37 @@ def __init__(self, address: str, query_port: int, timeout: float = 5.0):
1717
async def get_status(self):
1818
"""Retrieves information about the server including, Info, Players, and Teams."""
1919
# Connect to remote host
20-
sock = SocketAsync()
21-
sock.settimeout(self._timeout)
22-
await sock.connect((self._address, self._query_port))
20+
with SocketAsync() as sock:
21+
sock.settimeout(self._timeout)
22+
await sock.connect((self._address, self._query_port))
2323

24-
request_h = b'\xFE\xFD'
25-
timestamp = b'\x04\x05\x06\x07'
26-
challenge = b''
24+
request_h = b'\xFE\xFD'
25+
timestamp = b'\x04\x05\x06\x07'
26+
challenge = b''
2727

28-
if self.challenge:
29-
# Packet 1: Initial request - (https://wiki.unrealadmin.org/UT3_query_protocol#Packet_1:_Initial_request)
30-
sock.send(request_h + b'\x09' + timestamp)
28+
if self.challenge:
29+
# Packet 1: Initial request - (https://wiki.unrealadmin.org/UT3_query_protocol#Packet_1:_Initial_request)
30+
sock.send(request_h + b'\x09' + timestamp)
3131

32-
# Packet 2: First response - (https://wiki.unrealadmin.org/UT3_query_protocol#Packet_2:_First_response)
33-
response = await sock.recv()
34-
35-
if response[0] != 9:
36-
raise InvalidPacketException(
37-
'Packet header mismatch. Received: {}. Expected: {}.'
38-
.format(chr(response[0]), chr(9))
39-
)
32+
# Packet 2: First response - (https://wiki.unrealadmin.org/UT3_query_protocol#Packet_2:_First_response)
33+
response = await sock.recv()
4034

41-
# Packet 3: Second request - (http://wiki.unrealadmin.org/UT3_query_protocol#Packet_3:_Second_request)
42-
challenge = int(response[5:].decode('ascii').strip('\x00'))
43-
challenge = b'' if challenge == 0 else challenge.to_bytes(4, 'big', signed=True)
35+
if response[0] != 9:
36+
raise InvalidPacketException(
37+
'Packet header mismatch. Received: {}. Expected: {}.'
38+
.format(chr(response[0]), chr(9))
39+
)
4440

45-
request_data = request_h + b'\x00' + timestamp + challenge
46-
sock.send(request_data + b'\xFF\xFF\xFF\x01')
41+
# Packet 3: Second request - (http://wiki.unrealadmin.org/UT3_query_protocol#Packet_3:_Second_request)
42+
challenge = int(response[5:].decode('ascii').strip('\x00'))
43+
challenge = b'' if challenge == 0 else challenge.to_bytes(4, 'big', signed=True)
4744

48-
# Packet 4: Server information response
49-
# (http://wiki.unrealadmin.org/UT3_query_protocol#Packet_4:_Server_information_response)
50-
response = await self.__read(sock)
45+
request_data = request_h + b'\x00' + timestamp + challenge
46+
sock.send(request_data + b'\xFF\xFF\xFF\x01')
5147

52-
sock.close()
48+
# Packet 4: Server information response
49+
# (http://wiki.unrealadmin.org/UT3_query_protocol#Packet_4:_Server_information_response)
50+
response = await self.__read(sock)
5351

5452
br = BinaryReader(response)
5553

opengsq/protocols/quake1.py

+8-10
Original file line numberDiff line numberDiff line change
@@ -89,19 +89,17 @@ def _get_player_match_collections(self, br: BinaryReader):
8989

9090
async def _connect_and_send(self, data):
9191
# Connect to remote host
92-
sock = SocketAsync()
93-
sock.settimeout(self._timeout)
94-
await sock.connect((self._address, self._query_port))
92+
with SocketAsync() as sock:
93+
sock.settimeout(self._timeout)
94+
await sock.connect((self._address, self._query_port))
9595

96-
header = b'\xFF\xFF\xFF\xFF'
96+
header = b'\xFF\xFF\xFF\xFF'
9797

98-
# Send Request
99-
sock.send(header + data + b'\x00')
98+
# Send Request
99+
sock.send(header + data + b'\x00')
100100

101-
# Server response
102-
response_data = await sock.recv()
103-
104-
sock.close()
101+
# Server response
102+
response_data = await sock.recv()
105103

106104
# Remove the last 0x00 if exists (Only if Quake1)
107105
if response_data[-1] == 0:

opengsq/protocols/source.py

+22-24
Original file line numberDiff line numberDiff line change
@@ -189,33 +189,31 @@ async def get_rules(self) -> dict:
189189

190190
async def __connect_and_send_challenge(self, header: __RequestHeader) -> bytes:
191191
# Connect to remote host
192-
sock = SocketAsync()
193-
sock.settimeout(self._timeout)
194-
await sock.connect((self._address, self._query_port))
195-
196-
# Send and receive
197-
request_base = b'\xFF\xFF\xFF\xFF' + header
198-
request_data = request_base
199-
200-
if len(self._challenge) > 0:
201-
request_data += self._challenge
202-
elif header != self.__RequestHeader.A2S_INFO:
203-
request_data += b'\xFF\xFF\xFF\xFF'
192+
with SocketAsync() as sock:
193+
sock.settimeout(self._timeout)
194+
await sock.connect((self._address, self._query_port))
195+
196+
# Send and receive
197+
request_base = b'\xFF\xFF\xFF\xFF' + header
198+
request_data = request_base
204199

205-
sock.send(request_data)
206-
response_data = await self.__receive(sock)
207-
br = BinaryReader(response_data)
208-
header = br.read_byte()
200+
if len(self._challenge) > 0:
201+
request_data += self._challenge
202+
elif header != self.__RequestHeader.A2S_INFO:
203+
request_data += b'\xFF\xFF\xFF\xFF'
209204

210-
# The server may reply with a challenge
211-
if header == self.__ResponseHeader.S2C_CHALLENGE:
212-
self._challenge = br.read()
213-
214-
# Send the challenge and receive
215-
sock.send(request_base + self._challenge)
205+
sock.send(request_data)
216206
response_data = await self.__receive(sock)
217-
218-
sock.close()
207+
br = BinaryReader(response_data)
208+
header = br.read_byte()
209+
210+
# The server may reply with a challenge
211+
if header == self.__ResponseHeader.S2C_CHALLENGE:
212+
self._challenge = br.read()
213+
214+
# Send the challenge and receive
215+
sock.send(request_base + self._challenge)
216+
response_data = await self.__receive(sock)
219217

220218
return response_data
221219

opengsq/socket_async.py

+12-7
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class SocketAsync():
77
class SocketKind(Enum):
88
SOCK_STREAM = auto()
99
SOCK_DGRAM = auto()
10-
10+
1111
@staticmethod
1212
def gethostbyname(hostname: str) -> str:
1313
return socket.gethostbyname(hostname)
@@ -18,6 +18,12 @@ def __init__(self, kind: SocketKind = SocketKind.SOCK_DGRAM):
1818
self.__protocol = None
1919
self.__kind = kind
2020

21+
def __enter__(self):
22+
return self
23+
24+
def __exit__(self, type, value, traceback):
25+
self.close()
26+
2127
def settimeout(self, value: float):
2228
self.__timeout = value
2329

@@ -87,12 +93,11 @@ def error_received(self, exc):
8793

8894
if __name__ == '__main__':
8995
async def test_socket_async():
90-
socket_async = SocketAsync()
91-
socket_async.settimeout(5)
92-
await socket_async.connect(('', 27015))
93-
socket_async.send(b'\xFF\xFF\xFF\xFFTSource Engine Query\x00\xFF\xFF\xFF\xFF')
94-
print(await socket_async.recv())
95-
socket_async.close()
96+
with SocketAsync() as socket_async:
97+
socket_async.settimeout(5)
98+
await socket_async.connect(('122.128.109.245', 27015))
99+
socket_async.send(b'\xFF\xFF\xFF\xFFTSource Engine Query\x00\xFF\xFF\xFF\xFF')
100+
print(await socket_async.recv())
96101

97102
loop = asyncio.get_event_loop()
98103
loop.run_until_complete(test_socket_async())

opengsq/version.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = '1.1.1'
1+
__version__ = '1.2.0'

0 commit comments

Comments
 (0)