Unverified Commit ea39290f authored by Andrea Pappacoda's avatar Andrea Pappacoda Committed by GitHub

Merge branch 'master' into git-format-hook

parents efdc1cac e3c40485
......@@ -128,7 +128,6 @@ SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false
Standard: Latest
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 8
UseCRLF: false
......
......@@ -7,23 +7,23 @@ on:
jobs:
pistacheio-deploy:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install dependencies
run: |
sudo apt-get update && sudo apt-get install -qq npm --no-install-recommends --assume-yes
sudo npm install --global --silent yarn
sudo npm install --global --force --silent npx
sudo apt-get -qq update && sudo apt-get -qq install --assume-yes --no-install-recommends yarnpkg
sudo update-alternatives --install /usr/bin/yarn yarn /usr/bin/yarnpkg 10
sudo yarn global add --silent --no-progress --non-interactive npx
- name: Build docs site
run: |
cd pistache.io
yarn install --non-interactive
yarn build
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
with:
......
......@@ -197,7 +197,7 @@ before_install:
# Check source code formatting
- if [ $TRAVIS_PULL_REQUEST != "false" ]; then changed_src=$(git diff --name-only master...HEAD | egrep "\.(h|cc)$" | grep -v "include/pistache/thirdparty" || [ $? == 1 ]); fi
- if [ ! -z "$changed_src" ]; then git-clang-format-10 --quiet --binary $(which clang-format-10) --diff master HEAD -- $changed_src > ./clang-format-diff; fi
- if [ -s ./clang-format-diff ]; then cat ./clang-format-diff && echo "Format source code according to .clang-format rules. Make sure to run make format" && false; fi
- if [ -s ./clang-format-diff ]; then cat ./clang-format-diff && echo "Format source code according to .clang-format rules. Make sure to run ninja clang-format" && false; fi
install:
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
......
......@@ -20,6 +20,7 @@ option(PISTACHE_BUILD_TESTS "build tests alongside the project" OFF)
option(PISTACHE_ENABLE_NETWORK_TESTS "if tests are built, run ones needing network access" ON)
option(PISTACHE_USE_SSL "add support for SSL server" OFF)
option(PISTACHE_PIC "Enable pistache PIC" ON)
option(PISTACHE_BUILD_FUZZ "Build fuzzer for oss-fuzz" OFF)
# require fat LTO objects in static library
if(CMAKE_INTERPROCEDURAL_OPTIMIZATION OR CMAKE_CXX_FLAGS MATCHES "-flto" OR CMAKE_CXX_FLAGS MATCHES "-flto=thin")
......@@ -102,11 +103,13 @@ if (PISTACHE_BUILD_TESTS)
add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR})
endif()
endif()
enable_testing()
add_subdirectory(tests)
endif()
if (PISTACHE_BUILD_FUZZ)
add_subdirectory(tests/fuzzers)
endif()
# format target
add_custom_target(format
......
......@@ -26,9 +26,7 @@ Pistache has the following third party dependencies
Pistache is released under the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). Contributors are welcome!
Pistache was originally created by Mathieu Stefani, but he is no longer actively maintaining Pistache. A team of volunteers has taken over. To reach the original maintainer, drop a private message to `@octal` in [cpplang Slack channel](https://cpplang.now.sh/).
For those that prefer IRC over Slack, the rag-tag crew of maintainers idle in `#pistache` on Freenode. Please come and join us!
Pistache was originally created by Mathieu Stefani (`@octal`). He continues to contribute to the maintainence and development of Pistache, supported by a team of volunteers. The maintainers can be reached in `#pistache` on [Libera.Chat](https://libera.chat/) (ircs://irc.libera.chat:6697). Please come and join us!
The [Launchpad Team](https://launchpad.net/~pistache+team) administers the daily and stable Ubuntu pre-compiled packages.
......
......@@ -23,10 +23,7 @@ class XProtocolVersion : public Http::Header::Header
public:
NAME("X-Protocol-Version");
XProtocolVersion()
: maj(0)
, min(0)
{ }
XProtocolVersion() = default;
XProtocolVersion(uint32_t major, uint32_t minor)
: maj(major)
......@@ -69,8 +66,8 @@ public:
}
private:
uint32_t maj;
uint32_t min;
uint32_t maj = 0;
uint32_t min = 0;
};
int main()
......
......@@ -13,9 +13,8 @@ class HelloHandler : public Http::Handler
public:
HTTP_PROTOTYPE(HelloHandler)
void onRequest(const Http::Request& request, Http::ResponseWriter response) override
void onRequest(const Http::Request& /*request*/, Http::ResponseWriter response) override
{
UNUSED(request);
response.send(Pistache::Http::Code::Ok, "Hello World\n");
}
};
......
......@@ -29,7 +29,7 @@ struct LoadMonitor
void start()
{
shutdown_ = false;
thread.reset(new std::thread(std::bind(&LoadMonitor::run, this)));
thread = std::make_unique<std::thread>([this] { run(); });
}
void shutdown()
......@@ -95,7 +95,7 @@ class MyHandler : public Http::Handler
using namespace Http;
auto query = req.query();
const auto& query = req.query();
if (query.has("chunked"))
{
std::cout << "Using chunked encoding" << std::endl;
......@@ -166,10 +166,9 @@ class MyHandler : public Http::Handler
}
void onTimeout(
const Http::Request& req,
const Http::Request& /*req*/,
Http::ResponseWriter response) override
{
UNUSED(req);
response
.send(Http::Code::Request_Timeout, "Timeout")
.then([=](ssize_t) {}, PrintException());
......
......@@ -8,9 +8,8 @@ class HelloHandler : public Http::Handler
public:
HTTP_PROTOTYPE(HelloHandler)
void onRequest(const Http::Request& request, Http::ResponseWriter response) override
void onRequest(const Http::Request& /*request*/, Http::ResponseWriter response) override
{
UNUSED(request);
response.send(Pistache::Http::Code::Ok, "Hello World\n");
}
};
......
......@@ -84,7 +84,7 @@ private:
if (it == std::end(metrics))
{
metrics.push_back(Metric(std::move(name), val));
metrics.emplace_back(std::move(name), val);
response.send(Http::Code::Created, std::to_string(val));
}
else
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
......@@ -69,6 +69,3 @@ struct PrintException
};
#define unreachable() __builtin_unreachable()
// Until we require C++17 compiler with [[maybe_unused]]
#define UNUSED(x) (void)(x);
......@@ -7,24 +7,21 @@
#include <chrono>
// Allow compile-time overload
namespace Pistache
namespace Pistache::Const
{
namespace Const
{
static constexpr size_t MaxBacklog = 128;
static constexpr size_t MaxEvents = 1024;
static constexpr size_t MaxBuffer = 4096;
static constexpr size_t DefaultWorkers = 1;
static constexpr size_t MaxBacklog = 128;
static constexpr size_t MaxEvents = 1024;
static constexpr size_t MaxBuffer = 4096;
static constexpr size_t DefaultWorkers = 1;
static constexpr size_t DefaultTimerPoolSize = 128;
static constexpr size_t DefaultTimerPoolSize = 128;
// Defined from CMakeLists.txt in project root
static constexpr size_t DefaultMaxRequestSize = 4096;
static constexpr size_t DefaultMaxResponseSize = std::numeric_limits<uint32_t>::max();
static constexpr auto DefaultHeaderTimeout = std::chrono::seconds(60);
static constexpr auto DefaultBodyTimeout = std::chrono::seconds(60);
static constexpr size_t ChunkSize = 1024;
// Defined from CMakeLists.txt in project root
static constexpr size_t DefaultMaxRequestSize = 4096;
static constexpr size_t DefaultMaxResponseSize = std::numeric_limits<uint32_t>::max();
static constexpr auto DefaultHeaderTimeout = std::chrono::seconds(60);
static constexpr auto DefaultBodyTimeout = std::chrono::seconds(60);
static constexpr size_t ChunkSize = 1024;
static constexpr uint16_t HTTP_STANDARD_PORT = 80;
} // namespace Const
} // namespace Pistache
static constexpr uint16_t HTTP_STANDARD_PORT = 80;
} // namespace Pistache::Const
......@@ -16,133 +16,130 @@
#include <pistache/http_defs.h>
namespace Pistache
namespace Pistache::Http
{
namespace Http
struct Cookie
{
friend std::ostream& operator<<(std::ostream& os, const Cookie& cookie);
struct Cookie
{
friend std::ostream& operator<<(std::ostream& os, const Cookie& cookie);
Cookie(std::string name, std::string value);
Cookie(std::string name, std::string value);
std::string name;
std::string value;
std::string name;
std::string value;
std::optional<std::string> path;
std::optional<std::string> domain;
std::optional<FullDate> expires;
std::optional<std::string> path;
std::optional<std::string> domain;
std::optional<FullDate> expires;
std::optional<int> maxAge;
bool secure;
bool httpOnly;
std::optional<int> maxAge;
bool secure;
bool httpOnly;
std::map<std::string, std::string> ext;
std::map<std::string, std::string> ext;
static Cookie fromRaw(const char* str, size_t len);
static Cookie fromString(const std::string& str);
static Cookie fromRaw(const char* str, size_t len);
static Cookie fromString(const std::string& str);
private:
void write(std::ostream& os) const;
};
private:
void write(std::ostream& os) const;
};
std::ostream& operator<<(std::ostream& os, const Cookie& cookie);
std::ostream& operator<<(std::ostream& os, const Cookie& cookie);
class CookieJar
{
public:
using HashMapCookies = std::unordered_map<std::string, Cookie>; // "value" -> Cookie
using Storage = std::unordered_map<
std::string, HashMapCookies>; // "name" -> Hashmap("value" -> Cookie)
class CookieJar
struct iterator : std::iterator<std::bidirectional_iterator_tag, Cookie>
{
public:
using HashMapCookies = std::unordered_map<std::string, Cookie>; // "value" -> Cookie
using Storage = std::unordered_map<
std::string, HashMapCookies>; // "name" -> Hashmap("value" -> Cookie)
struct iterator : std::iterator<std::bidirectional_iterator_tag, Cookie>
explicit iterator(const Storage::const_iterator& _iterator)
: iter_storage(_iterator)
, iter_cookie_values()
, iter_storage_end()
{ }
iterator(const Storage::const_iterator& _iterator,
const Storage::const_iterator& end)
: iter_storage(_iterator)
, iter_cookie_values()
, iter_storage_end(end)
{
explicit iterator(const Storage::const_iterator& _iterator)
: iter_storage(_iterator)
, iter_cookie_values()
, iter_storage_end()
{ }
iterator(const Storage::const_iterator& _iterator,
const Storage::const_iterator& end)
: iter_storage(_iterator)
, iter_cookie_values()
, iter_storage_end(end)
if (iter_storage != iter_storage_end)
{
if (iter_storage != iter_storage_end)
{
iter_cookie_values = iter_storage->second.begin();
}
iter_cookie_values = iter_storage->second.begin();
}
}
Cookie operator*() const
{
return iter_cookie_values->second; // return iter_storage->second;
}
Cookie operator*() const
{
return iter_cookie_values->second; // return iter_storage->second;
}
const Cookie* operator->() const { return &(iter_cookie_values->second); }
const Cookie* operator->() const { return &(iter_cookie_values->second); }
iterator& operator++()
iterator& operator++()
{
++iter_cookie_values;
if (iter_cookie_values == iter_storage->second.end())
{
++iter_cookie_values;
if (iter_cookie_values == iter_storage->second.end())
{
++iter_storage;
if (iter_storage != iter_storage_end)
iter_cookie_values = iter_storage->second.begin();
}
return *this;
++iter_storage;
if (iter_storage != iter_storage_end)
iter_cookie_values = iter_storage->second.begin();
}
return *this;
}
iterator operator++(int)
iterator operator++(int)
{
iterator ret(iter_storage, iter_storage_end);
++iter_cookie_values;
if (iter_cookie_values == iter_storage->second.end())
{
iterator ret(iter_storage, iter_storage_end);
++iter_cookie_values;
if (iter_cookie_values == iter_storage->second.end())
{
++iter_storage;
if (iter_storage != iter_storage_end) // this check is important
iter_cookie_values = iter_storage->second.begin();
}
return ret;
++iter_storage;
if (iter_storage != iter_storage_end) // this check is important
iter_cookie_values = iter_storage->second.begin();
}
bool operator!=(iterator other) const
{
return iter_storage != other.iter_storage;
}
return ret;
}
bool operator==(iterator other) const
{
return iter_storage == other.iter_storage;
}
bool operator!=(iterator other) const
{
return iter_storage != other.iter_storage;
}
private:
Storage::const_iterator iter_storage;
HashMapCookies::const_iterator iter_cookie_values;
Storage::const_iterator
iter_storage_end; // we need to know where main hashmap ends.
};
bool operator==(iterator other) const
{
return iter_storage == other.iter_storage;
}
private:
Storage::const_iterator iter_storage;
HashMapCookies::const_iterator iter_cookie_values;
Storage::const_iterator
iter_storage_end; // we need to know where main hashmap ends.
};
CookieJar();
CookieJar();
void add(const Cookie& cookie);
void removeAllCookies();
void add(const Cookie& cookie);
void removeAllCookies();
void addFromRaw(const char* str, size_t len);
Cookie get(const std::string& name) const;
void addFromRaw(const char* str, size_t len);
Cookie get(const std::string& name) const;
bool has(const std::string& name) const;
bool has(const std::string& name) const;
iterator begin() const { return iterator(cookies.begin(), cookies.end()); }
iterator begin() const { return iterator(cookies.begin(), cookies.end()); }
iterator end() const { return iterator(cookies.end()); }
iterator end() const { return iterator(cookies.end()); }
private:
Storage cookies;
};
private:
Storage cookies;
};
} // namespace Http
} // namespace Pistache
} // namespace Pistache::Http
This diff is collapsed.
......@@ -13,94 +13,92 @@
#include <chrono>
namespace Pistache
namespace Pistache::Http
{
namespace Http
{
class Endpoint
class Endpoint
{
public:
struct Options
{
public:
struct Options
friend class Endpoint;
Options& threads(int val);
Options& threadsName(const std::string& val);
Options& flags(Flags<Tcp::Options> flags);
Options& flags(Tcp::Options tcp_opts)
{
flags(Flags<Tcp::Options>(tcp_opts));
return *this;
}
Options& backlog(int val);
Options& maxRequestSize(size_t val);
Options& maxResponseSize(size_t val);
template <typename Duration>
Options& headerTimeout(Duration timeout)
{
friend class Endpoint;
Options& threads(int val);
Options& threadsName(const std::string& val);
Options& flags(Flags<Tcp::Options> flags);
Options& flags(Tcp::Options tcp_opts)
{
flags(Flags<Tcp::Options>(tcp_opts));
return *this;
}
Options& backlog(int val);
Options& maxRequestSize(size_t val);
Options& maxResponseSize(size_t val);
template <typename Duration>
Options& headerTimeout(Duration timeout)
{
headerTimeout_ = std::chrono::duration_cast<std::chrono::milliseconds>(timeout);
return *this;
}
template <typename Duration>
Options& bodyTimeout(Duration timeout)
{
bodyTimeout_ = std::chrono::duration_cast<std::chrono::milliseconds>(timeout);
return *this;
}
Options& logger(PISTACHE_STRING_LOGGER_T logger);
[[deprecated("Replaced by maxRequestSize(val)")]] Options&
maxPayload(size_t val);
private:
// Thread options
int threads_;
std::string threadsName_;
// TCP flags
Flags<Tcp::Options> flags_;
// Backlog size
int backlog_;
// Size options
size_t maxRequestSize_;
size_t maxResponseSize_;
// Timeout options
std::chrono::milliseconds headerTimeout_;
std::chrono::milliseconds bodyTimeout_;
PISTACHE_STRING_LOGGER_T logger_;
Options();
};
Endpoint();
explicit Endpoint(const Address& addr);
template <typename... Args>
void initArgs(Args&&... args)
headerTimeout_ = std::chrono::duration_cast<std::chrono::milliseconds>(timeout);
return *this;
}
template <typename Duration>
Options& bodyTimeout(Duration timeout)
{
listener.init(std::forward<Args>(args)...);
bodyTimeout_ = std::chrono::duration_cast<std::chrono::milliseconds>(timeout);
return *this;
}
void init(const Options& options = Options());
void setHandler(const std::shared_ptr<Handler>& handler);
Options& logger(PISTACHE_STRING_LOGGER_T logger);
[[deprecated("Replaced by maxRequestSize(val)")]] Options&
maxPayload(size_t val);
private:
// Thread options
int threads_;
std::string threadsName_;
// TCP flags
Flags<Tcp::Options> flags_;
// Backlog size
int backlog_;
// Size options
size_t maxRequestSize_;
size_t maxResponseSize_;
void bind();
void bind(const Address& addr);
// Timeout options
std::chrono::milliseconds headerTimeout_;
std::chrono::milliseconds bodyTimeout_;
void serve();
void serveThreaded();
PISTACHE_STRING_LOGGER_T logger_;
Options();
};
Endpoint();
explicit Endpoint(const Address& addr);
template <typename... Args>
void initArgs(Args&&... args)
{
listener.init(std::forward<Args>(args)...);
}
void shutdown();
void init(const Options& options = Options());
void setHandler(const std::shared_ptr<Handler>& handler);
/*!
void bind();
void bind(const Address& addr);
void serve();
void serveThreaded();
void shutdown();
/*!
* \brief Use SSL on this endpoint
*
* \param[in] cert Server certificate path
......@@ -121,9 +119,9 @@ namespace Pistache
* [1] https://en.wikipedia.org/wiki/BREACH
* [2] https://en.wikipedia.org/wiki/CRIME
*/
void useSSL(const std::string& cert, const std::string& key, bool use_compression = false);
void useSSL(const std::string& cert, const std::string& key, bool use_compression = false);
/*!
/*!
* \brief Use SSL certificate authentication on this endpoint
*
* \param[in] ca_file Certificate Authority file
......@@ -163,50 +161,49 @@ namespace Pistache
*
* [1] https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_verify.html
*/
void useSSLAuth(std::string ca_file, std::string ca_path = "",
int (*cb)(int, void*) = NULL);
void useSSLAuth(std::string ca_file, std::string ca_path = "",
int (*cb)(int, void*) = nullptr);
bool isBound() const { return listener.isBound(); }
bool isBound() const { return listener.isBound(); }
Port getPort() const { return listener.getPort(); }
Port getPort() const { return listener.getPort(); }
Async::Promise<Tcp::Listener::Load>
requestLoad(const Tcp::Listener::Load& old);
Async::Promise<Tcp::Listener::Load>
requestLoad(const Tcp::Listener::Load& old);
static Options options();
static Options options();
private:
template <typename Method>
void serveImpl(Method method)
{
private:
template <typename Method>
void serveImpl(Method method)
{
#define CALL_MEMBER_FN(obj, pmf) ((obj).*(pmf))
if (!handler_)
throw std::runtime_error("Must call setHandler() prior to serve()");
if (!handler_)
throw std::runtime_error("Must call setHandler() prior to serve()");
listener.setHandler(handler_);
listener.bind();
listener.setHandler(handler_);
listener.bind();
CALL_MEMBER_FN(listener, method)
();
CALL_MEMBER_FN(listener, method)
();
#undef CALL_MEMBER_FN
}
}
std::shared_ptr<Handler> handler_;
Tcp::Listener listener;
std::shared_ptr<Handler> handler_;
Tcp::Listener listener;
Options options_;
PISTACHE_STRING_LOGGER_T logger_ = PISTACHE_NULL_STRING_LOGGER;
};
Options options_;
PISTACHE_STRING_LOGGER_T logger_ = PISTACHE_NULL_STRING_LOGGER;
};
template <typename Handler>
void listenAndServe(Address addr,
const Endpoint::Options& options = Endpoint::options())
{
Endpoint endpoint(addr);
endpoint.init(options);
endpoint.setHandler(make_handler<Handler>());
endpoint.serve();
}
template <typename Handler>
void listenAndServe(Address addr,
const Endpoint::Options& options = Endpoint::options())
{
Endpoint endpoint(addr);
endpoint.init(options);
endpoint.setHandler(make_handler<Handler>());
endpoint.serve();
}
} // namespace Http
} // namespace Pistache
} // namespace Pistache::Http
......@@ -2,26 +2,23 @@
#include <stdexcept>
namespace Pistache
namespace Pistache::Tcp
{
namespace Tcp
{
class SocketError : public std::runtime_error
{
public:
explicit SocketError(const char* what_arg)
: std::runtime_error(what_arg)
{ }
};
class SocketError : public std::runtime_error
{
public:
explicit SocketError(const char* what_arg)
: std::runtime_error(what_arg)
{ }
};
class ServerError : public std::runtime_error
{
public:
explicit ServerError(const char* what_arg)
: std::runtime_error(what_arg)
{ }
};
class ServerError : public std::runtime_error
{
public:
explicit ServerError(const char* what_arg)
: std::runtime_error(what_arg)
{ }
};
} // namespace Tcp
} // namespace Pistache
\ No newline at end of file
} // namespace Pistache::Tcp
......@@ -394,6 +394,7 @@ namespace Pistache
// C++11: std::weak_ptr move constructor is C++14 only so the default
// version of move constructor / assignement operator does not work and we
// have to define it ourself
// We're now using C++17, should this be removed?
ResponseWriter(ResponseWriter&& other);
ResponseWriter& operator=(ResponseWriter&& other) = default;
......@@ -548,7 +549,7 @@ namespace Pistache
class BodyStep : public Step
{
public:
static constexpr auto Id = Meta::Hash::fnv1a("Headers");
static constexpr auto Id = Meta::Hash::fnv1a("Body");
explicit BodyStep(Message* message_)
: Step(message_)
......@@ -616,17 +617,11 @@ namespace Pistache
State parse();
Step* step();
std::chrono::steady_clock::time_point time() const
{
return time_;
}
protected:
std::array<std::unique_ptr<Step>, StepsCount> allSteps;
size_t currentStep = 0;
std::chrono::steady_clock::time_point time_;
private:
ArrayStreamBuf<char> buffer;
StreamCursor cursor;
......@@ -643,7 +638,15 @@ namespace Pistache
void reset() override;
std::chrono::steady_clock::time_point time() const
{
return time_;
}
Request request;
private:
std::chrono::steady_clock::time_point time_;
};
template <>
......@@ -699,7 +702,7 @@ namespace Pistache
static std::shared_ptr<RequestParser> getParser(const std::shared_ptr<Tcp::Peer>& peer);
virtual ~Handler() override { }
~Handler() override = default;
private:
void onConnection(const std::shared_ptr<Tcp::Peer>& peer) override;
......
......@@ -12,10 +12,8 @@
#include <stdexcept>
#include <string>
namespace Pistache
namespace Pistache::Http
{
namespace Http
{
#define HTTP_METHODS \
METHOD(Options, "OPTIONS") \
......@@ -125,126 +123,125 @@ namespace Pistache
CHARSET(Utf32 - LE, "utf-32le") \
CHARSET(Unicode - 11, "unicode-1-1")
enum class Method {
enum class Method {
#define METHOD(m, _) m,
HTTP_METHODS
HTTP_METHODS
#undef METHOD
};
};
enum class Code {
enum class Code {
#define CODE(value, name, _) name = value,
STATUS_CODES
STATUS_CODES
#undef CODE
};
};
enum class Version {
Http10, // HTTP/1.0
Http11 // HTTP/1.1
};
enum class Version {
Http10, // HTTP/1.0
Http11 // HTTP/1.1
};
enum class ConnectionControl { Close,
KeepAlive,
Ext };
enum class ConnectionControl { Close,
KeepAlive,
Ext };
enum class Expectation { Continue,
Ext };
enum class Expectation { Continue,
Ext };
class CacheDirective
{
public:
enum Directive {
NoCache,
NoStore,
MaxAge,
MaxStale,
MinFresh,
NoTransform,
OnlyIfCached,
Public,
Private,
MustRevalidate,
ProxyRevalidate,
SMaxAge,
Ext
};
CacheDirective()
: directive_()
, data()
{ }
explicit CacheDirective(Directive directive);
CacheDirective(Directive directive, std::chrono::seconds delta);
Directive directive() const { return directive_; }
std::chrono::seconds delta() const;
private:
void init(Directive directive, std::chrono::seconds delta);
Directive directive_;
// Poor way of representing tagged unions in C++
union
{
uint64_t maxAge;
uint64_t sMaxAge;
uint64_t maxStale;
uint64_t minFresh;
} data;
class CacheDirective
{
public:
enum Directive {
NoCache,
NoStore,
MaxAge,
MaxStale,
MinFresh,
NoTransform,
OnlyIfCached,
Public,
Private,
MustRevalidate,
ProxyRevalidate,
SMaxAge,
Ext
};
// 3.3.1 Full Date
class FullDate
CacheDirective()
: directive_()
, data()
{ }
explicit CacheDirective(Directive directive);
CacheDirective(Directive directive, std::chrono::seconds delta);
Directive directive() const { return directive_; }
std::chrono::seconds delta() const;
private:
void init(Directive directive, std::chrono::seconds delta);
Directive directive_;
// Poor way of representing tagged unions in C++
union
{
public:
using time_point = std::chrono::system_clock::time_point;
FullDate()
: date_()
{ }
uint64_t maxAge;
uint64_t sMaxAge;
uint64_t maxStale;
uint64_t minFresh;
} data;
};
enum class Type { RFC1123,
RFC850,
AscTime };
// 3.3.1 Full Date
class FullDate
{
public:
using time_point = std::chrono::system_clock::time_point;
FullDate()
: date_()
{ }
explicit FullDate(time_point date)
: date_(date)
{ }
enum class Type { RFC1123,
RFC850,
AscTime };
time_point date() const { return date_; }
void write(std::ostream& os, Type type = Type::RFC1123) const;
explicit FullDate(time_point date)
: date_(date)
{ }
static FullDate fromString(const std::string& str);
time_point date() const { return date_; }
void write(std::ostream& os, Type type = Type::RFC1123) const;
private:
time_point date_;
};
static FullDate fromString(const std::string& str);
private:
time_point date_;
};
const char* methodString(Method method);
const char* versionString(Version version);
const char* codeString(Code code);
const char* methodString(Method method);
const char* versionString(Version version);
const char* codeString(Code code);
std::ostream& operator<<(std::ostream& os, Version version);
std::ostream& operator<<(std::ostream& os, Method method);
std::ostream& operator<<(std::ostream& os, Code code);
std::ostream& operator<<(std::ostream& os, Version version);
std::ostream& operator<<(std::ostream& os, Method method);
std::ostream& operator<<(std::ostream& os, Code code);
struct HttpError : public std::exception
{
HttpError(Code code, std::string reason);
HttpError(int code, std::string reason);
struct HttpError : public std::exception
{
HttpError(Code code, std::string reason);
HttpError(int code, std::string reason);
~HttpError() noexcept { }
~HttpError() noexcept override = default;
const char* what() const noexcept override { return reason_.c_str(); }
const char* what() const noexcept override { return reason_.c_str(); }
int code() const { return code_; }
std::string reason() const { return reason_; }
int code() const { return code_; }
std::string reason() const { return reason_; }
private:
int code_;
std::string reason_;
};
private:
int code_;
std::string reason_;
};
} // namespace Http
} // namespace Pistache
} // namespace Pistache::Http
namespace std
{
......
This diff is collapsed.
This diff is collapsed.
......@@ -26,97 +26,94 @@
#include <openssl/ssl.h>
#endif /* PISTACHE_USE_SSL */
namespace Pistache
namespace Pistache::Tcp
{
namespace Tcp
{
class Peer;
class Transport;
class Peer;
class Transport;
void setSocketOptions(Fd fd, Flags<Options> options);
void setSocketOptions(Fd fd, Flags<Options> options);
class Listener
class Listener
{
public:
struct Load
{
public:
struct Load
{
using TimePoint = std::chrono::system_clock::time_point;
double global;
std::vector<double> workers;
using TimePoint = std::chrono::system_clock::time_point;
double global;
std::vector<double> workers;
std::vector<rusage> raw;
TimePoint tick;
};
std::vector<rusage> raw;
TimePoint tick;
};
using TransportFactory = std::function<std::shared_ptr<Transport>()>;
using TransportFactory = std::function<std::shared_ptr<Transport>()>;
Listener();
~Listener();
Listener();
~Listener();
explicit Listener(const Address& address);
void init(size_t workers,
Flags<Options> options = Flags<Options>(Options::None),
const std::string& workersName = "",
int backlog = Const::MaxBacklog,
PISTACHE_STRING_LOGGER_T logger = PISTACHE_NULL_STRING_LOGGER);
explicit Listener(const Address& address);
void init(size_t workers,
Flags<Options> options = Flags<Options>(Options::None),
const std::string& workersName = "",
int backlog = Const::MaxBacklog,
PISTACHE_STRING_LOGGER_T logger = PISTACHE_NULL_STRING_LOGGER);
void setTransportFactory(TransportFactory factory);
void setHandler(const std::shared_ptr<Handler>& handler);
void setTransportFactory(TransportFactory factory);
void setHandler(const std::shared_ptr<Handler>& handler);
void bind();
void bind(const Address& address);
void bind();
void bind(const Address& address);
bool isBound() const;
Port getPort() const;
bool isBound() const;
Port getPort() const;
void run();
void runThreaded();
void run();
void runThreaded();
void shutdown();
void shutdown();
Async::Promise<Load> requestLoad(const Load& old);
Async::Promise<Load> requestLoad(const Load& old);
Options options() const;
Address address() const;
Options options() const;
Address address() const;
void pinWorker(size_t worker, const CpuSet& set);
void pinWorker(size_t worker, const CpuSet& set);
void setupSSL(const std::string& cert_path, const std::string& key_path,
bool use_compression);
void setupSSLAuth(const std::string& ca_file, const std::string& ca_path,
int (*cb)(int, void*));
void setupSSL(const std::string& cert_path, const std::string& key_path,
bool use_compression);
void setupSSLAuth(const std::string& ca_file, const std::string& ca_path,
int (*cb)(int, void*));
private:
Address addr_;
int listen_fd = -1;
int backlog_ = Const::MaxBacklog;
NotifyFd shutdownFd;
Polling::Epoll poller;
private:
Address addr_;
int listen_fd = -1;
int backlog_ = Const::MaxBacklog;
NotifyFd shutdownFd;
Polling::Epoll poller;
Flags<Options> options_;
std::thread acceptThread;
Flags<Options> options_;
std::thread acceptThread;
size_t workers_ = Const::DefaultWorkers;
std::string workersName_;
std::shared_ptr<Handler> handler_;
size_t workers_ = Const::DefaultWorkers;
std::string workersName_;
std::shared_ptr<Handler> handler_;
Aio::Reactor reactor_;
Aio::Reactor::Key transportKey;
Aio::Reactor reactor_;
Aio::Reactor::Key transportKey;
TransportFactory transportFactory_;
TransportFactory transportFactory_;
TransportFactory defaultTransportFactory() const;
TransportFactory defaultTransportFactory() const;
void handleNewConnection();
int acceptConnection(struct sockaddr_in& peer_addr) const;
void dispatchPeer(const std::shared_ptr<Peer>& peer);
void handleNewConnection();
int acceptConnection(struct sockaddr_in& peer_addr) const;
void dispatchPeer(const std::shared_ptr<Peer>& peer);
bool useSSL_ = false;
ssl::SSLCtxPtr ssl_ctx_ = nullptr;
bool useSSL_ = false;
ssl::SSLCtxPtr ssl_ctx_ = nullptr;
PISTACHE_STRING_LOGGER_T logger_ = PISTACHE_NULL_STRING_LOGGER;
};
PISTACHE_STRING_LOGGER_T logger_ = PISTACHE_NULL_STRING_LOGGER;
};
} // namespace Tcp
} // namespace Pistache
} // namespace Pistache::Tcp
......@@ -29,7 +29,7 @@ namespace Pistache
public:
Mailbox() { data.store(nullptr); }
virtual ~Mailbox() { }
virtual ~Mailbox() = default;
const T* get() const
{
......@@ -269,7 +269,7 @@ namespace Pistache
: event_fd(-1)
{ }
~PollableQueue()
~PollableQueue() override
{
if (event_fd != -1)
close(event_fd);
......
......@@ -33,7 +33,6 @@ install_headers([
'ssl_wrappers.h',
'stream.h',
'string_logger.h',
'string_view.h',
'tcp.h',
'timer_pool.h',
'transport.h',
......
......@@ -2,19 +2,13 @@
#include <cstdint>
namespace Pistache
namespace Pistache::Meta::Hash
{
namespace Meta
{
namespace Hash
{
static constexpr uint64_t val64 = 0xcbf29ce484222325;
static constexpr uint64_t prime64 = 0x100000001b3;
static constexpr uint64_t val64 = 0xcbf29ce484222325;
static constexpr uint64_t prime64 = 0x100000001b3;
inline constexpr uint64_t fnv1a(const char* const str, const uint64_t value = val64) noexcept
{
return (str[0] == '\0') ? value : fnv1a(&str[1], (value ^ uint64_t(str[0])) * prime64);
}
}
inline constexpr uint64_t fnv1a(const char* const str, const uint64_t value = val64) noexcept
{
return (str[0] == '\0') ? value : fnv1a(&str[1], (value ^ uint64_t(str[0])) * prime64);
}
}
\ No newline at end of file
} // namespace Pistache::Meta::Hash
This diff is collapsed.
......@@ -6,8 +6,6 @@
#pragma once
#include <pistache/view.h>
#include <cstring>
#include <limits>
#include <stdexcept>
......@@ -175,10 +173,9 @@ namespace Pistache
namespace helpers
{
inline Address httpAddr(const StringView& view)
inline Address httpAddr(const std::string_view& view)
{
auto const str = view.toString();
return Address(str);
return Address(std::string(view));
}
} // namespace helpers
......
......@@ -22,58 +22,55 @@
#endif /* PISTACHE_USE_SSL */
namespace Pistache
namespace Pistache::Tcp
{
namespace Tcp
{
class Transport;
class Transport;
class Peer
{
public:
friend class Transport;
friend class Http::Handler;
friend class Http::Timeout;
class Peer
{
public:
friend class Transport;
friend class Http::Handler;
friend class Http::Timeout;
~Peer();
~Peer();
static std::shared_ptr<Peer> Create(Fd fd, const Address& addr);
static std::shared_ptr<Peer> CreateSSL(Fd fd, const Address& addr, void* ssl);
static std::shared_ptr<Peer> Create(Fd fd, const Address& addr);
static std::shared_ptr<Peer> CreateSSL(Fd fd, const Address& addr, void* ssl);
const Address& address() const;
const std::string& hostname();
Fd fd() const;
const Address& address() const;
const std::string& hostname();
Fd fd() const;
void* ssl() const;
void* ssl() const;
void putData(std::string name, std::shared_ptr<void> data);
std::shared_ptr<void> getData(std::string name) const;
std::shared_ptr<void> tryGetData(std::string name) const;
void putData(std::string name, std::shared_ptr<void> data);
std::shared_ptr<void> getData(std::string name) const;
std::shared_ptr<void> tryGetData(std::string name) const;
Async::Promise<ssize_t> send(const RawBuffer& buffer, int flags = 0);
size_t getID() const;
Async::Promise<ssize_t> send(const RawBuffer& buffer, int flags = 0);
size_t getID() const;
protected:
Peer(Fd fd, const Address& addr, void* ssl);
protected:
Peer(Fd fd, const Address& addr, void* ssl);
private:
void associateTransport(Transport* transport);
Transport* transport() const;
static size_t getUniqueId();
private:
void associateTransport(Transport* transport);
Transport* transport() const;
static size_t getUniqueId();
Transport* transport_ = nullptr;
Fd fd_ = -1;
Address addr;
Transport* transport_ = nullptr;
Fd fd_ = -1;
Address addr;
std::string hostname_;
std::unordered_map<std::string, std::shared_ptr<void>> data_;
std::string hostname_;
std::unordered_map<std::string, std::shared_ptr<void>> data_;
void* ssl_ = nullptr;
const size_t id_;
};
void* ssl_ = nullptr;
const size_t id_;
};
std::ostream& operator<<(std::ostream& os, Peer& peer);
std::ostream& operator<<(std::ostream& os, Peer& peer);
} // namespace Tcp
} // namespace Pistache
} // namespace Pistache::Tcp
......@@ -17,7 +17,7 @@ namespace Pistache
struct Prototype
{
public:
virtual ~Prototype() { }
virtual ~Prototype() = default;
virtual std::shared_ptr<Class> clone() const = 0;
};
......
This diff is collapsed.
......@@ -6,76 +6,70 @@
#pragma once
namespace Pistache
namespace Pistache::Rest::Route
{
namespace Rest
{
namespace Route
{
void Get(Router& router, std::string resource, Route::Handler handler);
void Post(Router& router, std::string resource, Route::Handler handler);
void Put(Router& router, std::string resource, Route::Handler handler);
void Delete(Router& router, std::string resource, Route::Handler handler);
void Get(Router& router, std::string resource, Route::Handler handler);
void Post(Router& router, std::string resource, Route::Handler handler);
void Put(Router& router, std::string resource, Route::Handler handler);
void Delete(Router& router, std::string resource, Route::Handler handler);
namespace details
namespace details
{
template <class... Args>
struct TypeList
{
template <size_t N>
struct At
{
template <class... Args>
struct TypeList
{
template <size_t N>
struct At
{
static_assert(N < sizeof...(Args), "Invalid index");
typedef typename std::tuple_element<N, std::tuple<Args...>>::type Type;
};
};
static_assert(N < sizeof...(Args), "Invalid index");
typedef typename std::tuple_element<N, std::tuple<Args...>>::type Type;
};
};
template <typename... Args>
void static_checks()
{
static_assert(sizeof...(Args) == 2, "Function should take 2 parameters");
typedef details::TypeList<Args...> Arguments;
// Disabled now as it
// 1/ does not compile
// 2/ might not be relevant
template <typename... Args>
void static_checks()
{
static_assert(sizeof...(Args) == 2, "Function should take 2 parameters");
typedef details::TypeList<Args...> Arguments;
// Disabled now as it
// 1/ does not compile
// 2/ might not be relevant
#if 0
static_assert(std::is_same<Arguments::At<0>::Type, const Rest::Request&>::value, "First argument should be a const Rest::Request&");
static_assert(std::is_same<typename Arguments::At<0>::Type, Http::Response>::value, "Second argument should be a Http::Response");
#endif
}
} // namespace details
}
} // namespace details
template <typename Result, typename Cls, typename... Args, typename Obj>
Route::Handler bind(Result (Cls::*func)(Args...), Obj obj)
{
details::static_checks<Args...>();
template <typename Result, typename Cls, typename... Args, typename Obj>
Route::Handler bind(Result (Cls::*func)(Args...), Obj obj)
{
details::static_checks<Args...>();
return [=](const Rest::Request& request, Http::ResponseWriter response) {
(obj->*func)(request, std::move(response));
};
}
return [=](const Rest::Request& request, Http::ResponseWriter response) {
(obj->*func)(request, std::move(response));
};
}
template <typename Result, typename Cls, typename... Args, typename Obj>
Route::Handler bind(Result (Cls::*func)(Args...), std::shared_ptr<Obj> objPtr)
{
details::static_checks<Args...>();
template <typename Result, typename Cls, typename... Args, typename Obj>
Route::Handler bind(Result (Cls::*func)(Args...), std::shared_ptr<Obj> objPtr)
{
details::static_checks<Args...>();
return [=](const Rest::Request& request, Http::ResponseWriter response) {
(objPtr.get()->*func)(request, std::move(response));
};
}
return [=](const Rest::Request& request, Http::ResponseWriter response) {
(objPtr.get()->*func)(request, std::move(response));
};
}
template <typename Result, typename... Args>
Route::Handler bind(Result (*func)(Args...))
{
details::static_checks<Args...>();
template <typename Result, typename... Args>
Route::Handler bind(Result (*func)(Args...))
{
details::static_checks<Args...>();
return [=](const Rest::Request& request, Http::ResponseWriter response) {
func(request, std::move(response));
};
}
return [=](const Rest::Request& request, Http::ResponseWriter response) {
func(request, std::move(response));
};
}
} // namespace Route
} // namespace Rest
} // namespace Pistache
} // namespace Pistache::Rest::Route
This diff is collapsed.
......@@ -6,55 +6,48 @@
#include <memory>
namespace Pistache
namespace Pistache::ssl
{
namespace ssl
{
struct SSLCtxDeleter
struct SSLCtxDeleter
{
void operator()([[maybe_unused]] void* ptr)
{
void operator()(void* ptr)
{
#ifdef PISTACHE_USE_SSL
SSL_CTX_free(reinterpret_cast<SSL_CTX*>(ptr));
// EVP_cleanup call is not related to cleaning SSL_CTX, just global cleanup routine.
// TODO: Think about removing EVP_cleanup call at all
// It was deprecated in openssl 1.1.0 version (see
// https://www.openssl.org/news/changelog.txt):
// "Make various cleanup routines no-ops and mark them as deprecated."
EVP_cleanup();
#else
(void)ptr;
SSL_CTX_free(reinterpret_cast<SSL_CTX*>(ptr));
// EVP_cleanup call is not related to cleaning SSL_CTX, just global cleanup routine.
// TODO: Think about removing EVP_cleanup call at all
// It was deprecated in openssl 1.1.0 version (see
// https://www.openssl.org/news/changelog.txt):
// "Make various cleanup routines no-ops and mark them as deprecated."
EVP_cleanup();
#endif
}
};
}
};
struct SSLBioDeleter
struct SSLBioDeleter
{
void operator()([[maybe_unused]] void* ptr)
{
void operator()(void* ptr)
{
#ifdef PISTACHE_USE_SSL
BIO_free(reinterpret_cast<BIO*>(ptr));
#else
(void)ptr;
BIO_free(reinterpret_cast<BIO*>(ptr));
#endif
}
};
}
};
using SSLCtxPtr = std::unique_ptr<void, SSLCtxDeleter>;
using SSLBioPtr = std::unique_ptr<void, SSLBioDeleter>;
using SSLCtxPtr = std::unique_ptr<void, SSLCtxDeleter>;
using SSLBioPtr = std::unique_ptr<void, SSLBioDeleter>;
#ifdef PISTACHE_USE_SSL
inline SSL_CTX* GetSSLContext(ssl::SSLCtxPtr& ctx)
{
return reinterpret_cast<SSL_CTX*>(ctx.get());
}
inline BIO* GetSSLBio(ssl::SSLBioPtr& ctx)
{
return reinterpret_cast<BIO*>(ctx.get());
}
inline SSL_CTX* GetSSLContext(ssl::SSLCtxPtr& ctx)
{
return reinterpret_cast<SSL_CTX*>(ctx.get());
}
inline BIO* GetSSLBio(ssl::SSLBioPtr& ctx)
{
return reinterpret_cast<BIO*>(ctx.get());
}
#endif
}
}
} // namespace Pistache::ssl
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -5,4 +5,4 @@ namespace Pistache
#define REQUIRES(condition) typename std::enable_if<(condition), int>::type = 0
} // namespace Pistache
\ No newline at end of file
} // namespace Pistache
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
add_executable(fuzz_parser fuzz_parser.cpp)
target_link_libraries(fuzz_parser pistache_static)
set_target_properties(fuzz_parser PROPERTIES LINK_FLAGS $ENV{LIB_FUZZING_ENGINE})
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment