Commit 04818887 authored by Mathieu Stefani's avatar Mathieu Stefani

Format everything with new clang-format formatting rules

parent 61ff656c
......@@ -4,21 +4,22 @@
Example of custom headers registering
*/
#include <pistache/net.h>
#include <pistache/http_headers.h>
#include <pistache/net.h>
#include <sys/types.h>
// Quiet a warning about "minor" and "major" being doubly defined.
#ifdef major
#undef major
#undef major
#endif
#ifdef minor
#undef minor
#undef minor
#endif
using namespace Pistache;
class XProtocolVersion : public Http::Header::Header {
class XProtocolVersion : public Http::Header::Header
{
public:
NAME("X-Protocol-Version");
......@@ -32,14 +33,17 @@ public:
, min(minor)
{ }
void parse(const std::string& str) override {
void parse(const std::string& str) override
{
auto p = str.find('.');
std::string major, minor;
if (p != std::string::npos) {
if (p != std::string::npos)
{
major = str.substr(0, p);
minor = str.substr(p + 1);
}
else {
else
{
major = str;
}
......@@ -48,16 +52,19 @@ public:
min = std::stoi(minor);
}
void write(std::ostream& os) const override {
void write(std::ostream& os) const override
{
os << maj;
os << "." << min;
}
uint32_t majorVersion() const {
uint32_t majorVersion() const
{
return maj;
}
uint32_t minorVersion() const {
uint32_t minorVersion() const
{
return min;
}
......@@ -66,6 +73,7 @@ private:
uint32_t min;
};
int main() {
int main()
{
Http::Header::Registry::instance().registerHeader<XProtocolVersion>();
}
......@@ -4,26 +4,27 @@
Example of an hello world server
*/
#include "pistache/endpoint.h"
using namespace Pistache;
class HelloHandler : public Http::Handler {
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");
}
};
int main() {
int main()
{
Pistache::Address addr(Pistache::Ipv4::any(), Pistache::Port(9080));
auto opts = Pistache::Http::Endpoint::options()
.threads(1);
.threads(1);
Http::Endpoint server(addr);
server.init(opts);
......
......@@ -12,64 +12,67 @@
using namespace Pistache;
int main(int argc, char *argv[]) {
if (argc < 2) {
std::cerr << "Usage: http_client page [count]\n";
return 1;
}
int main(int argc, char* argv[])
{
if (argc < 2)
{
std::cerr << "Usage: http_client page [count]\n";
return 1;
}
std::string page = argv[1];
int count = 1;
if (argc == 3) {
count = std::stoi(argv[2]);
}
std::string page = argv[1];
int count = 1;
if (argc == 3)
{
count = std::stoi(argv[2]);
}
Http::Client client;
Http::Client client;
auto opts = Http::Client::options().threads(1).maxConnectionsPerHost(8);
client.init(opts);
auto opts = Http::Client::options().threads(1).maxConnectionsPerHost(8);
client.init(opts);
std::vector<Async::Promise<Http::Response>> responses;
std::vector<Async::Promise<Http::Response>> responses;
std::atomic<size_t> completedRequests(0);
std::atomic<size_t> failedRequests(0);
std::atomic<size_t> completedRequests(0);
std::atomic<size_t> failedRequests(0);
auto start = std::chrono::system_clock::now();
auto start = std::chrono::system_clock::now();
for (int i = 0; i < count; ++i) {
auto resp = client.get(page).cookie(Http::Cookie("FOO", "bar")).send();
resp.then(
[&](Http::Response response) {
++completedRequests;
std::cout << "Response code = " << response.code() << std::endl;
auto body = response.body();
if (!body.empty())
std::cout << "Response body = " << body << std::endl;
},
[&](std::exception_ptr exc) {
++failedRequests;
PrintException excPrinter;
excPrinter(exc);
});
responses.push_back(std::move(resp));
}
for (int i = 0; i < count; ++i)
{
auto resp = client.get(page).cookie(Http::Cookie("FOO", "bar")).send();
resp.then(
[&](Http::Response response) {
++completedRequests;
std::cout << "Response code = " << response.code() << std::endl;
auto body = response.body();
if (!body.empty())
std::cout << "Response body = " << body << std::endl;
},
[&](std::exception_ptr exc) {
++failedRequests;
PrintException excPrinter;
excPrinter(exc);
});
responses.push_back(std::move(resp));
}
auto sync = Async::whenAll(responses.begin(), responses.end());
Async::Barrier<std::vector<Http::Response>> barrier(sync);
barrier.wait_for(std::chrono::seconds(5));
auto sync = Async::whenAll(responses.begin(), responses.end());
Async::Barrier<std::vector<Http::Response>> barrier(sync);
barrier.wait_for(std::chrono::seconds(5));
auto end = std::chrono::system_clock::now();
std::cout << "Summary of execution\n"
<< "Total number of requests sent : " << count << '\n'
<< "Total number of responses received: "
<< completedRequests.load() << '\n'
<< "Total number of requests failed : " << failedRequests.load()
<< '\n'
<< "Total time of execution : "
<< std::chrono::duration_cast<std::chrono::milliseconds>(end -
start)
.count()
<< "ms" << std::endl;
auto end = std::chrono::system_clock::now();
std::cout << "Summary of execution\n"
<< "Total number of requests sent : " << count << '\n'
<< "Total number of responses received: "
<< completedRequests.load() << '\n'
<< "Total number of requests failed : " << failedRequests.load()
<< '\n'
<< "Total time of execution : "
<< std::chrono::duration_cast<std::chrono::milliseconds>(end - start)
.count()
<< "ms" << std::endl;
client.shutdown();
client.shutdown();
}
......@@ -4,38 +4,44 @@
Example of an http server
*/
#include <pistache/net.h>
#include <pistache/http.h>
#include <pistache/peer.h>
#include <pistache/http_headers.h>
#include <pistache/common.h>
#include <pistache/cookie.h>
#include <pistache/endpoint.h>
#include <pistache/common.h>
#include <pistache/http.h>
#include <pistache/http_headers.h>
#include <pistache/net.h>
#include <pistache/peer.h>
using namespace Pistache;
struct LoadMonitor {
struct LoadMonitor
{
LoadMonitor(const std::shared_ptr<Http::Endpoint>& endpoint)
: endpoint_(endpoint)
, interval(std::chrono::seconds(1))
{ }
void setInterval(std::chrono::seconds secs) {
void setInterval(std::chrono::seconds secs)
{
interval = secs;
}
void start() {
void start()
{
shutdown_ = false;
thread.reset(new std::thread(std::bind(&LoadMonitor::run, this)));
}
void shutdown() {
void shutdown()
{
shutdown_ = true;
}
~LoadMonitor() {
~LoadMonitor()
{
shutdown_ = true;
if (thread) thread->join();
if (thread)
thread->join();
}
private:
......@@ -45,45 +51,53 @@ private:
std::atomic<bool> shutdown_;
void run() {
void run()
{
Tcp::Listener::Load old;
while (!shutdown_) {
if (!endpoint_->isBound()) continue;
while (!shutdown_)
{
if (!endpoint_->isBound())
continue;
endpoint_->requestLoad(old).then([&](const Tcp::Listener::Load& load) {
old = load;
double global = load.global;
if (global > 100) global = 100;
if (global > 100)
global = 100;
if (global > 1)
std::cout << "Global load is " << global << "%" << std::endl;
else
std::cout << "Global load is 0%" << std::endl;
},
Async::NoExcept);
Async::NoExcept);
std::this_thread::sleep_for(std::chrono::seconds(interval));
}
}
};
class MyHandler : public Http::Handler {
class MyHandler : public Http::Handler
{
HTTP_PROTOTYPE(MyHandler)
void onRequest(
const Http::Request& req,
Http::ResponseWriter response) override {
const Http::Request& req,
Http::ResponseWriter response) override
{
if (req.resource() == "/ping") {
if (req.method() == Http::Method::Get) {
if (req.resource() == "/ping")
{
if (req.method() == Http::Method::Get)
{
using namespace Http;
auto query = req.query();
if (query.has("chunked")) {
if (query.has("chunked"))
{
std::cout << "Using chunked encoding" << std::endl;
response.headers()
......@@ -98,64 +112,78 @@ class MyHandler : public Http::Handler {
stream << "NG";
stream << ends;
}
else {
else
{
response.send(Http::Code::Ok, "PONG");
}
}
}
else if (req.resource() == "/echo") {
if (req.method() == Http::Method::Post) {
else if (req.resource() == "/echo")
{
if (req.method() == Http::Method::Post)
{
response.send(Http::Code::Ok, req.body(), MIME(Text, Plain));
} else {
}
else
{
response.send(Http::Code::Method_Not_Allowed);
}
}
else if (req.resource() == "/stream_binary") {
auto stream = response.stream(Http::Code::Ok);
else if (req.resource() == "/stream_binary")
{
auto stream = response.stream(Http::Code::Ok);
char binary_data[] = "some \0\r\n data\n";
size_t chunk_size = 14;
for (size_t i = 0; i < 10; ++i) {
size_t chunk_size = 14;
for (size_t i = 0; i < 10; ++i)
{
stream.write(binary_data, chunk_size);
stream.flush();
}
stream.ends();
}
else if (req.resource() == "/exception") {
else if (req.resource() == "/exception")
{
throw std::runtime_error("Exception thrown in the handler");
}
else if (req.resource() == "/timeout") {
else if (req.resource() == "/timeout")
{
response.timeoutAfter(std::chrono::seconds(2));
}
else if (req.resource() == "/static") {
if (req.method() == Http::Method::Get) {
else if (req.resource() == "/static")
{
if (req.method() == Http::Method::Get)
{
Http::serveFile(response, "README.md").then([](ssize_t bytes) {
std::cout << "Sent " << bytes << " bytes" << std::endl;
}, Async::NoExcept);
},
Async::NoExcept);
}
} else {
}
else
{
response.send(Http::Code::Not_Found);
}
}
void onTimeout(
const Http::Request& req,
Http::ResponseWriter response) override {
const Http::Request& req,
Http::ResponseWriter response) override
{
UNUSED(req);
response
.send(Http::Code::Request_Timeout, "Timeout")
.then([=](ssize_t) { }, PrintException());
.then([=](ssize_t) {}, PrintException());
}
};
int main(int argc, char *argv[]) {
int main(int argc, char* argv[])
{
Port port(9080);
int thr = 2;
if (argc >= 2) {
if (argc >= 2)
{
port = static_cast<uint16_t>(std::stol(argv[1]));
if (argc == 3)
......@@ -170,7 +198,7 @@ int main(int argc, char *argv[]) {
auto server = std::make_shared<Http::Endpoint>(addr);
auto opts = Http::Endpoint::options()
.threads(thr);
.threads(thr);
server->init(opts);
server->setHandler(Http::make_handler<MyHandler>());
server->serve();
......
......@@ -3,31 +3,34 @@
using namespace Pistache;
class HelloHandler : public Http::Handler {
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");
}
};
int main() {
int main()
{
sigset_t signals;
if (sigemptyset(&signals) != 0
|| sigaddset(&signals, SIGTERM) != 0
|| sigaddset(&signals, SIGINT) != 0
|| sigaddset(&signals, SIGHUP) != 0
|| pthread_sigmask(SIG_BLOCK, &signals, nullptr) != 0) {
|| sigaddset(&signals, SIGTERM) != 0
|| sigaddset(&signals, SIGINT) != 0
|| sigaddset(&signals, SIGHUP) != 0
|| pthread_sigmask(SIG_BLOCK, &signals, nullptr) != 0)
{
perror("install signal handler failed");
return 1;
}
Pistache::Address addr(Pistache::Ipv4::any(), Pistache::Port(9080));
auto opts = Pistache::Http::Endpoint::options()
.threads(1);
.threads(1);
Http::Endpoint server(addr);
server.init(opts);
......
......@@ -4,37 +4,42 @@
Example of how to use the Description mechanism
*/
#include <pistache/http.h>
#include <pistache/description.h>
#include <pistache/endpoint.h>
#include <pistache/http.h>
#include <pistache/thirdparty/serializer/rapidjson.h>
using namespace Pistache;
namespace Generic {
namespace Generic
{
void handleReady(const Rest::Request&, Http::ResponseWriter response) {
response.send(Http::Code::Ok, "1");
}
void handleReady(const Rest::Request&, Http::ResponseWriter response)
{
response.send(Http::Code::Ok, "1");
}
}
class BankerService {
class BankerService
{
public:
BankerService(Address addr)
: httpEndpoint(std::make_shared<Http::Endpoint>(addr))
, desc("Banking API", "0.1")
{ }
void init(size_t thr = 2) {
void init(size_t thr = 2)
{
auto opts = Http::Endpoint::options()
.threads(static_cast<int>(thr));
.threads(static_cast<int>(thr));
httpEndpoint->init(opts);
createDescription();
}
void start() {
void start()
{
router.initFromDescription(desc);
Rest::Swagger swagger(desc);
......@@ -50,13 +55,13 @@ public:
}
private:
void createDescription() {
void createDescription()
{
desc
.info()
.license("Apache", "http://www.apache.org/licenses/LICENSE-2.0");
auto backendErrorResponse =
desc.response(Http::Code::Internal_Server_Error, "An error occured with the backend");
auto backendErrorResponse = desc.response(Http::Code::Internal_Server_Error, "An error occured with the backend");
desc
.schemes(Rest::Scheme::Http)
......@@ -106,22 +111,25 @@ private:
.produces(MIME(Application, Json))
.response(Http::Code::Ok, "Budget has been added to the account")
.response(backendErrorResponse);
}
void retrieveAllAccounts(const Rest::Request&, Http::ResponseWriter response) {
void retrieveAllAccounts(const Rest::Request&, Http::ResponseWriter response)
{
response.send(Http::Code::Ok, "No Account");
}
void retrieveAccount(const Rest::Request&, Http::ResponseWriter response) {
void retrieveAccount(const Rest::Request&, Http::ResponseWriter response)
{
response.send(Http::Code::Ok, "The bank is closed, come back later");
}
void createAccount(const Rest::Request&, Http::ResponseWriter response) {
void createAccount(const Rest::Request&, Http::ResponseWriter response)
{
response.send(Http::Code::Ok, "The bank is closed, come back later");
}
void creditAccount(const Rest::Request&, Http::ResponseWriter response) {
void creditAccount(const Rest::Request&, Http::ResponseWriter response)
{
response.send(Http::Code::Ok, "The bank is closed, come back later");
}
......@@ -130,12 +138,14 @@ private:
Rest::Router router;
};
int main(int argc, char *argv[]) {
int main(int argc, char* argv[])
{
Port port(9080);
int thr = 2;
if (argc >= 2) {
if (argc >= 2)
{
port = static_cast<uint16_t>(std::stol(argv[1]));
if (argc == 3)
......
......@@ -6,60 +6,68 @@
#include <algorithm>
#include <pistache/endpoint.h>
#include <pistache/http.h>
#include <pistache/router.h>
#include <pistache/endpoint.h>
using namespace Pistache;
void printCookies(const Http::Request& req) {
void printCookies(const Http::Request& req)
{
auto cookies = req.cookies();
std::cout << "Cookies: [" << std::endl;
const std::string indent(4, ' ');
for (const auto& c: cookies) {
for (const auto& c : cookies)
{
std::cout << indent << c.name << " = " << c.value << std::endl;
}
std::cout << "]" << std::endl;
}
namespace Generic {
namespace Generic
{
void handleReady(const Rest::Request&, Http::ResponseWriter response) {
response.send(Http::Code::Ok, "1");
}
void handleReady(const Rest::Request&, Http::ResponseWriter response)
{
response.send(Http::Code::Ok, "1");
}
}
class StatsEndpoint {
class StatsEndpoint
{
public:
explicit StatsEndpoint(Address addr)
: httpEndpoint(std::make_shared<Http::Endpoint>(addr))
{ }
void init(size_t thr = 2) {
void init(size_t thr = 2)
{
auto opts = Http::Endpoint::options()
.threads(static_cast<int>(thr));
.threads(static_cast<int>(thr));
httpEndpoint->init(opts);
setupRoutes();
}
void start() {
void start()
{
httpEndpoint->setHandler(router.handler());
httpEndpoint->serve();
}
private:
void setupRoutes() {
void setupRoutes()
{
using namespace Rest;
Routes::Post(router, "/record/:name/:value?", Routes::bind(&StatsEndpoint::doRecordMetric, this));
Routes::Get(router, "/value/:name", Routes::bind(&StatsEndpoint::doGetMetric, this));
Routes::Get(router, "/ready", Routes::bind(&Generic::handleReady));
Routes::Get(router, "/auth", Routes::bind(&StatsEndpoint::doAuth, this));
}
void doRecordMetric(const Rest::Request& request, Http::ResponseWriter response) {
void doRecordMetric(const Rest::Request& request, Http::ResponseWriter response)
{
auto name = request.param(":name").as<std::string>();
Guard guard(metricsLock);
......@@ -68,24 +76,27 @@ private:
});
int val = 1;
if (request.hasParam(":value")) {
if (request.hasParam(":value"))
{
auto value = request.param(":value");
val = value.as<int>();
val = value.as<int>();
}
if (it == std::end(metrics)) {
if (it == std::end(metrics))
{
metrics.push_back(Metric(std::move(name), val));
response.send(Http::Code::Created, std::to_string(val));
}
else {
auto &metric = *it;
else
{
auto& metric = *it;
metric.incr(val);
response.send(Http::Code::Ok, std::to_string(metric.value()));
}
}
void doGetMetric(const Rest::Request& request, Http::ResponseWriter response) {
void doGetMetric(const Rest::Request& request, Http::ResponseWriter response)
{
auto name = request.param(":name").as<std::string>();
Guard guard(metricsLock);
......@@ -93,48 +104,56 @@ private:
return metric.name() == name;
});
if (it == std::end(metrics)) {
if (it == std::end(metrics))
{
response.send(Http::Code::Not_Found, "Metric does not exist");
} else {
}
else
{
const auto& metric = *it;
response.send(Http::Code::Ok, std::to_string(metric.value()));
}
}
void doAuth(const Rest::Request& request, Http::ResponseWriter response) {
void doAuth(const Rest::Request& request, Http::ResponseWriter response)
{
printCookies(request);
response.cookies()
.add(Http::Cookie("lang", "en-US"));
response.send(Http::Code::Ok);
}
class Metric {
class Metric
{
public:
explicit Metric(std::string name, int initialValue = 1)
: name_(std::move(name))
, value_(initialValue)
{ }
int incr(int n = 1) {
int incr(int n = 1)
{
int old = value_;
value_ += n;
return old;
}
int value() const {
int value() const
{
return value_;
}
const std::string& name() const {
const std::string& name() const
{
return name_;
}
private:
std::string name_;
int value_;
};
using Lock = std::mutex;
using Lock = std::mutex;
using Guard = std::lock_guard<Lock>;
Lock metricsLock;
std::vector<Metric> metrics;
......@@ -143,12 +162,14 @@ private:
Rest::Router router;
};
int main(int argc, char *argv[]) {
int main(int argc, char* argv[])
{
Port port(9080);
int thr = 2;
if (argc >= 2) {
if (argc >= 2)
{
port = static_cast<uint16_t>(std::stol(argv[1]));
if (argc == 3)
......
This diff is collapsed.
......@@ -18,83 +18,90 @@
#include <vector>
#if __cplusplus < 201703L
namespace std {
typedef uint8_t byte;
namespace std
{
typedef uint8_t byte;
}
#endif
// A class for performing decoding to raw bytes from base 64 encoding...
class Base64Decoder {
// Public methods...
class Base64Decoder
{
// Public methods...
public:
// Constructor...
explicit Base64Decoder(const std::string &Base64EncodedString)
: m_Base64EncodedString(Base64EncodedString) {}
// Calculate length of decoded raw bytes from that would be generated if
// the base 64 encoded input buffer was decoded. This is not a static
// method because we need to examine the string...
std::vector<std::byte>::size_type CalculateDecodedSize() const;
// Decode base 64 encoding into raw bytes...
const std::vector<std::byte> &Decode();
// Get raw decoded data...
const std::vector<std::byte> &GetRawDecodedData() const noexcept {
return m_DecodedData;
}
// Protected methods...
// Constructor...
explicit Base64Decoder(const std::string& Base64EncodedString)
: m_Base64EncodedString(Base64EncodedString)
{ }
// Calculate length of decoded raw bytes from that would be generated if
// the base 64 encoded input buffer was decoded. This is not a static
// method because we need to examine the string...
std::vector<std::byte>::size_type CalculateDecodedSize() const;
// Decode base 64 encoding into raw bytes...
const std::vector<std::byte>& Decode();
// Get raw decoded data...
const std::vector<std::byte>& GetRawDecodedData() const noexcept
{
return m_DecodedData;
}
// Protected methods...
protected:
// Convert an octet character to corresponding sextet, provided it can
// safely be represented as such. Otherwise return 0xff...
std::byte DecodeCharacter(const unsigned char Character) const;
// Convert an octet character to corresponding sextet, provided it can
// safely be represented as such. Otherwise return 0xff...
std::byte DecodeCharacter(const unsigned char Character) const;
// Protected attributes...
// Protected attributes...
protected:
// Base 64 encoded string to decode...
const std::string &m_Base64EncodedString;
// Base 64 encoded string to decode...
const std::string& m_Base64EncodedString;
// Decoded raw data...
std::vector<std::byte> m_DecodedData;
// Decoded raw data...
std::vector<std::byte> m_DecodedData;
};
// A class for performing base 64 encoding from raw bytes...
class Base64Encoder {
// Public methods...
class Base64Encoder
{
// Public methods...
public:
// Construct encoder to encode from a raw input buffer...
explicit Base64Encoder(const std::vector<std::byte> &InputBuffer)
: m_InputBuffer(InputBuffer) {}
// Construct encoder to encode from a raw input buffer...
explicit Base64Encoder(const std::vector<std::byte>& InputBuffer)
: m_InputBuffer(InputBuffer)
{ }
// Calculate length of base 64 string that would need to be generated
// for raw data of a given length...
static std::string::size_type CalculateEncodedSize(
const std::vector<std::byte>::size_type DecodedSize) noexcept;
// Calculate length of base 64 string that would need to be generated
// for raw data of a given length...
static std::string::size_type CalculateEncodedSize(
const std::vector<std::byte>::size_type DecodedSize) noexcept;
// Encode raw data input buffer to base 64...
const std::string &Encode() noexcept;
// Encode raw data input buffer to base 64...
const std::string& Encode() noexcept;
// Encode a string into base 64 format...
static std::string EncodeString(const std::string &StringInput);
// Encode a string into base 64 format...
static std::string EncodeString(const std::string& StringInput);
// Get the encoded data...
const std::string &GetBase64EncodedString() const noexcept {
return m_Base64EncodedString;
}
// Get the encoded data...
const std::string& GetBase64EncodedString() const noexcept
{
return m_Base64EncodedString;
}
// Protected methods...
// Protected methods...
protected:
// Encode single binary byte to 6-bit base 64 character...
unsigned char EncodeByte(const std::byte Byte) const;
// Encode single binary byte to 6-bit base 64 character...
unsigned char EncodeByte(const std::byte Byte) const;
// Protected attributes...
// Protected attributes...
protected:
// Raw bytes to encode to base 64 string...
const std::vector<std::byte> &m_InputBuffer;
// Raw bytes to encode to base 64 string...
const std::vector<std::byte>& m_InputBuffer;
// Base64 encoded string...
std::string m_Base64EncodedString;
// Base64 encoded string...
std::string m_Base64EncodedString;
};
// Multiple include protection...
......
This diff is collapsed.
......@@ -16,45 +16,56 @@
#include <sys/socket.h>
#include <sys/types.h>
#define TRY(...) \
do { \
auto ret = __VA_ARGS__; \
if (ret < 0) { \
const char *str = #__VA_ARGS__; \
std::ostringstream oss; \
oss << str << ": "; \
if (errno == 0) { \
oss << gai_strerror(static_cast<int>(ret)); \
} else { \
oss << strerror(errno); \
} \
oss << " (" << __FILE__ << ":" << __LINE__ << ")"; \
throw std::runtime_error(oss.str()); \
} \
} while (0)
#define TRY_RET(...) \
[&]() { \
auto ret = __VA_ARGS__; \
if (ret < 0) { \
const char *str = #__VA_ARGS__; \
std::ostringstream oss; \
oss << str << ": " << strerror(errno); \
oss << " (" << __FILE__ << ":" << __LINE__ << ")"; \
throw std::runtime_error(oss.str()); \
} \
return ret; \
}(); \
(void)0
struct PrintException {
void operator()(std::exception_ptr exc) const {
try {
std::rethrow_exception(exc);
} catch (const std::exception &e) {
std::cerr << "An exception occured: " << e.what() << std::endl;
#define TRY(...) \
do \
{ \
auto ret = __VA_ARGS__; \
if (ret < 0) \
{ \
const char* str = #__VA_ARGS__; \
std::ostringstream oss; \
oss << str << ": "; \
if (errno == 0) \
{ \
oss << gai_strerror(static_cast<int>(ret)); \
} \
else \
{ \
oss << strerror(errno); \
} \
oss << " (" << __FILE__ << ":" << __LINE__ << ")"; \
throw std::runtime_error(oss.str()); \
} \
} while (0)
#define TRY_RET(...) \
[&]() { \
auto ret = __VA_ARGS__; \
if (ret < 0) \
{ \
const char* str = #__VA_ARGS__; \
std::ostringstream oss; \
oss << str << ": " << strerror(errno); \
oss << " (" << __FILE__ << ":" << __LINE__ << ")"; \
throw std::runtime_error(oss.str()); \
} \
return ret; \
}(); \
(void)0
struct PrintException
{
void operator()(std::exception_ptr exc) const
{
try
{
std::rethrow_exception(exc);
}
catch (const std::exception& e)
{
std::cerr << "An exception occured: " << e.what() << std::endl;
}
}
}
};
#define unreachable() __builtin_unreachable()
......
......@@ -7,23 +7,24 @@
#include <chrono>
// Allow compile-time overload
namespace Pistache {
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;
namespace Pistache
{
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 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
static constexpr uint16_t HTTP_STANDARD_PORT = 80;
} // namespace Const
} // namespace Pistache
......@@ -16,115 +16,133 @@
#include <pistache/http_defs.h>
#include <pistache/optional.h>
namespace Pistache {
namespace Http {
struct Cookie {
friend std::ostream &operator<<(std::ostream &os, const Cookie &cookie);
Cookie(std::string name, std::string value);
std::string name;
std::string value;
Optional<std::string> path;
Optional<std::string> domain;
Optional<FullDate> expires;
Optional<int> maxAge;
bool secure;
bool httpOnly;
std::map<std::string, std::string> ext;
static Cookie fromRaw(const char *str, size_t len);
static Cookie fromString(const std::string &str);
private:
void write(std::ostream &os) const;
};
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)
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) {
if (iter_storage != iter_storage_end) {
iter_cookie_values = iter_storage->second.begin();
}
}
Cookie operator*() const {
return iter_cookie_values->second; // return iter_storage->second;
}
const Cookie *operator->() const { return &(iter_cookie_values->second); }
iterator &operator++() {
++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;
}
iterator operator++(int) {
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;
}
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.
};
CookieJar();
void add(const Cookie &cookie);
void removeAllCookies();
void addFromRaw(const char *str, size_t len);
Cookie get(const std::string &name) const;
bool has(const std::string &name) const;
iterator begin() const { return iterator(cookies.begin(), cookies.end()); }
iterator end() const { return iterator(cookies.end()); }
private:
Storage cookies;
};
} // namespace Http
namespace Pistache
{
namespace Http
{
struct Cookie
{
friend std::ostream& operator<<(std::ostream& os, const Cookie& cookie);
Cookie(std::string name, std::string value);
std::string name;
std::string value;
Optional<std::string> path;
Optional<std::string> domain;
Optional<FullDate> expires;
Optional<int> maxAge;
bool secure;
bool httpOnly;
std::map<std::string, std::string> ext;
static Cookie fromRaw(const char* str, size_t len);
static Cookie fromString(const std::string& str);
private:
void write(std::ostream& os) const;
};
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)
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)
{
if (iter_storage != iter_storage_end)
{
iter_cookie_values = iter_storage->second.begin();
}
}
Cookie operator*() const
{
return iter_cookie_values->second; // return iter_storage->second;
}
const Cookie* operator->() const { return &(iter_cookie_values->second); }
iterator& operator++()
{
++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;
}
iterator operator++(int)
{
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;
}
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.
};
CookieJar();
void add(const Cookie& cookie);
void removeAllCookies();
void addFromRaw(const char* str, size_t len);
Cookie get(const std::string& name) const;
bool has(const std::string& name) const;
iterator begin() const { return iterator(cookies.begin(), cookies.end()); }
iterator end() const { return iterator(cookies.end()); }
private:
Storage cookies;
};
} // namespace Http
} // namespace Pistache
This diff is collapsed.
This diff is collapsed.
......@@ -2,18 +2,26 @@
#include <stdexcept>
namespace Pistache {
namespace Tcp {
namespace Pistache
{
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 Tcp
} // namespace Pistache
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -6,34 +6,41 @@
#pragma once
namespace Pistache {
template <typename Map> struct FlatMapIteratorAdapter {
typedef typename Map::key_type Key;
typedef typename Map::mapped_type Value;
typedef typename Map::const_iterator const_iterator;
explicit FlatMapIteratorAdapter(const_iterator _it) : it(_it) {}
FlatMapIteratorAdapter &operator++() {
++it;
return *this;
}
const Value &operator*() { return it->second; }
bool operator==(FlatMapIteratorAdapter other) { return other.it == it; }
bool operator!=(FlatMapIteratorAdapter other) { return !(*this == other); }
private:
const_iterator it;
};
template <typename Map>
FlatMapIteratorAdapter<Map>
makeFlatMapIterator(const Map &, typename Map::const_iterator it) {
return FlatMapIteratorAdapter<Map>(it);
}
namespace Pistache
{
template <typename Map>
struct FlatMapIteratorAdapter
{
typedef typename Map::key_type Key;
typedef typename Map::mapped_type Value;
typedef typename Map::const_iterator const_iterator;
explicit FlatMapIteratorAdapter(const_iterator _it)
: it(_it)
{ }
FlatMapIteratorAdapter& operator++()
{
++it;
return *this;
}
const Value& operator*() { return it->second; }
bool operator==(FlatMapIteratorAdapter other) { return other.it == it; }
bool operator!=(FlatMapIteratorAdapter other) { return !(*this == other); }
private:
const_iterator it;
};
template <typename Map>
FlatMapIteratorAdapter<Map>
makeFlatMapIterator(const Map&, typename Map::const_iterator it)
{
return FlatMapIteratorAdapter<Map>(it);
}
} // namespace Pistache
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -4,16 +4,17 @@
namespace Pistache
{
namespace Meta
{
namespace Hash
{
static constexpr uint64_t val64 = 0xcbf29ce484222325;
static constexpr uint64_t prime64 = 0x100000001b3;
namespace Meta
{
namespace Hash
{
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
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -22,54 +22,57 @@
#endif /* PISTACHE_USE_SSL */
namespace Pistache {
namespace Tcp {
namespace Pistache
{
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;
private:
void associateTransport(Transport* transport);
Transport* transport() const;
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 Tcp
} // 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.
#pragma once
namespace Pistache {
namespace Pistache
{
#define REQUIRES(condition) typename std::enable_if<(condition), int>::type = 0
......
This diff is collapsed.
......@@ -34,6 +34,6 @@
*
* [1] https://www.openssl.org/docs/manmaster/man3/SSL_sendfile.html
*/
ssize_t SSL_sendfile(SSL *out, int in, off_t *offset, size_t count);
ssize_t SSL_sendfile(SSL* out, int in, off_t* offset, size_t count);
#endif /* PISTACHE_USE_SSL */
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.
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.
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