-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathsession.r2py
101 lines (80 loc) · 3.17 KB
/
session.r2py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# This module wraps communications in a signaling protocol. The purpose is to
# overlay a connection-based protocol with explicit message signaling.
#
# The protocol is to send the size of the message followed by \n and then the
# message itself. The size of a message must be able to be stored in
# sessionmaxdigits. A size of -1 indicates that this side of the connection
# should be considered closed.
#
# Note that the client will block while sending a message, and the receiver
# will block while recieving a message.
#
# While it should be possible to reuse the connectionbased socket for other
# tasks so long as it does not overlap with the time periods when messages are
# being sent, this is inadvisable.
class SessionEOF(Exception):
pass
sessionmaxdigits = 20
# get the next message off of the socket...
def session_recvmessage(socketobj):
messagesizestring = ''
# first, read the number of characters...
for junkcount in range(sessionmaxdigits):
while True:
try:
currentbyte = socketobj.recv(1)
break
except SocketWouldBlockError:
sleep(0.01)
if currentbyte == '\n':
break
# not a valid digit
if currentbyte not in '0123456789' and messagesizestring != '' and currentbyte != '-':
raise ValueError, "Incorrect value in message size header. Found character '%s' in the header." % str(currentbyte)
messagesizestring = messagesizestring + currentbyte
else:
# too large
raise ValueError, "The header message size exceeds the maximum limit of %d." % sessionmaxdigits
try:
messagesize = int(messagesizestring)
except ValueError:
raise ValueError, "Unable to convert the message size '%s' to int." % messagesizestring
# nothing to read...
if messagesize == 0:
return ''
# end of messages
if messagesize == -1:
raise SessionEOF, "Connection Closed. Received a messagesize of -1"
if messagesize < 0:
raise ValueError, "Received a negative message size '%d'" % messagesize
data = ''
while len(data) < messagesize:
try:
chunk = socketobj.recv(messagesize-len(data))
if chunk == '':
raise SessionEOF, "Received an empty string when performing socketobj.recv(). Socket possibly closed."
data = data + chunk
except SocketWouldBlockError:
sleep(0.01)
return data
# a private helper function
def session_sendhelper(socketobj,data):
sentlength = 0
# if I'm still missing some, continue to send (I could have used sendall
# instead but this isn't supported in repy currently)
while sentlength < len(data):
try:
thissent = socketobj.send(data[sentlength:])
sentlength = sentlength + thissent
except SocketWouldBlockError:
sleep(0.01)
# send the message
def session_sendmessage(socketobj,data):
header = str(len(data)) + '\n'
# Sending these piecemeal does not accomplish anything, and can contribute
# to timeout issues when run by constantly overloaded machines.
# session_sendhelper(socketobj,header)
# Concatenate the header and data, rather than sending both separately.
complete_packet = header + data
# session_sendhelper(socketobj,data)
session_sendhelper(socketobj, complete_packet)