瀏覽代碼

net: implement async HTTP/HTTPS requests for Windows and Linux.

legacy
Sam Hocevar 4 年之前
父節點
當前提交
607369b223
共有 4 個文件被更改,包括 102 次插入23 次删除
  1. +9
    -0
      build/autotools/m4/lol-conf.m4
  2. +10
    -2
      doc/tutorial/17_net.cpp
  3. +4
    -3
      src/lol/net/http.h
  4. +79
    -18
      src/net/http.cpp

+ 9
- 0
build/autotools/m4/lol-conf.m4 查看文件

@@ -84,6 +84,15 @@ if test "$ac_cv_have_getopt_long" != "no"; then
fi


dnl Use OpenSSL?
ac_cv_have_openssl=no
AC_CHECK_LIB(ssl, OPENSSL_init_ssl,
[ac_cv_have_openssl=yes
AC_DEFINE(LOL_USE_OPENSSL, 1, Define to 1 to use OpenSSL)
LOL_LIBS="${LOL_LIBS} -lssl -lcrypto"])
AM_CONDITIONAL(LOL_USE_OPENSSL, test "${ac_cv_have_openssl}" = "yes")


dnl Use Bullet Physics?
ac_cv_my_have_bullet="no"
if test "${enable_bullet}" != "no"; then


+ 10
- 2
doc/tutorial/17_net.cpp 查看文件

@@ -30,12 +30,20 @@ public:
{
entity::tick_game(seconds);

if (client.get_status() == lol::net::http::status::success)
switch (client.get_status())
{
lol::msg::info("Downloaded %d bytes: %s\n",
case lol::net::http::status::success:
lol::msg::info("downloaded %d bytes: %s\n",
(int)client.get_result().size(),
client.get_result().c_str());
client.reset();
break;
case lol::net::http::status::error:
lol::msg::info("error downloading %s\n", client.get_url().c_str());
client.reset();
break;
default:
break;
}
}



+ 4
- 3
src/lol/net/http.h 查看文件

@@ -23,8 +23,6 @@ namespace net
namespace http
{

class client_impl;

enum class status : uint8_t
{
ready = 0,
@@ -33,6 +31,8 @@ enum class status : uint8_t
error = 3,
};

class client_impl;

class client
{
public:
@@ -45,8 +45,9 @@ public:
// Reset state
void reset();

// Get status (may be pending) and result
// Get current URL, status (may be pending), and result
status get_status() const;
std::string const & get_url() const;
std::string const & get_result() const;

private:


+ 79
- 18
src/net/http.cpp 查看文件

@@ -12,12 +12,20 @@

#include <lol/engine-internal.h>

#if LOL_USE_OPENSSL
# define CPPHTTPLIB_OPENSSL_SUPPORT 1
#endif

#if __EMSCRIPTEN__
# include <emscripten/fetch.h>
#else
# include <httplib.h>
#endif

#include <utility>
#include <memory>
#include <regex>

namespace lol
{

@@ -31,11 +39,26 @@ class client_impl
{
public:
#if __EMSCRIPTEN__
~client_impl()
{
emscripten_fetch_close(impl->m_fetch);
}

void get(std::string const &url)
{
emscripten_fetch_attr_t attr;
emscripten_fetch_attr_init(&attr);
strcpy(attr.requestMethod, "GET");
attr.userData = impl.get();
attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY;
attr.onsuccess = client_impl::on_success;
attr.onerror = client_impl::on_failure;
impl->m_fetch = emscripten_fetch(&attr, url.c_str());
}

static void on_success(emscripten_fetch_t *fetch)
{
auto *that = (client_impl *)fetch->userData;
msg::info("finished downloading %llu bytes from URL %s.\n",
fetch->numBytes, fetch->url);
that->m_result.assign(fetch->data, fetch->numBytes);
that->m_status = status::success;
}
@@ -50,15 +73,59 @@ public:

emscripten_fetch_t *m_fetch = nullptr;
#else
void get(std::string const& url)
~client_impl()
{
delete m_thread;
}

void get(std::string const& url)
{
// This regex is copied from cpp-httplib
const static std::regex re(
R"(^(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*(?:\?[^#]*)?)(?:#.*)?)");

std::smatch m;
if (!std::regex_match(url, m, re))
{
m_status = status::error;
return;
}

auto scheme = m[1].str();
auto host = m[2].str();
auto path = m[3].str();

#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
if (scheme == "https")
m_client = std::make_unique<httplib::SSLClient>(host);
else
#endif
m_client = std::make_shared<httplib::Client>(host);
m_client->set_follow_location(true);

m_thread = new lol::thread([this, path](thread *)
{
auto res = m_client->Get(path.c_str());
if (res && res->status == 200)
{
m_result = std::move(res->body);
m_status = status::success;
}
else
{
msg::error("downloading %s failed, HTTP failure status code: %d.\n",
m_url.c_str(), res ? res->status : -1);
m_status = status::error;
}
});
}

//httplib::Client &client;
lol::thread *m_thread = nullptr;
std::shared_ptr<httplib::Client> m_client;
#endif

status m_status;
std::string m_url;
std::string m_result;
};

@@ -69,30 +136,19 @@ client::client()

client::~client()
{
#if __EMSCRIPTEN__
emscripten_fetch_close(impl->m_fetch);
#endif
}

void client::get(std::string const &url)
{
impl->m_status = status::pending;
#if __EMSCRIPTEN__
emscripten_fetch_attr_t attr;
emscripten_fetch_attr_init(&attr);
strcpy(attr.requestMethod, "GET");
attr.userData = impl.get();
attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY;
attr.onsuccess = client_impl::on_success;
attr.onerror = client_impl::on_failure;
impl->m_fetch = emscripten_fetch(&attr, url.c_str());
#else
#endif
impl->m_url = url;
impl->get(url);
}

void client::reset()
{
impl->m_status = status::ready;
impl->m_url.assign("");
impl->m_result.assign("");
}

@@ -101,6 +157,11 @@ status client::get_status() const
return impl->m_status;
}

std::string const & client::get_url() const
{
return impl->m_url;
}

std::string const & client::get_result() const
{
return impl->m_result;


Loading…
取消
儲存