def testStreaming(self): bin_data = os.urandom(20) f = Msgpack.FilePart("%s/users.json" % config.data_dir, "rb") f.read_bytes = 30 data = {"cmd": "response", "body": f, "bin": bin_data} out_buff = io.BytesIO() Msgpack.stream(data, out_buff.write) out_buff.seek(0) data_packb = { "cmd": "response", "body": open("%s/users.json" % config.data_dir, "rb").read(30), "bin": bin_data } out_buff.seek(0) data_unpacked = Msgpack.unpack(out_buff.read()) assert data_unpacked == data_packb assert data_unpacked["cmd"] == "response" assert type(data_unpacked["body"]) == bytes
def handleGetFile(self, params, streaming=False): site = self.sites.get(params["site"]) if not site or not site.isServing(): # Site unknown or not serving self.response({"error": "Unknown site"}) self.connection.badAction(5) return False try: file_path = site.storage.getPath(params["inner_path"]) if streaming: file_obj = site.storage.open(params["inner_path"]) else: file_obj = Msgpack.FilePart(file_path, "rb") with file_obj as file: file.seek(params["location"]) read_bytes = params.get("read_bytes", FILE_BUFF) file_size = os.fstat(file.fileno()).st_size if file_size > read_bytes: # Check if file is readable at current position (for big files) if not self.isReadable(site, params["inner_path"], file, params["location"]): raise RequestError( "File not readable at position: %s" % params["location"]) else: if params.get( "file_size") and params["file_size"] != file_size: self.connection.badAction(2) raise RequestError( "File size does not match: %sB != %sB" % (params["file_size"], file_size)) if not streaming: file.read_bytes = read_bytes if params["location"] > file_size: self.connection.badAction(5) raise RequestError("Bad file location") if streaming: back = { "size": file_size, "location": min(file.tell() + read_bytes, file_size), "stream_bytes": min(read_bytes, file_size - params["location"]) } self.response(back) self.sendRawfile(file, read_bytes=read_bytes) else: back = { "body": file, "size": file_size, "location": min(file.tell() + file.read_bytes, file_size) } self.response(back, streaming=True) bytes_sent = min( read_bytes, file_size - params["location"]) # Number of bytes we going to send site.settings["bytes_sent"] = site.settings.get( "bytes_sent", 0) + bytes_sent if config.debug_socket: self.log.debug("File %s at position %s sent %s bytes" % (file_path, params["location"], bytes_sent)) # Add peer to site if not added before connected_peer = site.addPeer(self.connection.ip, self.connection.port, source="request") if connected_peer: # Just added connected_peer.connect( self.connection) # Assign current connection to peer return { "bytes_sent": bytes_sent, "file_size": file_size, "location": params["location"] } except RequestError as err: self.log.debug("GetFile %s %s request error: %s" % (self.connection, params["inner_path"], Debug.formatException(err))) self.response({"error": "File read error: %s" % err}) except OSError as err: if config.verbose: self.log.debug("GetFile read error: %s" % Debug.formatException(err)) self.response({"error": "File read error"}) return False except Exception as err: self.log.error("GetFile exception: %s" % Debug.formatException(err)) self.response({"error": "File read exception"}) return False