def _translate_error(self, resp, orig_path=None): """Raise an exception from a response""" if resp is None: what = None else: what = resp[0] if what == 'ok': return elif what == 'NoSuchFile': if orig_path is not None: error_path = orig_path else: error_path = resp[1] raise errors.NoSuchFile(error_path) elif what == 'error': raise errors.SmartProtocolError(unicode(resp[1])) elif what == 'FileExists': raise errors.FileExists(resp[1]) elif what == 'DirectoryNotEmpty': raise errors.DirectoryNotEmpty(resp[1]) elif what == 'ShortReadvError': raise errors.ShortReadvError(resp[1], int(resp[2]), int(resp[3]), int(resp[4])) elif what in ('UnicodeEncodeError', 'UnicodeDecodeError'): encoding = str(resp[1]) # encoding must always be a string val = resp[2] start = int(resp[3]) end = int(resp[4]) reason = str(resp[5]) # reason must always be a string if val.startswith('u:'): val = val[2:].decode('utf-8') elif val.startswith('s:'): val = val[2:].decode('base64') if what == 'UnicodeDecodeError': raise UnicodeDecodeError(encoding, val, start, end, reason) elif what == 'UnicodeEncodeError': raise UnicodeEncodeError(encoding, val, start, end, reason) elif what == "ReadOnlyError": raise errors.TransportNotPossible('readonly transport') elif what == "ReadError": if orig_path is not None: error_path = orig_path else: error_path = resp[1] raise errors.ReadError(error_path) elif what == "PermissionDenied": if orig_path is not None: error_path = orig_path else: error_path = resp[1] raise errors.PermissionDenied(error_path) else: raise errors.SmartProtocolError('unexpected smart server error: %r' % (resp,))
def end_received(self): if self.expecting not in ['body', 'end']: raise errors.SmartProtocolError( 'End of message received prematurely (while expecting %s)' % (self.expecting, )) self.expecting = 'nothing' self.request_handler.end_received() if not self.request_handler.finished_reading: raise errors.SmartProtocolError( "Complete conventional request was received, but request " "handler has not finished reading.") if not self._response_sent: self.responder.send_response(self.request_handler.response)
def byte_part_received(self, byte): if byte not in ['E', 'S']: raise errors.SmartProtocolError('Unknown response status: %r' % (byte, )) if self._body_started: if self._body_stream_status is not None: raise errors.SmartProtocolError( 'Unexpected byte part received: %r' % (byte, )) self._body_stream_status = byte else: if self.status is not None: raise errors.SmartProtocolError( 'Unexpected byte part received: %r' % (byte, )) self.status = byte
def byte_part_received(self, byte): if self.expecting == 'body': if byte == 'S': # Success. Nothing more to come except the end of message. self.expecting = 'end' elif byte == 'E': # Error. Expect an error structure. self.expecting = 'error' else: raise errors.SmartProtocolError( 'Non-success status byte in request body: %r' % (byte, )) else: raise errors.SmartProtocolError( 'Unexpected message part: byte(%r)' % (byte, ))
def do_POST_inner(self, chrooted_transport): self.send_response(200) self.send_header("Content-type", "application/octet-stream") if not self.path.endswith('.bzr/smart'): raise AssertionError('POST to path not ending in .bzr/smart: %r' % (self.path, )) t = chrooted_transport.clone(self.path[:-len('.bzr/smart')]) # if this fails, we should return 400 bad request, but failure is # failure for now - RBC 20060919 data_length = int(self.headers['Content-Length']) # TODO: We might like to support streaming responses. 1.0 allows no # Content-length in this case, so for integrity we should perform our # own chunking within the stream. # 1.1 allows chunked responses, and in this case we could chunk using # the HTTP chunking as this will allow HTTP persistence safely, even if # we have to stop early due to error, but we would also have to use the # HTTP trailer facility which may not be widely available. request_bytes = self.rfile.read(data_length) protocol_factory, unused_bytes = medium._get_protocol_factory_for_bytes( request_bytes) out_buffer = StringIO() smart_protocol_request = protocol_factory(t, out_buffer.write, '/') # Perhaps there should be a SmartServerHTTPMedium that takes care of # feeding the bytes in the http request to the smart_protocol_request, # but for now it's simpler to just feed the bytes directly. smart_protocol_request.accept_bytes(unused_bytes) if not (smart_protocol_request.next_read_size() == 0): raise errors.SmartProtocolError( "not finished reading, but all data sent to protocol.") self.send_header("Content-Length", str(len(out_buffer.getvalue()))) self.end_headers() self.wfile.write(out_buffer.getvalue())
def structure_part_received(self, structure): if type(structure) is not tuple: raise errors.SmartProtocolError( 'Args structure is not a sequence: %r' % (structure, )) if not self._body_started: if self.args is not None: raise errors.SmartProtocolError( 'Unexpected structure received: %r (already got %r)' % (structure, self.args)) self.args = structure else: if self._body_stream_status != 'E': raise errors.SmartProtocolError( 'Unexpected structure received after body: %r' % (structure, )) self._body_error_args = structure
def bytes_part_received(self, bytes): if self.expecting == 'body': self._should_finish_body = True self.request_handler.accept_body(bytes) else: raise errors.SmartProtocolError( 'Unexpected message part: bytes(%r)' % (bytes, ))
def structure_part_received(self, structure): if self.expecting == 'args': self._args_received(structure) elif self.expecting == 'error': self._error_received(structure) else: raise errors.SmartProtocolError( 'Unexpected message part: structure(%r)' % (structure, ))
def structure_part_received(self, structure): if self.args_received: raise errors.SmartProtocolError( 'Unexpected message part: structure(%r)' % (structure, )) self.args_received = True self.request_handler.dispatch_command(structure[0], structure[1:]) if self.request_handler.finished_reading: self.responder.send_response(self.request_handler.response)
def send_http_smart_request(self, bytes): try: code, body_filelike = self._post(bytes) if code != 200: raise InvalidHttpResponse( self._remote_path('.bzr/smart'), 'Expected 200 response code, got %r' % (code, )) except errors.InvalidHttpResponse, e: raise errors.SmartProtocolError(str(e))
def do_body(self, body_bytes): """Called if the client sends a body with the request. The do() method is still called, and must have returned None. Must return a SmartServerResponse. """ if body_bytes != '': raise errors.SmartProtocolError('Request does not expect a body')
def send_http_smart_request(self, bytes): try: # Get back the http_transport hold by the weak reference t = self._http_transport_ref() code, body_filelike = t._post(bytes) if code != 200: raise errors.InvalidHttpResponse( t._remote_path('.bzr/smart'), 'Expected 200 response code, got %r' % (code, )) except (errors.InvalidHttpResponse, errors.ConnectionReset), e: raise errors.SmartProtocolError(str(e))
def byte_part_received(self, byte): raise errors.SmartProtocolError('Unexpected message part: byte(%r)' % (byte, ))
# we recognise the protocol version. warning( 'Server does not understand Bazaar network protocol %d,' ' reconnecting. (Upgrade the server to avoid this.)' % (protocol_version,)) self._medium.disconnect() continue except errors.ErrorFromSmartServer: # If we received an error reply from the server, then it # must be ok with this protocol version. self._medium._protocol_version = protocol_version raise else: self._medium._protocol_version = protocol_version return response_tuple, response_handler raise errors.SmartProtocolError( 'Server is not a Bazaar server: ' + str(err)) def _construct_protocol(self, version): request = self._medium.get_request() if version == 3: request_encoder = protocol.ProtocolThreeRequester(request) response_handler = message.ConventionalResponseHandler() response_proto = protocol.ProtocolThreeDecoder( response_handler, expect_version_marker=True) response_handler.setProtoAndMediumRequest(response_proto, request) elif version == 2: request_encoder = protocol.SmartClientRequestProtocolTwo(request) response_handler = request_encoder else: request_encoder = protocol.SmartClientRequestProtocolOne(request) response_handler = request_encoder