Port to websocketpp Web server, Ubuntu LV2 headers.
This commit is contained in:
+447
-1093
File diff suppressed because it is too large
Load Diff
+79
-87
@@ -1,7 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/beast/http.hpp>
|
||||
#include <boost/asio/ip/network_v4.hpp>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
#include <mutex>
|
||||
@@ -11,17 +14,63 @@
|
||||
#include <filesystem>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// forward declaration.
|
||||
|
||||
class websocket_session;
|
||||
|
||||
namespace pipedal {
|
||||
using HttpRequest =boost::beast::http::request<boost::beast::http::string_body>;
|
||||
|
||||
|
||||
class HttpRequest {
|
||||
public:
|
||||
virtual const std::string&body() const = 0;
|
||||
virtual const std::string &method() const = 0;
|
||||
virtual const std::string&get(const std::string&key) const = 0;
|
||||
virtual bool keepAlive() const = 0;
|
||||
};
|
||||
|
||||
class HttpResponse {
|
||||
public:
|
||||
virtual void set(const std::string&key, const std::string&value) = 0;
|
||||
virtual void setContentLength(size_t size) = 0;
|
||||
virtual void setBody(const std::string&body) = 0;
|
||||
virtual void keepAlive(bool value) = 0;
|
||||
};
|
||||
|
||||
|
||||
struct HttpVerb {
|
||||
constexpr static const char * options = "OPTIONS";
|
||||
constexpr static const char * get = "GET";
|
||||
constexpr static const char * post = "POST";
|
||||
constexpr static const char * head = "HEAD";
|
||||
};
|
||||
|
||||
|
||||
class HttpField {
|
||||
public:
|
||||
constexpr static const char * LastModified = "Last-Modified";
|
||||
constexpr static const char* content_length = "Content-Length";
|
||||
constexpr static const char* content_type = "Content-Type";
|
||||
constexpr static const char* cache_control = "Cache-Control";
|
||||
constexpr static const char* content_disposition = "Content-Disposition";
|
||||
constexpr static const char* access_control_allow_origin = "Access-Control-Allow-Origin";
|
||||
constexpr static const char* access_control_allow_methods= "Access-Control-Allow-Methods";
|
||||
constexpr static const char* access_control_allow_headers = "Acess-Control-Allow-Headers";
|
||||
constexpr static const char* origin = "Origin";
|
||||
constexpr static const char* date = "Date";
|
||||
};
|
||||
|
||||
|
||||
//xxx move this to HtmlHelpers.
|
||||
std::string last_modified(const std::filesystem::path& path);
|
||||
|
||||
class BeastServerImpl;
|
||||
|
||||
class SocketHandler {
|
||||
friend class BeastServerImpl;
|
||||
public:
|
||||
|
||||
class IWriteCallback {
|
||||
@@ -33,16 +82,15 @@ public:
|
||||
};
|
||||
|
||||
private:
|
||||
friend class ::websocket_session;
|
||||
|
||||
|
||||
IWriteCallback *writeCallback_;
|
||||
|
||||
public:
|
||||
void setWriteCallback(IWriteCallback *writeCallback) {
|
||||
writeCallback_ = writeCallback;
|
||||
}
|
||||
|
||||
protected:
|
||||
public:
|
||||
virtual void onReceive(const std::string_view&text) = 0;
|
||||
public:
|
||||
std::string getFromAddress() const { return writeCallback_->getFromAddress(); }
|
||||
@@ -76,6 +124,7 @@ class RequestHandler {
|
||||
private:
|
||||
uri target_url_;
|
||||
public:
|
||||
|
||||
RequestHandler(const char*target_url)
|
||||
: target_url_(target_url)
|
||||
{
|
||||
@@ -92,7 +141,7 @@ public:
|
||||
return requestUri;
|
||||
}
|
||||
|
||||
virtual bool wants(boost::beast::http::verb verb,const uri &request_uri) const {
|
||||
virtual bool wants(const std::string& method,const uri &request_uri) const {
|
||||
if (request_uri.segment_count() < target_url_.segment_count())
|
||||
{
|
||||
return false;
|
||||
@@ -107,105 +156,48 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
virtual void head_response(
|
||||
const uri&request_uri,
|
||||
const boost::beast::http::request<boost::beast::http::string_body> &req,
|
||||
boost::beast::http::response<boost::beast::http::empty_body> &res,
|
||||
boost::beast::error_code &ec) = 0;
|
||||
const HttpRequest &req,
|
||||
HttpResponse &res,
|
||||
std::error_code &ec) = 0;
|
||||
|
||||
virtual void get_response(
|
||||
const uri&request_uri,
|
||||
const boost::beast::http::request<boost::beast::http::string_body> &req,
|
||||
boost::beast::http::response<boost::beast::http::string_body> &res,
|
||||
boost::beast::error_code &ec) = 0;
|
||||
const HttpRequest &req,
|
||||
HttpResponse &res,
|
||||
std::error_code &ec) = 0;
|
||||
|
||||
virtual void post_response(
|
||||
const uri&request_uri,
|
||||
const boost::beast::http::request<boost::beast::http::string_body> &req,
|
||||
boost::beast::http::response<boost::beast::http::string_body> &res,
|
||||
boost::beast::error_code &ec)
|
||||
const HttpRequest &req,
|
||||
HttpResponse &res,
|
||||
std::error_code &ec)
|
||||
{
|
||||
get_response(request_uri,req,res,ec);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
class BeastServer {
|
||||
private:
|
||||
boost::asio::ip::address address;
|
||||
unsigned short port;
|
||||
std::string doc_root;
|
||||
int threads;
|
||||
std::mutex log_mutex;
|
||||
std::vector<std::shared_ptr<RequestHandler> > request_handlers;
|
||||
std::vector<std::shared_ptr<ISocketFactory> > socket_factories;
|
||||
std::mutex io_mutex;
|
||||
boost::asio::io_context *pIoContext = nullptr;
|
||||
void*pListener = nullptr;
|
||||
std::thread*pBgThread = nullptr;
|
||||
|
||||
bool logHttpRequests = false;
|
||||
|
||||
bool hasAccessPointGateway = false;
|
||||
boost::asio::ip::network_v4 accessPointGateway;
|
||||
std::string accessPointServerAddress;
|
||||
bool stopping = false;
|
||||
|
||||
|
||||
public:
|
||||
virtual ~BeastServer() { }
|
||||
|
||||
BeastServer(
|
||||
const boost::asio::ip::address& address,
|
||||
int port,
|
||||
const char*rootPath,
|
||||
int threads = 10);
|
||||
virtual void SetLogHttpRequests(bool enableLogging) = 0;
|
||||
|
||||
void Run();
|
||||
void RunInBackground();
|
||||
bool Stopping() const { return this->stopping; }
|
||||
void Stop();
|
||||
void Join();
|
||||
virtual void AddRequestHandler(std::shared_ptr<RequestHandler> requestHandler) = 0;
|
||||
virtual void AddSocketFactory(std::shared_ptr<ISocketFactory> &socketHandler) = 0;
|
||||
|
||||
void SetLogHttpRequests(bool logRequests) { this->logHttpRequests = logRequests; }
|
||||
bool LogHttpRequests() const { return this->logHttpRequests; }
|
||||
boost::asio::io_context& IoContext() {
|
||||
return *pIoContext;
|
||||
}
|
||||
virtual void ShutDown(int timeoutMs) = 0;
|
||||
virtual void Join() = 0;
|
||||
|
||||
void AddRequestHandler(std::shared_ptr<RequestHandler> requestHandler)
|
||||
{
|
||||
request_handlers.push_back(requestHandler);
|
||||
}
|
||||
|
||||
void AddSocketFactory(const std::shared_ptr<ISocketFactory> &socketHandler)
|
||||
{
|
||||
socket_factories.push_back(socketHandler);
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<RequestHandler> > &RequestHandlers() { return request_handlers; }
|
||||
|
||||
const std::string&GetDocRoot() { return doc_root; }
|
||||
|
||||
virtual ~BeastServer();
|
||||
|
||||
std::shared_ptr<ISocketFactory> GetSocketFactory(const uri &request_uri);
|
||||
|
||||
void SetAccessPointGateway(const boost::asio::ip::network_v4 &gateway, const std::string&accessPointServerAddress)
|
||||
{
|
||||
this->accessPointGateway = gateway;
|
||||
this->hasAccessPointGateway = true;
|
||||
this->accessPointServerAddress = accessPointServerAddress;
|
||||
}
|
||||
bool HasAccessPointGateway() const { return hasAccessPointGateway; }
|
||||
boost::asio::ip::network_v4 &GetAccessPointGateway() { return this->accessPointGateway; }
|
||||
const std::string & GetAccessPointServerAddress() const { return this->accessPointServerAddress; }
|
||||
|
||||
public:
|
||||
virtual void onError(boost::system::error_code ec, char const* what);
|
||||
virtual void onWarning(boost::system::error_code ec, char const* what);
|
||||
virtual void onInfo(char const* what);
|
||||
|
||||
virtual void onListenerClosed();
|
||||
virtual void RunInBackground() = 0;
|
||||
};
|
||||
|
||||
|
||||
std::shared_ptr<BeastServer> createBeastServer(const boost::asio::ip::address &address, int port, const char *rootPath, int threads);
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace pipedal;
|
||||
@@ -0,0 +1,43 @@
|
||||
// Copyright (c) 2021 Robin Davies
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#include "pch.h"
|
||||
#include "catch.hpp"
|
||||
|
||||
|
||||
#include "BeastServer.hpp"
|
||||
|
||||
using namespace pipedal;
|
||||
|
||||
TEST_CASE( "BeastServer shutdown", "[beastServerShutdown]" ) {
|
||||
|
||||
auto const address = boost::asio::ip::make_address("0.0.0.0");
|
||||
auto const port = 8081;
|
||||
std::string doc_root = ".";
|
||||
auto const threads = 3;
|
||||
|
||||
auto server = createBeastServer(
|
||||
address,port,doc_root.c_str(),threads);
|
||||
server->RunInBackground();
|
||||
sleep(30000);
|
||||
server->ShutDown(1000);
|
||||
sleep(1);
|
||||
server->Join();
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,217 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
// avoid breaking changes from 1.64 to.71
|
||||
// Note that raspbian only prvides 1.64; ubuntu studio only provides 1.71
|
||||
#define BOOST_BEAST_ALLOW_DEPRECATED
|
||||
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/beast/http.hpp>
|
||||
#include <boost/asio/ip/network_v4.hpp>
|
||||
|
||||
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include "Uri.hpp"
|
||||
#include <string_view>
|
||||
#include <filesystem>
|
||||
|
||||
|
||||
// forward declaration.
|
||||
|
||||
class websocket_session;
|
||||
|
||||
namespace pipedal {
|
||||
using HttpRequest =boost::beast::http::request<boost::beast::http::string_body>;
|
||||
|
||||
|
||||
std::string last_modified(const std::filesystem::path& path);
|
||||
|
||||
class SocketHandler {
|
||||
public:
|
||||
|
||||
class IWriteCallback {
|
||||
public:
|
||||
virtual void close() = 0;
|
||||
|
||||
virtual void writeCallback(const std::string& text) = 0;
|
||||
virtual std::string getFromAddress() const = 0;
|
||||
};
|
||||
|
||||
private:
|
||||
friend class ::websocket_session;
|
||||
|
||||
|
||||
IWriteCallback *writeCallback_;
|
||||
|
||||
void setWriteCallback(IWriteCallback *writeCallback) {
|
||||
writeCallback_ = writeCallback;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void onReceive(const std::string_view&text) = 0;
|
||||
public:
|
||||
std::string getFromAddress() const { return writeCallback_->getFromAddress(); }
|
||||
void receive(const std::string_view&text) {
|
||||
onReceive(text);
|
||||
}
|
||||
void send(const std::string &text) {
|
||||
if (writeCallback_ != nullptr)
|
||||
{
|
||||
writeCallback_->writeCallback(text);
|
||||
}
|
||||
}
|
||||
virtual void Close()
|
||||
{
|
||||
writeCallback_->close();
|
||||
}
|
||||
|
||||
virtual ~SocketHandler() = default;
|
||||
|
||||
virtual void onAttach() { }
|
||||
|
||||
};
|
||||
|
||||
class ISocketFactory {
|
||||
public:
|
||||
virtual bool wants(const uri &request) = 0;
|
||||
virtual std::shared_ptr<SocketHandler> CreateHandler(const uri& request) = 0;
|
||||
};
|
||||
|
||||
class RequestHandler {
|
||||
private:
|
||||
uri target_url_;
|
||||
public:
|
||||
RequestHandler(const char*target_url)
|
||||
: target_url_(target_url)
|
||||
{
|
||||
|
||||
}
|
||||
~RequestHandler() = default;
|
||||
|
||||
virtual bool wantsRedirect(const uri& requestUri)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
uri GetRedirect(const uri& requestUri)
|
||||
{
|
||||
return requestUri;
|
||||
}
|
||||
|
||||
virtual bool wants(boost::beast::http::verb verb,const uri &request_uri) const {
|
||||
if (request_uri.segment_count() < target_url_.segment_count())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < target_url_.segment_count(); ++i)
|
||||
{
|
||||
if (request_uri.segment(i) != target_url_.segment(i))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void head_response(
|
||||
const uri&request_uri,
|
||||
const boost::beast::http::request<boost::beast::http::string_body> &req,
|
||||
boost::beast::http::response<boost::beast::http::empty_body> &res,
|
||||
boost::beast::error_code &ec) = 0;
|
||||
|
||||
virtual void get_response(
|
||||
const uri&request_uri,
|
||||
const boost::beast::http::request<boost::beast::http::string_body> &req,
|
||||
boost::beast::http::response<boost::beast::http::string_body> &res,
|
||||
boost::beast::error_code &ec) = 0;
|
||||
|
||||
virtual void post_response(
|
||||
const uri&request_uri,
|
||||
const boost::beast::http::request<boost::beast::http::string_body> &req,
|
||||
boost::beast::http::response<boost::beast::http::string_body> &res,
|
||||
boost::beast::error_code &ec)
|
||||
{
|
||||
get_response(request_uri,req,res,ec);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
class BeastServer {
|
||||
private:
|
||||
boost::asio::ip::address address;
|
||||
unsigned short port;
|
||||
std::string doc_root;
|
||||
int threads;
|
||||
std::mutex log_mutex;
|
||||
std::vector<std::shared_ptr<RequestHandler> > request_handlers;
|
||||
std::vector<std::shared_ptr<ISocketFactory> > socket_factories;
|
||||
std::mutex io_mutex;
|
||||
boost::asio::io_context *pIoContext = nullptr;
|
||||
void*pListener = nullptr;
|
||||
std::thread*pBgThread = nullptr;
|
||||
|
||||
bool logHttpRequests = false;
|
||||
|
||||
bool hasAccessPointGateway = false;
|
||||
boost::asio::ip::network_v4 accessPointGateway;
|
||||
std::string accessPointServerAddress;
|
||||
bool stopping = false;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
BeastServer(
|
||||
const boost::asio::ip::address& address,
|
||||
int port,
|
||||
const char*rootPath,
|
||||
int threads = 10);
|
||||
|
||||
void Run();
|
||||
void RunInBackground();
|
||||
bool Stopping() const { return this->stopping; }
|
||||
void Stop();
|
||||
void Join();
|
||||
|
||||
void SetLogHttpRequests(bool logRequests) { this->logHttpRequests = logRequests; }
|
||||
bool LogHttpRequests() const { return this->logHttpRequests; }
|
||||
boost::asio::io_context& IoContext() {
|
||||
return *pIoContext;
|
||||
}
|
||||
|
||||
void AddRequestHandler(std::shared_ptr<RequestHandler> requestHandler)
|
||||
{
|
||||
request_handlers.push_back(requestHandler);
|
||||
}
|
||||
|
||||
void AddSocketFactory(const std::shared_ptr<ISocketFactory> &socketHandler)
|
||||
{
|
||||
socket_factories.push_back(socketHandler);
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<RequestHandler> > &RequestHandlers() { return request_handlers; }
|
||||
|
||||
const std::string&GetDocRoot() { return doc_root; }
|
||||
|
||||
virtual ~BeastServer();
|
||||
|
||||
std::shared_ptr<ISocketFactory> GetSocketFactory(const uri &request_uri);
|
||||
|
||||
void SetAccessPointGateway(const boost::asio::ip::network_v4 &gateway, const std::string&accessPointServerAddress)
|
||||
{
|
||||
this->accessPointGateway = gateway;
|
||||
this->hasAccessPointGateway = true;
|
||||
this->accessPointServerAddress = accessPointServerAddress;
|
||||
}
|
||||
bool HasAccessPointGateway() const { return hasAccessPointGateway; }
|
||||
boost::asio::ip::network_v4 &GetAccessPointGateway() { return this->accessPointGateway; }
|
||||
const std::string & GetAccessPointServerAddress() const { return this->accessPointServerAddress; }
|
||||
|
||||
public:
|
||||
virtual void onError(boost::system::error_code ec, char const* what);
|
||||
virtual void onWarning(boost::system::error_code ec, char const* what);
|
||||
virtual void onInfo(char const* what);
|
||||
|
||||
virtual void onListenerClosed();
|
||||
};
|
||||
|
||||
} // namespace pipedal;
|
||||
+11
-1
@@ -149,6 +149,7 @@ add_executable(pipedaltest ${PIPEDAL_SOURCES} testMain.cpp
|
||||
|
||||
SystemConfigFile.hpp SystemConfigFile.cpp
|
||||
SystemConfigFileTest.cpp
|
||||
BeastServerTest.cpp
|
||||
)
|
||||
|
||||
configure_file(config.hpp.in config.hpp)
|
||||
@@ -211,12 +212,21 @@ set (REACT_NOTICES_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../build/src/notices.txt)
|
||||
set (DEBIAN_COPYRIGHT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../debian/copyright)
|
||||
|
||||
# generate Copyright section of settings page.
|
||||
# warning: there may be multiple versions. Pick the latest.
|
||||
if(EXISTS "/usr/share/doc/libboost1.71-dev")
|
||||
set (BOOST_COPYRIGHT_DIR "libboost1.71-dev")
|
||||
elseif(EXISTS "/usr/share/doc/libboost1.67-dev")
|
||||
set (BOOST_COPYRIGHT_DIR "libboost1.67-dev")
|
||||
else()
|
||||
message(ERROR "Boost libary version has changed. Please update me.")
|
||||
endif()
|
||||
|
||||
|
||||
add_custom_command(OUTPUT ${REACT_NOTICES_FILE}
|
||||
COMMAND "$<TARGET_FILE:processcopyrights>"
|
||||
--output ${REACT_NOTICES_FILE}
|
||||
--projectCopyright ${DEBIAN_COPYRIGHT_FILE}
|
||||
liblilv-0-0 libboost1.67-dev libnl-3-dev libnl-3-dev lv2-dev
|
||||
liblilv-0-0 ${BOOST_COPYRIGHT_DIR} libnl-3-dev libnl-3-dev lv2-dev
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
DEPENDS ${DEBIAN_COPYRIGHT_FILE} "$<TARGET_FILE:processcopyrights>"
|
||||
COMMENT "Updating copyright notices."
|
||||
|
||||
+1
-3
@@ -19,12 +19,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lv2/lv2core.lv2/lv2.h"
|
||||
#include "lv2.h"
|
||||
|
||||
#include "lv2/atom.lv2/atom.h"
|
||||
#include "lv2/atom.lv2/util.h"
|
||||
#include "lv2/lv2core.lv2/lv2.h"
|
||||
#include "lv2/log.lv2/log.h"
|
||||
#include "lv2/log.lv2/logger.h"
|
||||
#include "lv2/midi.lv2/midi.h"
|
||||
#include "lv2/urid.lv2/urid.h"
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@
|
||||
#include <lilv/lilv.h>
|
||||
#include "lv2/atom.lv2/atom.h"
|
||||
#include "lv2/atom.lv2/util.h"
|
||||
#include "lv2/lv2core.lv2/lv2.h"
|
||||
#include "lv2.h"
|
||||
#include "lv2/log.lv2/log.h"
|
||||
#include "lv2/log.lv2/logger.h"
|
||||
#include "lv2/midi.lv2/midi.h"
|
||||
|
||||
@@ -41,7 +41,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cassert>
|
||||
#include <lv2/lv2core.lv2/lv2.h>
|
||||
#include <lv2.h>
|
||||
#include <lv2/atom.lv2/atom.h>
|
||||
#include <lv2/midi.lv2/midi.h>
|
||||
#include <lv2/urid.lv2/urid.h>
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
#include "OptionsFeature.hpp"
|
||||
#include "JackConfiguration.hpp"
|
||||
#include "lv2/urid.lv2/urid.h"
|
||||
#include "lv2/lv2core.lv2/lv2.h"
|
||||
#include "lv2.h"
|
||||
#include "lv2/atom.lv2/atom.h"
|
||||
#include "lv2/lv2plug.in/ns/ext/buf-size/buf-size.h"
|
||||
#include "lv2/lv2plug.in/ns/ext/presets/presets.h"
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
#include <filesystem>
|
||||
#include <cmath>
|
||||
|
||||
#include "lv2/lv2core.lv2/lv2.h"
|
||||
#include "lv2.h"
|
||||
#include "Units.hpp"
|
||||
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
|
||||
#include "lv2.h"
|
||||
|
||||
#include "lv2/lv2core.lv2/lv2.h"
|
||||
#include "lv2/log.lv2/log.h"
|
||||
#include "lv2/log.lv2/logger.h"
|
||||
#include "lv2/midi.lv2/midi.h"
|
||||
|
||||
@@ -125,13 +125,11 @@ private:
|
||||
std::string response;
|
||||
|
||||
public:
|
||||
template <typename T> // either execution_context (boost 1.74) or io_context (boost 1.63)
|
||||
Reader(T &ios)
|
||||
Reader(asio::io_service &ios)
|
||||
: socket(ios)
|
||||
{
|
||||
}
|
||||
template <typename T> // either execution_context (boost 1.74) or io_context (boost 1.63)
|
||||
static std::shared_ptr<Reader> Create(T &ios)
|
||||
static std::shared_ptr<Reader> Create(asio::io_service &ios)
|
||||
{
|
||||
return std::make_shared<Reader>(ios);
|
||||
}
|
||||
@@ -290,6 +288,7 @@ class Server
|
||||
{
|
||||
private:
|
||||
tcp::acceptor acceptor_;
|
||||
boost::asio::io_service &io_service;
|
||||
|
||||
void HandleAccept(std::shared_ptr<Reader> connection, const boost::system::error_code &err)
|
||||
{
|
||||
@@ -303,7 +302,7 @@ private:
|
||||
void StartAccept()
|
||||
{
|
||||
// socket
|
||||
std::shared_ptr<Reader> reader = Reader::Create(acceptor_.get_executor().context());
|
||||
std::shared_ptr<Reader> reader = Reader::Create(io_service);
|
||||
|
||||
// asynchronous accept operation and wait for a new connection.
|
||||
acceptor_.async_accept(reader->Socket(),
|
||||
@@ -314,7 +313,9 @@ private:
|
||||
public:
|
||||
//constructor for accepting connection from client
|
||||
Server(boost::asio::io_service &io_service, const tcp::endpoint &endpoint)
|
||||
: acceptor_(io_service, endpoint)
|
||||
: acceptor_(io_service, endpoint),
|
||||
io_service(io_service)
|
||||
|
||||
{
|
||||
StartAccept();
|
||||
}
|
||||
|
||||
+3
-1
@@ -29,8 +29,11 @@
|
||||
using namespace pipedal;
|
||||
using namespace std;
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wunused-result"
|
||||
|
||||
// find on path, but ONLY /usr/bin and /usr/sbin
|
||||
|
||||
|
||||
static std::filesystem::path findOnSystemPath(const std::string &command)
|
||||
{
|
||||
if (command.length() != 0 && command[0] == '/')
|
||||
@@ -76,7 +79,6 @@ void pipedal::SilentSysExec(const char *szCommand)
|
||||
pclose(output);
|
||||
}
|
||||
}
|
||||
|
||||
int pipedal::SysExec(const char *szCommand)
|
||||
{
|
||||
char *args = strdup(szCommand);
|
||||
|
||||
+2
-2
@@ -21,11 +21,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <lilv/lilv.h>
|
||||
#include "lv2/lv2core.lv2/lv2.h"
|
||||
#include "lv2.h"
|
||||
|
||||
#include "lv2/atom.lv2/atom.h"
|
||||
#include "lv2/atom.lv2/util.h"
|
||||
#include "lv2/lv2core.lv2/lv2.h"
|
||||
#include "lv2.h"
|
||||
#include "lv2/log.lv2/log.h"
|
||||
#include "lv2/log.lv2/logger.h"
|
||||
#include "lv2/midi.lv2/midi.h"
|
||||
|
||||
+56
-112
@@ -40,7 +40,6 @@
|
||||
#include <systemd/sd-daemon.h>
|
||||
|
||||
using namespace pipedal;
|
||||
using namespace boost::beast;
|
||||
|
||||
#define PRESET_EXTENSION ".piPreset"
|
||||
#define BANK_EXTENSION ".piBank"
|
||||
@@ -83,7 +82,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool wants(boost::beast::http::verb verb, const uri &request_uri) const
|
||||
virtual bool wants(const std::string& method, const uri &request_uri) const
|
||||
{
|
||||
if (request_uri.segment_count() != 2 || request_uri.segment(0) != "var")
|
||||
{
|
||||
@@ -156,9 +155,9 @@ public:
|
||||
|
||||
virtual void head_response(
|
||||
const uri &request_uri,
|
||||
const boost::beast::http::request<boost::beast::http::string_body> &req,
|
||||
boost::beast::http::response<boost::beast::http::empty_body> &res,
|
||||
boost::beast::error_code &ec)
|
||||
const HttpRequest &req,
|
||||
HttpResponse &res,
|
||||
std::error_code &ec)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -168,10 +167,10 @@ public:
|
||||
std::string content;
|
||||
GetPreset(request_uri, &name, &content);
|
||||
|
||||
res.set(http::field::content_type, "application/octet-stream");
|
||||
res.set(http::field::cache_control, "no-cache");
|
||||
res.set(http::field::content_length, content.length());
|
||||
res.set(http::field::content_disposition, GetContentDispositionHeader(name, PRESET_EXTENSION));
|
||||
res.set(HttpField::content_type, "application/octet-stream");
|
||||
res.set(HttpField::cache_control, "no-cache");
|
||||
res.setContentLength(content.length());
|
||||
res.set(HttpField::content_disposition, GetContentDispositionHeader(name, PRESET_EXTENSION));
|
||||
return;
|
||||
}
|
||||
if (request_uri.segment(1) == "downloadBank")
|
||||
@@ -180,10 +179,10 @@ public:
|
||||
std::string content;
|
||||
GetBank(request_uri, &name, &content);
|
||||
|
||||
res.set(http::field::content_type, "application/octet-stream");
|
||||
res.set(http::field::cache_control, "no-cache");
|
||||
res.set(http::field::content_length, content.length());
|
||||
res.set(http::field::content_disposition, GetContentDispositionHeader(name, BANK_EXTENSION));
|
||||
res.set(HttpField::content_type, "application/octet-stream");
|
||||
res.set(HttpField::cache_control, "no-cache");
|
||||
res.set(HttpField::content_disposition, GetContentDispositionHeader(name, BANK_EXTENSION));
|
||||
res.setContentLength(content.length());
|
||||
return;
|
||||
}
|
||||
throw PiPedalException("Not found.");
|
||||
@@ -203,9 +202,9 @@ public:
|
||||
|
||||
virtual void get_response(
|
||||
const uri &request_uri,
|
||||
const boost::beast::http::request<boost::beast::http::string_body> &req,
|
||||
boost::beast::http::response<boost::beast::http::string_body> &res,
|
||||
boost::beast::error_code &ec)
|
||||
const HttpRequest &req,
|
||||
HttpResponse &res,
|
||||
std::error_code &ec)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -215,11 +214,11 @@ public:
|
||||
std::string content;
|
||||
GetPreset(request_uri, &name, &content);
|
||||
|
||||
res.set(http::field::content_type, "application/octet-stream");
|
||||
res.set(http::field::cache_control, "no-cache");
|
||||
res.set(http::field::content_length, content.length());
|
||||
res.set(http::field::content_disposition, GetContentDispositionHeader(name, PRESET_EXTENSION));
|
||||
res.body() = content;
|
||||
res.set(HttpField::content_type, "application/octet-stream");
|
||||
res.set(HttpField::cache_control, "no-cache");
|
||||
res.setContentLength(content.length());
|
||||
res.set(HttpField::content_disposition, GetContentDispositionHeader(name, PRESET_EXTENSION));
|
||||
res.setBody(content);
|
||||
}
|
||||
else if (request_uri.segment(1) == "downloadBank")
|
||||
{
|
||||
@@ -227,11 +226,11 @@ public:
|
||||
std::string content;
|
||||
GetBank(request_uri, &name, &content);
|
||||
|
||||
res.set(http::field::content_type, "application/octet-stream");
|
||||
res.set(http::field::cache_control, "no-cache");
|
||||
res.set(http::field::content_length, content.length());
|
||||
res.set(http::field::content_disposition, GetContentDispositionHeader(name, BANK_EXTENSION));
|
||||
res.body() = content;
|
||||
res.set(HttpField::content_type, "application/octet-stream");
|
||||
res.set(HttpField::cache_control, "no-cache");
|
||||
res.setContentLength(content.length());
|
||||
res.set(HttpField::content_disposition, GetContentDispositionHeader(name, BANK_EXTENSION));
|
||||
res.setBody(content);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -252,15 +251,15 @@ public:
|
||||
}
|
||||
virtual void post_response(
|
||||
const uri &request_uri,
|
||||
const boost::beast::http::request<boost::beast::http::string_body> &req,
|
||||
boost::beast::http::response<boost::beast::http::string_body> &res,
|
||||
boost::beast::error_code &ec)
|
||||
const HttpRequest &req,
|
||||
HttpResponse &res,
|
||||
std::error_code &ec)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (request_uri.segment(1) == "uploadPreset")
|
||||
{
|
||||
std::string presetBody = req.body();
|
||||
const std::string& presetBody = req.body();
|
||||
std::stringstream s(presetBody);
|
||||
json_reader reader(s);
|
||||
|
||||
@@ -276,19 +275,19 @@ public:
|
||||
|
||||
uint64_t instanceId = model->uploadPreset(bankFile, uploadAfter);
|
||||
|
||||
res.set(http::field::content_type, "application/json");
|
||||
res.set(http::field::cache_control, "no-cache");
|
||||
res.set(HttpField::content_type, "application/json");
|
||||
res.set(HttpField::cache_control, "no-cache");
|
||||
std::stringstream sResult;
|
||||
sResult << instanceId;
|
||||
std::string result = sResult.str();
|
||||
res.set(http::field::content_length, result.length());
|
||||
res.setContentLength(result.length());
|
||||
|
||||
res.body() = result;
|
||||
res.setBody(result);
|
||||
}
|
||||
else if (request_uri.segment(1) == "uploadBank")
|
||||
{
|
||||
std::string presetBody = req.body();
|
||||
std::stringstream s(presetBody);
|
||||
const std::string& presetBody = req.body();
|
||||
std::istringstream s(presetBody);
|
||||
json_reader reader(s);
|
||||
|
||||
uint64_t uploadAfter = -1;
|
||||
@@ -303,14 +302,14 @@ public:
|
||||
|
||||
uint64_t instanceId = model->uploadBank(bankFile, uploadAfter);
|
||||
|
||||
res.set(http::field::content_type, "application/json");
|
||||
res.set(http::field::cache_control, "no-cache");
|
||||
res.set(HttpField::content_type, "application/json");
|
||||
res.set(HttpField::cache_control, "no-cache");
|
||||
std::stringstream sResult;
|
||||
sResult << instanceId;
|
||||
std::string result = sResult.str();
|
||||
res.set(http::field::content_length, result.length());
|
||||
res.setContentLength(result.length());
|
||||
|
||||
res.body() = result;
|
||||
res.setBody(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -354,81 +353,31 @@ public:
|
||||
}
|
||||
virtual ~InterceptConfig() {}
|
||||
|
||||
virtual void head_response(
|
||||
const uri &request_uri,
|
||||
const boost::beast::http::request<boost::beast::http::string_body> &req,
|
||||
boost::beast::http::response<boost::beast::http::empty_body> &res,
|
||||
boost::beast::error_code &ec)
|
||||
virtual void head_response(
|
||||
const uri&request_uri,
|
||||
const HttpRequest &req,
|
||||
HttpResponse &res,
|
||||
std::error_code &ec)
|
||||
{
|
||||
res.set(http::field::content_type, "application/json");
|
||||
res.set(http::field::cache_control, "no-cache");
|
||||
res.content_length(response.length());
|
||||
res.set(HttpField::content_type, "application/json");
|
||||
res.set(HttpField::cache_control, "no-cache");
|
||||
res.setContentLength(response.length());
|
||||
return;
|
||||
}
|
||||
|
||||
virtual void get_response(
|
||||
const uri &request_uri,
|
||||
const boost::beast::http::request<boost::beast::http::string_body> &req,
|
||||
boost::beast::http::response<boost::beast::http::string_body> &res,
|
||||
boost::beast::error_code &ec)
|
||||
const HttpRequest &req,
|
||||
HttpResponse &res,
|
||||
std::error_code &ec)
|
||||
{
|
||||
res.set(http::field::content_type, "application/json");
|
||||
res.set(http::field::cache_control, "no-cache");
|
||||
res.content_length(response.length());
|
||||
res.body() = response;
|
||||
res.set(HttpField::content_type, "application/json");
|
||||
res.set(HttpField::cache_control, "no-cache");
|
||||
res.setContentLength(response.length());
|
||||
res.setBody(response);
|
||||
}
|
||||
};
|
||||
|
||||
class ReactRedirector : public RequestHandler
|
||||
{
|
||||
PiPedalConfiguration config;
|
||||
|
||||
public:
|
||||
ReactRedirector(const PiPedalConfiguration &config)
|
||||
: RequestHandler("/"),
|
||||
config(config)
|
||||
|
||||
{
|
||||
}
|
||||
virtual ~ReactRedirector() {}
|
||||
|
||||
virtual bool wantsRedirect(const uri &requestUri)
|
||||
{
|
||||
if (requestUri.segment_count() == 0 || (requestUri.segment_count() == 1 && requestUri.segment(0) == "index.htm"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
uri GetRedirect(const uri &requestUri)
|
||||
{
|
||||
return requestUri;
|
||||
}
|
||||
|
||||
virtual bool wants(boost::beast::http::verb verb, const uri &request_uri) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void head_response(
|
||||
const uri &request_uri,
|
||||
const boost::beast::http::request<boost::beast::http::string_body> &req,
|
||||
boost::beast::http::response<boost::beast::http::empty_body> &res,
|
||||
boost::beast::error_code &ec)
|
||||
{
|
||||
ec = errc::make_error_code(errc::no_such_file_or_directory);
|
||||
return;
|
||||
}
|
||||
|
||||
virtual void get_response(
|
||||
const uri &request_uri,
|
||||
const boost::beast::http::request<boost::beast::http::string_body> &req,
|
||||
boost::beast::http::response<boost::beast::http::string_body> &res,
|
||||
boost::beast::error_code &ec)
|
||||
{
|
||||
ec = errc::make_error_code(errc::no_such_file_or_directory);
|
||||
}
|
||||
};
|
||||
|
||||
static bool isJackServiceRunning()
|
||||
{
|
||||
@@ -553,18 +502,13 @@ int main(int argc, char *argv[])
|
||||
|
||||
auto const threads = std::max<int>(1, configuration.GetThreads());
|
||||
|
||||
server = std::make_shared<BeastServer>(
|
||||
server = createBeastServer(
|
||||
address, port, web_root.c_str(), threads);
|
||||
|
||||
Lv2Log::info("Document root: %s Threads: %d", doc_root.c_str(), (int)threads);
|
||||
|
||||
server->SetLogHttpRequests(configuration.LogHttpRequests());
|
||||
|
||||
boost::asio::ip::network_v4 gateway;
|
||||
if (configuration.GetAccessPointGateway(&gateway))
|
||||
{
|
||||
server->SetAccessPointGateway(gateway, configuration.GetAccessPointServerAddress());
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
@@ -655,7 +599,7 @@ int main(int argc, char *argv[])
|
||||
Lv2Log::info("Shutting down gracefully.");
|
||||
model.Close();
|
||||
Lv2Log::info("Stopping web server.");
|
||||
server->Stop();
|
||||
server->ShutDown(5000);
|
||||
server->Join();
|
||||
Lv2Log::info("Shutdown complete.");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user