13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
18
from cStringIO import StringIO
84
84
"Conventional" is used in the sense described in
85
85
doc/developers/network-protocol.txt: a simple message with arguments and an
89
* args: expecting args
90
* body: expecting body (terminated by receiving a post-body status)
91
* error: expecting post-body error
92
* end: expecting end of message
96
89
def __init__(self, request_handler, responder):
97
90
MessageHandler.__init__(self)
98
91
self.request_handler = request_handler
99
92
self.responder = responder
100
self.expecting = 'args'
101
self._should_finish_body = False
102
self._response_sent = False
93
self.args_received = False
104
95
def protocol_error(self, exception):
105
96
if self.responder.response_sent:
109
100
self.responder.send_error(exception)
111
102
def byte_part_received(self, byte):
112
if self.expecting == 'body':
114
# Success. Nothing more to come except the end of message.
115
self.expecting = 'end'
117
# Error. Expect an error structure.
118
self.expecting = 'error'
120
raise errors.SmartProtocolError(
121
'Non-success status byte in request body: %r' % (byte,))
123
raise errors.SmartProtocolError(
124
'Unexpected message part: byte(%r)' % (byte,))
103
raise errors.SmartProtocolError(
104
'Unexpected message part: byte(%r)' % (byte,))
126
106
def structure_part_received(self, structure):
127
if self.expecting == 'args':
128
self._args_received(structure)
129
elif self.expecting == 'error':
130
self._error_received(structure)
107
if self.args_received:
132
108
raise errors.SmartProtocolError(
133
109
'Unexpected message part: structure(%r)' % (structure,))
135
def _args_received(self, args):
136
self.expecting = 'body'
137
self.request_handler.args_received(args)
110
self.args_received = True
111
self.request_handler.dispatch_command(structure[0], structure[1:])
138
112
if self.request_handler.finished_reading:
139
self._response_sent = True
140
113
self.responder.send_response(self.request_handler.response)
141
self.expecting = 'end'
143
def _error_received(self, error_args):
144
self.expecting = 'end'
145
self.request_handler.post_body_error_received(error_args)
147
115
def bytes_part_received(self, bytes):
148
if self.expecting == 'body':
149
self._should_finish_body = True
150
self.request_handler.accept_body(bytes)
152
raise errors.SmartProtocolError(
153
'Unexpected message part: bytes(%r)' % (bytes,))
155
def end_received(self):
156
if self.expecting not in ['body', 'end']:
157
raise errors.SmartProtocolError(
158
'End of message received prematurely (while expecting %s)'
160
self.expecting = 'nothing'
161
self.request_handler.end_received()
116
# Note that there's no intrinsic way to distinguish a monolithic body
117
# from a chunk stream. A request handler knows which it is expecting
118
# (once the args have been received), so it should be able to do the
120
self.request_handler.accept_body(bytes)
121
self.request_handler.end_of_body()
162
122
if not self.request_handler.finished_reading:
163
123
raise errors.SmartProtocolError(
164
"Complete conventional request was received, but request "
165
"handler has not finished reading.")
166
if not self._response_sent:
167
self.responder.send_response(self.request_handler.response)
124
"Conventional request body was received, but request handler "
125
"has not finished reading.")
126
self.responder.send_response(self.request_handler.response)
170
129
class ResponseHandler(object):
243
202
self._bytes_parts.append(bytes)
245
204
def structure_part_received(self, structure):
246
if type(structure) is not tuple:
205
if type(structure) is not list:
247
206
raise errors.SmartProtocolError(
248
207
'Args structure is not a sequence: %r' % (structure,))
208
structure = tuple(structure)
249
209
if not self._body_started:
250
210
if self.args is not None:
251
211
raise errors.SmartProtocolError(
283
243
self._protocol_decoder._get_in_buffer()[:10],
284
244
self._protocol_decoder.state_accept.__name__)
285
245
raise errors.ConnectionReset(
286
"Unexpected end of message. "
287
"Please check connectivity and permissions, and report a bug "
288
"if problems persist.")
246
"please check connectivity and permissions",
247
"(and try -Dhpss if further diagnosis is required)")
289
248
self._protocol_decoder.accept_bytes(bytes)
291
250
def protocol_error(self, exception):