1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 07:27:45 +00:00

ProtocolServer: Stream the downloaded data if possible

This patchset makes ProtocolServer stream the downloads to its client
(LibProtocol), and as such changes the download API; a possible
download lifecycle could be as such:
notation = client->server:'>', server->client:'<', pipe activity:'*'
```
> StartDownload(GET, url, headers, {})
< Response(0, fd 8)
* {data, 1024b}
< HeadersBecameAvailable(0, response_headers, 200)
< DownloadProgress(0, 4K, 1024)
* {data, 1024b}
* {data, 1024b}
< DownloadProgress(0, 4K, 2048)
* {data, 1024b}
< DownloadProgress(0, 4K, 1024)
< DownloadFinished(0, true, 4K)
```

Since managing the received file descriptor is a pain, LibProtocol
implements `Download::stream_into(OutputStream)`, which can be used to
stream the download into any given output stream (be it a file, or
memory, or writing stuff with a delay, etc.).
Also, as some of the users of this API require all the downloaded data
upfront, LibProtocol also implements `set_should_buffer_all_input()`,
which causes the download instance to buffer all the data until the
download is complete, and to call the `on_buffered_download_finish`
hook.
This commit is contained in:
AnotherTest 2020-12-26 17:14:12 +03:30 committed by Andreas Kling
parent 36d642ee75
commit 4a2da10e38
55 changed files with 528 additions and 235 deletions

View file

@ -26,8 +26,9 @@
#pragma once
#include <AK/ByteBuffer.h>
#include <AK/FileStream.h>
#include <AK/HashMap.h>
#include <AK/NonnullOwnPtr.h>
#include <AK/Optional.h>
#include <AK/RefCounted.h>
#include <AK/URL.h>
@ -45,30 +46,35 @@ public:
Optional<u32> status_code() const { return m_status_code; }
Optional<u32> total_size() const { return m_total_size; }
size_t downloaded_size() const { return m_downloaded_size; }
const ByteBuffer& payload() const { return m_payload; }
const HashMap<String, String, CaseInsensitiveStringTraits>& response_headers() const { return m_response_headers; }
void stop();
virtual void set_certificate(String, String);
// FIXME: Want Badge<Protocol>, but can't make one from HttpProtocol, etc.
void set_download_fd(int fd) { m_download_fd = fd; }
int download_fd() const { return m_download_fd; }
protected:
explicit Download(ClientConnection&);
explicit Download(ClientConnection&, NonnullOwnPtr<OutputFileStream>&&);
void did_finish(bool success);
void did_progress(Optional<u32> total_size, u32 downloaded_size);
void set_status_code(u32 status_code) { m_status_code = status_code; }
void did_request_certificates();
void set_payload(const ByteBuffer&);
void set_response_headers(const HashMap<String, String, CaseInsensitiveStringTraits>&);
void set_downloaded_size(size_t size) { m_downloaded_size = size; }
const OutputFileStream& output_stream() const { return *m_output_stream; }
private:
ClientConnection& m_client;
i32 m_id { 0 };
int m_download_fd { -1 }; // Passed to client.
URL m_url;
Optional<u32> m_status_code;
Optional<u32> m_total_size {};
size_t m_downloaded_size { 0 };
ByteBuffer m_payload;
NonnullOwnPtr<OutputFileStream> m_output_stream;
HashMap<String, String, CaseInsensitiveStringTraits> m_response_headers;
};