ppsspp/ext/native/net/http_client.h

186 lines
5.1 KiB
C
Raw Normal View History

#pragma once
#include <functional>
2013-06-01 00:50:08 +02:00
#include <memory>
#include <thread>
#include "base/basictypes.h"
#include "base/buffer.h"
#include "net/resolve.h"
#ifdef _WIN32
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <winsock2.h>
2017-08-29 22:24:20 +02:00
#include <ws2tcpip.h>
#else
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#endif
namespace net {
class Connection {
2012-10-30 13:20:55 +01:00
public:
Connection();
virtual ~Connection();
2012-10-30 13:20:55 +01:00
// Inits the sockaddr_in.
bool Resolve(const char *host, int port, DNSType type = DNSType::ANY);
bool Connect(int maxTries = 2, double timeout = 20.0f, bool *cancelConnect = nullptr);
2012-10-30 13:20:55 +01:00
void Disconnect();
2012-10-30 13:20:55 +01:00
// Only to be used for bring-up and debugging.
uintptr_t sock() const { return sock_; }
2012-10-30 13:20:55 +01:00
protected:
// Store the remote host here, so we can send it along through HTTP/1.1 requests.
// TODO: Move to http::client?
std::string host_;
int port_;
addrinfo *resolved_;
2012-10-30 13:20:55 +01:00
private:
uintptr_t sock_;
};
2012-10-30 13:20:55 +01:00
} // namespace net
namespace http {
bool GetHeaderValue(const std::vector<std::string> &responseHeaders, const std::string &header, std::string *value);
class Client : public net::Connection {
2012-10-30 13:20:55 +01:00
public:
Client();
~Client();
// Return value is the HTTP return code. 200 means OK. < 0 means some local error.
int GET(const char *resource, Buffer *output, float *progress = nullptr, bool *cancelled = nullptr);
2017-03-11 00:23:49 -05:00
int GET(const char *resource, Buffer *output, std::vector<std::string> &responseHeaders, float *progress = nullptr, bool *cancelled = nullptr);
2012-10-30 13:20:55 +01:00
// Return value is the HTTP return code.
2014-11-25 08:49:05 -08:00
int POST(const char *resource, const std::string &data, const std::string &mime, Buffer *output, float *progress = nullptr);
int POST(const char *resource, const std::string &data, Buffer *output, float *progress = nullptr);
2014-11-25 08:49:05 -08:00
// HEAD, PUT, DELETE aren't implemented yet, but can be done with SendRequest.
int SendRequest(const char *method, const char *resource, const char *otherHeaders = nullptr, float *progress = nullptr, bool *cancelled = nullptr);
int SendRequestWithData(const char *method, const char *resource, const std::string &data, const char *otherHeaders = nullptr, float *progress = nullptr, bool *cancelled = nullptr);
int ReadResponseHeaders(Buffer *readbuf, std::vector<std::string> &responseHeaders, float *progress = nullptr, bool *cancelled = nullptr);
// If your response contains a response, you must read it.
int ReadResponseEntity(Buffer *readbuf, const std::vector<std::string> &responseHeaders, Buffer *output, float *progress = nullptr, bool *cancelled = nullptr);
void SetDataTimeout(double t) {
dataTimeout_ = t;
}
protected:
const char *userAgent_;
const char *httpVersion_;
double dataTimeout_ = -1.0;
};
// Not particularly efficient, but hey - it's a background download, that's pretty cool :P
class Download {
public:
Download(const std::string &url, const std::string &outfile);
~Download();
void Start();
void Join();
2013-06-01 18:59:03 +02:00
// Returns 1.0 when done. That one value can be compared exactly - or just use Done().
float Progress() const { return progress_; }
2013-06-01 18:59:03 +02:00
2013-11-29 17:33:56 +01:00
bool Done() const { return completed_; }
bool Failed() const { return failed_; }
2013-11-29 17:33:56 +01:00
// NOTE! The value of ResultCode is INVALID until Done() returns true.
2013-06-02 23:44:28 +02:00
int ResultCode() const { return resultCode_; }
std::string url() const { return url_; }
std::string outfile() const { return outfile_; }
2013-06-01 18:59:03 +02:00
// If not downloading to a file, access this to get the result.
Buffer &buffer() { return buffer_; }
const Buffer &buffer() const { return buffer_; }
2013-06-01 18:59:03 +02:00
void Cancel() {
cancelled_ = true;
}
2015-10-06 19:07:09 +02:00
bool IsCancelled() const {
return cancelled_;
}
// NOTE: Callbacks are NOT executed until RunCallback is called. This is so that
// the call will end up on the thread that calls g_DownloadManager.Update().
void SetCallback(std::function<void(Download &)> callback) {
callback_ = callback;
}
void RunCallback() {
2013-11-29 12:21:02 +01:00
if (callback_) {
callback_(*this);
}
}
// Just metadata. Convenient for download managers, for example, if set,
// Downloader::GetCurrentProgress won't return it in the results.
bool IsHidden() const { return hidden_; }
void SetHidden(bool hidden) { hidden_ = hidden; }
private:
void Do(); // Actually does the download. Runs on thread.
2019-06-23 12:04:59 -07:00
int PerformGET(const std::string &url);
std::string RedirectLocation(const std::string &baseUrl);
void SetFailed(int code);
2019-09-28 11:40:10 -07:00
float progress_ = 0.0f;
Buffer buffer_;
2019-06-23 12:04:59 -07:00
std::vector<std::string> responseHeaders_;
std::string url_;
std::string outfile_;
2019-09-28 11:40:10 -07:00
std::thread thread_;
int resultCode_ = 0;
bool completed_ = false;
bool failed_ = false;
bool cancelled_ = false;
bool hidden_ = false;
bool joined_ = false;
std::function<void(Download &)> callback_;
};
2013-06-02 23:44:28 +02:00
using std::shared_ptr;
class Downloader {
public:
~Downloader() {
CancelAll();
}
2013-11-18 16:27:39 +01:00
2013-06-02 22:58:55 +10:00
std::shared_ptr<Download> StartDownload(const std::string &url, const std::string &outfile);
std::shared_ptr<Download> StartDownloadWithCallback(
const std::string &url,
const std::string &outfile,
std::function<void(Download &)> callback);
// Drops finished downloads from the list.
void Update();
void CancelAll();
2013-11-29 16:31:19 +01:00
std::vector<float> GetCurrentProgress();
private:
2013-06-02 22:58:55 +10:00
std::vector<std::shared_ptr<Download>> downloads_;
};
} // http