14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
from collections.abc import deque
19
except ImportError: # python < 3.7
20
from collections import deque
18
from cStringIO import StringIO
30
from ...trace import mutter
24
from bzrlib.trace import mutter
33
27
class MessageHandler(object):
115
109
self.responder.send_error(exception)
117
111
def byte_part_received(self, byte):
118
if not isinstance(byte, bytes):
119
raise TypeError(byte)
120
112
if self.expecting == 'body':
122
114
# Success. Nothing more to come except the end of message.
123
115
self.expecting = 'end'
125
117
# Error. Expect an error structure.
126
118
self.expecting = 'error'
143
135
def _args_received(self, args):
144
136
self.expecting = 'body'
145
self.request_handler.args_received(args)
137
self.request_handler.dispatch_command(args[0], args[1:])
146
138
if self.request_handler.finished_reading:
147
139
self._response_sent = True
148
140
self.responder.send_response(self.request_handler.response)
220
212
MessageHandler.__init__(self)
221
213
self.status = None
223
self._bytes_parts = deque()
215
self._bytes_parts = collections.deque()
224
216
self._body_started = False
225
217
self._body_stream_status = None
226
218
self._body = None
232
224
self._medium_request = medium_request
234
226
def byte_part_received(self, byte):
235
if not isinstance(byte, bytes):
236
raise TypeError(byte)
237
if byte not in [b'E', b'S']:
227
if byte not in ['E', 'S']:
238
228
raise errors.SmartProtocolError(
239
229
'Unknown response status: %r' % (byte,))
240
230
if self._body_started:
253
243
self._bytes_parts.append(bytes)
255
245
def structure_part_received(self, structure):
256
if not isinstance(structure, tuple):
246
if type(structure) is not tuple:
257
247
raise errors.SmartProtocolError(
258
248
'Args structure is not a sequence: %r' % (structure,))
259
249
if not self._body_started:
263
253
% (structure, self.args))
264
254
self.args = structure
266
if self._body_stream_status != b'E':
256
if self._body_stream_status != 'E':
267
257
raise errors.SmartProtocolError(
268
258
'Unexpected structure received after body: %r'
284
274
self.finished_reading = True
285
275
self._medium_request.finished_reading()
287
data = self._medium_request.read_bytes(next_read_size)
277
bytes = self._medium_request.read_bytes(next_read_size)
289
279
# end of file encountered reading from server
290
280
if 'hpss' in debug.debug_flags:
296
286
"Unexpected end of message. "
297
287
"Please check connectivity and permissions, and report a bug "
298
288
"if problems persist.")
299
self._protocol_decoder.accept_bytes(data)
289
self._protocol_decoder.accept_bytes(bytes)
301
291
def protocol_error(self, exception):
302
292
# Whatever the error is, we're done with this request.
311
301
self._wait_for_response_end()
312
302
if 'hpss' in debug.debug_flags:
313
303
mutter(' result: %r', self.args)
314
if self.status == b'E':
304
if self.status == 'E':
315
305
self._wait_for_response_end()
316
_raise_smart_server_error(self.args)
306
_translate_error(self.args)
317
307
return tuple(self.args)
319
309
def read_body_bytes(self, count=-1):
329
319
# != -1. (2008/04/30, Andrew Bennetts)
330
320
if self._body is None:
331
321
self._wait_for_response_end()
332
body_bytes = b''.join(self._bytes_parts)
322
body_bytes = ''.join(self._bytes_parts)
333
323
if 'hpss' in debug.debug_flags:
334
324
mutter(' %d body bytes read', len(body_bytes))
335
self._body = BytesIO(body_bytes)
325
self._body = StringIO(body_bytes)
336
326
self._bytes_parts = None
337
327
return self._body.read(count)
344
334
mutter(' %d byte part read', len(bytes_part))
346
336
self._read_more()
347
if self._body_stream_status == b'E':
348
_raise_smart_server_error(self._body_error_args)
337
if self._body_stream_status == 'E':
338
_translate_error(self._body_error_args)
350
340
def cancel_read_body(self):
351
341
self._wait_for_response_end()
354
def _raise_smart_server_error(error_tuple):
355
"""Raise exception based on tuple received from smart server
357
Specific error translation is handled by breezy.bzr.remote._translate_error
359
if error_tuple[0] == b'UnknownMethod':
360
raise errors.UnknownSmartMethod(error_tuple[1])
361
raise errors.ErrorFromSmartServer(error_tuple)
344
def _translate_error(error_tuple):
345
# Many exceptions need some state from the requestor to be properly
346
# translated (e.g. they need a branch object). So this only translates a
347
# few errors, and the rest are turned into a generic ErrorFromSmartServer.
348
error_name = error_tuple[0]
349
error_args = error_tuple[1:]
350
if error_name == 'UnknownMethod':
351
raise errors.UnknownSmartMethod(error_args[0])
352
if error_name == 'LockContention':
353
raise errors.LockContention('(remote lock)')
354
elif error_name == 'LockFailed':
355
raise errors.LockFailed(*error_args[:2])
356
elif error_name == 'FileExists':
357
raise errors.FileExists(error_args[0])
358
elif error_name == 'NoSuchFile':
359
raise errors.NoSuchFile(error_args[0])
361
raise errors.ErrorFromSmartServer(error_tuple)