Parcourir la source

net: implement async HTTP requests for the emscripten backend.

Does not work very well because of CORS restrictions in browsers.
legacy
Sam Hocevar il y a 4 ans
Parent
révision
e1c47e9e03
7 fichiers modifiés avec 219 ajouts et 16 suppressions
  1. +1
    -0
      .gitignore
  2. +55
    -0
      doc/tutorial/17_net.cpp
  3. +66
    -0
      doc/tutorial/17_net.vcxproj
  4. +5
    -1
      doc/tutorial/Makefile.am
  5. +19
    -0
      lol.sln
  6. +16
    -2
      src/lol/net/http.h
  7. +57
    -13
      src/net/http.cpp

+ 1
- 0
.gitignore Voir le fichier

@@ -66,6 +66,7 @@ build/visualstudio/ipch
build/visualstudio/*.log
build/visualstudio/*.XGD
# Emscripten cruft
a.out*
doc/samples/*.html
doc/samples/*.wasm
doc/samples/*.wasm.*


+ 55
- 0
doc/tutorial/17_net.cpp Voir le fichier

@@ -0,0 +1,55 @@
//
// Lol Engine — HTTP client sample
//
// Copyright © 2016—2020 Sam Hocevar <sam@hocevar.net>
//
// Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
//

#if HAVE_CONFIG_H
# include "config.h"
#endif

#include <lol/engine.h>

class demo : public lol::entity
{
public:
virtual bool init_game() override
{
// Choose URL that works with CORS (cross-origin resource sharing)
client.get("https://api.github.com/");
return true;
}

virtual void tick_game(float seconds) override
{
entity::tick_game(seconds);

if (client.get_status() == 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();
}
}

lol::net::http::client client;
};

int main(int argc, char **argv)
{
lol::sys::init(argc, argv);

lol::Application app("Tutorial 17: HTTP", lol::ivec2(800, 600), 60.0f);
auto p = new demo();
app.Run();

return 0;
}


+ 66
- 0
doc/tutorial/17_net.vcxproj Voir le fichier

@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="LolMacros">
<LolDir Condition="Exists('$(SolutionDir)\lol')">$(SolutionDir)\lol</LolDir>
<LolDir Condition="!Exists('$(SolutionDir)\lol')">$(SolutionDir)</LolDir>
</PropertyGroup>
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|NX64">
<Configuration>Debug</Configuration>
<Platform>NX64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|ORBIS">
<Configuration>Debug</Configuration>
<Platform>ORBIS</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|NX64">
<Configuration>Release</Configuration>
<Platform>NX64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ORBIS">
<Configuration>Release</Configuration>
<Platform>ORBIS</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="17_net.cpp" />
</ItemGroup>
<Import Project="$(LolDir)\build\msbuild\lol-core.props" />
<Import Project="$(LolDir)\build\msbuild\lol-bullet.props" />
<PropertyGroup Label="Globals">
<ProjectGuid>{46910277-18E3-4151-9AD9-DC5B551772A9}</ProjectGuid>
<ConfigurationType>Application</ConfigurationType>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(LolDir)\build\msbuild\lol.config.props" />
<ImportGroup Label="ExtensionSettings">
<Import Project="$(LolDir)\build\msbuild\lolfx.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(LolDir)\build\msbuild\lol.vars.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<Import Project="$(LolDir)\build\msbuild\lol.rules.props" />
<ItemDefinitionGroup />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(LolDir)\build\msbuild\lolfx.targets" />
</ImportGroup>
</Project>

+ 5
- 1
doc/tutorial/Makefile.am Voir le fichier

@@ -11,7 +11,7 @@ tutorials += 01_triangle 02_cube 03_noise 04_texture 05_easymesh \
06_sprite 07_input 08_fbo 09_sound 11_fractal \
12_voronoi 13_shader_builder 14_lua 15_gui
endif
tutorials += 16_movie
tutorials += 16_movie 17_net

01_triangle_SOURCES = 01_triangle.cpp 01_triangle.lolfx
01_triangle_CPPFLAGS = $(AM_CPPFLAGS)
@@ -81,3 +81,7 @@ endif
16_movie_CPPFLAGS = $(AM_CPPFLAGS)
16_movie_DEPENDENCIES = @LOL_DEPS@

17_net_SOURCES = 17_net.cpp
17_net_CPPFLAGS = $(AM_CPPFLAGS)
17_net_DEPENDENCIES = @LOL_DEPS@


+ 19
- 0
lol.sln Voir le fichier

@@ -62,6 +62,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "14_lua", "doc\tutorial\14_l
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "16_movie", "doc\tutorial\16_movie.vcxproj", "{5F5714D0-1C3D-4522-A409-214C5A2951AA}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "17_net", "doc\tutorial\17_net.vcxproj", "{46910277-18E3-4151-9AD9-DC5B551772A9}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "09_sound", "doc\tutorial\09_sound.vcxproj", "{51626A22-DD68-4450-9696-13B03BF7A2C5}"
EndProject
Global
@@ -418,6 +420,22 @@ Global
{5F5714D0-1C3D-4522-A409-214C5A2951AA}.Release|Win32.Build.0 = Release|Win32
{5F5714D0-1C3D-4522-A409-214C5A2951AA}.Release|Win64.ActiveCfg = Release|x64
{5F5714D0-1C3D-4522-A409-214C5A2951AA}.Release|Win64.Build.0 = Release|x64
{46910277-18E3-4151-9AD9-DC5B551772A9}.Debug|NX64.ActiveCfg = Debug|NX64
{46910277-18E3-4151-9AD9-DC5B551772A9}.Debug|NX64.Build.0 = Debug|NX64
{46910277-18E3-4151-9AD9-DC5B551772A9}.Debug|ORBIS.ActiveCfg = Debug|ORBIS
{46910277-18E3-4151-9AD9-DC5B551772A9}.Debug|ORBIS.Build.0 = Debug|ORBIS
{46910277-18E3-4151-9AD9-DC5B551772A9}.Debug|Win32.ActiveCfg = Debug|Win32
{46910277-18E3-4151-9AD9-DC5B551772A9}.Debug|Win32.Build.0 = Debug|Win32
{46910277-18E3-4151-9AD9-DC5B551772A9}.Debug|Win64.ActiveCfg = Debug|x64
{46910277-18E3-4151-9AD9-DC5B551772A9}.Debug|Win64.Build.0 = Debug|x64
{46910277-18E3-4151-9AD9-DC5B551772A9}.Release|NX64.ActiveCfg = Release|NX64
{46910277-18E3-4151-9AD9-DC5B551772A9}.Release|NX64.Build.0 = Release|NX64
{46910277-18E3-4151-9AD9-DC5B551772A9}.Release|ORBIS.ActiveCfg = Release|ORBIS
{46910277-18E3-4151-9AD9-DC5B551772A9}.Release|ORBIS.Build.0 = Release|ORBIS
{46910277-18E3-4151-9AD9-DC5B551772A9}.Release|Win32.ActiveCfg = Release|Win32
{46910277-18E3-4151-9AD9-DC5B551772A9}.Release|Win32.Build.0 = Release|Win32
{46910277-18E3-4151-9AD9-DC5B551772A9}.Release|Win64.ActiveCfg = Release|x64
{46910277-18E3-4151-9AD9-DC5B551772A9}.Release|Win64.Build.0 = Release|x64
{51626A22-DD68-4450-9696-13B03BF7A2C5}.Debug|NX64.ActiveCfg = Debug|NX64
{51626A22-DD68-4450-9696-13B03BF7A2C5}.Debug|NX64.Build.0 = Debug|NX64
{51626A22-DD68-4450-9696-13B03BF7A2C5}.Debug|ORBIS.ActiveCfg = Debug|ORBIS
@@ -463,6 +481,7 @@ Global
{81C83B42-D00A-4FA3-9A3D-80F9D46524BF} = {E74CF679-CA2A-47E9-B1F4-3779D6AC6B04}
{31B96262-1C41-43B9-BA38-27AA385B05DB} = {E74CF679-CA2A-47E9-B1F4-3779D6AC6B04}
{5F5714D0-1C3D-4522-A409-214C5A2951AA} = {E74CF679-CA2A-47E9-B1F4-3779D6AC6B04}
{46910277-18E3-4151-9AD9-DC5B551772A9} = {E74CF679-CA2A-47E9-B1F4-3779D6AC6B04}
{51626A22-DD68-4450-9696-13B03BF7A2C5} = {E74CF679-CA2A-47E9-B1F4-3779D6AC6B04}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution


+ 16
- 2
src/lol/net/http.h Voir le fichier

@@ -25,15 +25,29 @@ namespace http

class client_impl;

enum class status : uint8_t
{
ready = 0,
pending = 1,
success = 2,
error = 3,
};

class client
{
public:
client();
~client();

// Enqueue a query
void get(std::string const &url);
bool is_ready() const;
std::tuple<int, std::string> result();

// Reset state
void reset();

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

private:
std::unique_ptr<client_impl> impl;


+ 57
- 13
src/net/http.cpp Voir le fichier

@@ -10,10 +10,14 @@
// See http://www.wtfpl.net/ for more details.
//

#pragma once

#include <lol/engine-internal.h>

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

namespace lol
{

@@ -23,22 +27,41 @@ namespace net
namespace http
{

#if __EMSCRIPTEN__
class client_impl
{
// FIXME
};
#else
class client_impl
{
public:
#if __EMSCRIPTEN__
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;
}

static void on_failure(emscripten_fetch_t *fetch)
{
auto *that = (client_impl *)fetch->userData;
msg::error("downloading %s failed, HTTP failure status code: %d.\n",
fetch->url, fetch->status);
that->m_status = status::error;
}

emscripten_fetch_t *m_fetch = nullptr;
#else
void get(std::string const& url)
{

}
};

//httplib::Client &client;
#endif

status m_status;
std::string m_result;
};

client::client()
: impl(std::make_unique<client_impl>())
{
@@ -46,20 +69,41 @@ 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
}

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

bool client::is_ready() const
status client::get_status() const
{
return false;
return impl->m_status;
}

std::tuple<int, std::string> client::result()
std::string const & client::get_result() const
{
return std::make_tuple(404, std::string());
return impl->m_result;
}

} // namespace http


Chargement…
Annuler
Enregistrer