1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-09 00:00:00 +01:00

api: refactoring to fix undefined behavior

This commit is contained in:
Steffen Vogel 2020-09-30 17:56:12 +02:00
parent e59cd8ac15
commit 770e9c2f2c
21 changed files with 86 additions and 82 deletions

View file

@ -32,11 +32,6 @@ namespace villas {
namespace node {
namespace api {
/* Forward declarations */
class Session;
class Response;
class RequestFactory;
class NodeRequest : public Request {
public:

View file

@ -32,11 +32,6 @@ namespace villas {
namespace node {
namespace api {
/* Forward declarations */
class Session;
class Response;
class RequestFactory;
class PathRequest : public Request {
public:

View file

@ -53,28 +53,18 @@ protected:
Logger logger;
public:
std::string uri;
std::smatch matches;
Session::Method method;
json_t *body;
RequestFactory *factory;
enum Method {
UNKNOWN,
GET,
POST,
DELETE,
OPTIONS,
PUT,
PATCH
} method;
Request(Session *s) :
session(s),
logger(logging.get("api:request")),
method(Session::Method::UNKNOWN),
body(nullptr),
factory(nullptr),
method(Method::UNKNOWN)
factory(nullptr)
{ }
virtual ~Request()
@ -106,7 +96,7 @@ public:
make(Session *s) = 0;
static Request *
make(Session *s, const std::string &uri, Request::Method meth);
create(Session *s);
};
template<typename T, const char *name, const char *re, const char *desc>

View file

@ -60,10 +60,24 @@ public:
VERSION_2 = 2
};
enum Method {
UNKNOWN,
GET,
POST,
DELETE,
OPTIONS,
PUT,
PATCH
};
protected:
enum State state;
enum Version version;
std::string uri;
Method method;
unsigned long contentLength;
lws *wsi;
Web *web;
@ -97,11 +111,14 @@ public:
void execute();
void shutdown();
static int protocolCallback(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len);
static int
protocolCallback(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len);
int getRequestMethod(struct lws *wsi);
Method getRequestMethod() const;
std::string getRequestURI() const;
static std::string methodToString(int meth);
static std::string
methodToString(Method meth);
};

View file

@ -34,10 +34,9 @@ using namespace villas::node;
using namespace villas::node::api;
InvalidMethod::InvalidMethod(Request *req) :
BadRequest(
fmt::format("The '{}' API endpoint does not support {} requests",
req->factory->getName(), Session::methodToString(req->method)
)
BadRequest("The '{}' API endpoint does not support {} requests",
req->factory->getName(),
Session::methodToString(req->method)
)
{ }

View file

@ -28,8 +28,11 @@
using namespace villas;
using namespace villas::node::api;
Request * RequestFactory::make(Session *s, const std::string &uri, Request::Method meth)
Request * RequestFactory::create(Session *s)
{
auto uri = s->getRequestURI();
auto meth = s->getRequestMethod();
for (auto *rf : plugin::Registry::lookup<RequestFactory>()) {
std::smatch mr;
if (not rf->match(uri, mr))
@ -40,13 +43,12 @@ Request * RequestFactory::make(Session *s, const std::string &uri, Request::Meth
p->matches = mr;
p->factory = rf;
p->method = meth;
p->uri = uri;
return p;
}
throw BadRequest("Unknown API request", "{ s: s, s: i }",
throw BadRequest("Unknown API request", "{ s: s, s: s }",
"uri", uri.c_str(),
"method", meth
"method", Session::methodToString(meth).c_str()
);
}

View file

@ -42,7 +42,7 @@ public:
json_t *json_formats = json_array();
json_t *json_name;
if (method != Method::GET)
if (method != Session::Method::GET)
throw InvalidMethod(this);
if (body != nullptr)

View file

@ -38,7 +38,7 @@ public:
{
json_t *cfg = session->getSuperNode()->getConfig();
if (method != Method::GET)
if (method != Session::Method::GET)
throw InvalidMethod(this);
if (body != nullptr)

View file

@ -43,7 +43,7 @@ public:
virtual Response * execute()
{
if (method != Method::POST)
if (method != Session::Method::POST)
throw InvalidMethod(this);
if (body != nullptr)

View file

@ -39,7 +39,7 @@ public:
virtual Response * execute()
{
if (method != Method::GET && method != Method::POST)
if (method != Session::Method::GET && method != Session::Method::POST)
throw InvalidMethod(this);
if (body != nullptr)

View file

@ -42,7 +42,7 @@ public:
virtual Response * execute()
{
if (method != Method::GET)
if (method != Session::Method::GET)
throw InvalidMethod(this);
if (body != nullptr)

View file

@ -43,7 +43,7 @@ public:
virtual Response * execute()
{
if (method != Method::GET)
if (method != Session::Method::GET)
throw InvalidMethod(this);
if (body != nullptr)

View file

@ -43,7 +43,7 @@ public:
virtual Response * execute()
{
if (method != Method::POST)
if (method != Session::Method::POST)
throw InvalidMethod(this);
if (body != nullptr)

View file

@ -42,7 +42,7 @@ public:
virtual Response * execute()
{
if (method != Method::GET)
if (method != Session::Method::GET)
throw InvalidMethod(this);
if (body != nullptr)

View file

@ -43,7 +43,7 @@ public:
virtual Response * execute()
{
if (method != Method::POST)
if (method != Session::Method::POST)
throw InvalidMethod(this);
if (body != nullptr)

View file

@ -42,7 +42,7 @@ public:
virtual Response * execute()
{
if (method != Method::GET)
if (method != Session::Method::GET)
throw InvalidMethod(this);
if (body != nullptr)

View file

@ -43,7 +43,7 @@ public:
virtual Response * execute()
{
if (method != Method::GET)
if (method != Session::Method::GET)
throw InvalidMethod(this);
if (body != nullptr)

View file

@ -63,7 +63,7 @@ public:
int ret;
json_error_t err;
if (method != Method::POST)
if (method != Session::Method::POST)
throw InvalidMethod(this);
const char *cfg = nullptr;

View file

@ -37,7 +37,7 @@ public:
virtual Response * execute()
{
if (method != Method::POST)
if (method != Session::Method::POST)
throw InvalidMethod(this);
if (body != nullptr)

View file

@ -42,7 +42,7 @@ public:
struct lws_context *ctx = lws_get_context(s->wsi);
char buf[4096];
if (method != Method::GET)
if (method != Session::Method::GET)
throw InvalidMethod(this);
if (body != nullptr)

View file

@ -37,6 +37,9 @@ using namespace villas::node;
using namespace villas::node::api;
Session::Session(lws *w) :
uri(),
method(Method::UNKNOWN),
contentLength(0),
wsi(w),
logger(logging.get("api:session"))
{
@ -73,21 +76,21 @@ void Session::execute()
{
Request *r = request.exchange(nullptr);
logger->debug("Running API request: uri={}, method={}", r->uri, r->method);
logger->debug("Running API request: uri={}, method={}", uri, method);
try {
r->prepare();
response = r->execute();
logger->debug("Completed API request: request={}", r->uri, r->method);
logger->debug("Completed API request: request={}", uri, method);
} catch (const Error &e) {
response = new ErrorResponse(this, e);
logger->warn("API request failed: uri={}, method={}, code={}: {}", r->uri, r->method, e.code, e.what());
logger->warn("API request failed: uri={}, method={}, code={}: {}", uri, method, e.code, e.what());
} catch (const RuntimeError &e) {
response = new ErrorResponse(this, e);
logger->warn("API request failed: uri={}, method={}: {}", r->uri, r->method, e.what());
logger->warn("API request failed: uri={}, method={}: {}", uri, method, e.what());
}
logger->debug("Ran pending API requests. Triggering on_writeable callback: wsi={}", (void *) wsi);
@ -124,17 +127,15 @@ void Session::open(void *in, size_t len)
{
int ret;
char buf[32];
unsigned long contentLength;
Request::Method meth;
std::string uri = reinterpret_cast<char *>(in);
uri = reinterpret_cast<char *>(in);
try {
meth = (Request::Method) getRequestMethod(wsi);
if (meth == Request::Method::UNKNOWN)
auto method = getRequestMethod();
if (method == Method::UNKNOWN)
throw RuntimeError("Invalid request method");
request = RequestFactory::make(this, uri, meth);
request = RequestFactory::create(this);
ret = lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_HTTP_CONTENT_LENGTH);
if (ret < 0)
@ -150,7 +151,7 @@ void Session::open(void *in, size_t len)
*
* We immediatly send headers and close the connection
* without waiting for a POST body */
if (meth == Request::Method::OPTIONS)
if (method == Method::OPTIONS)
lws_callback_on_writable(wsi);
/* This request has no body.
* We can reply immediatly */
@ -317,43 +318,48 @@ int Session::protocolCallback(struct lws *wsi, enum lws_callback_reasons reason,
return 0;
}
int Session::getRequestMethod(struct lws *wsi)
std::string Session::getRequestURI() const
{
if (lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI))
return Request::Method::GET;
else if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI))
return Request::Method::POST;
#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL)
else if (lws_hdr_total_length(wsi, WSI_TOKEN_PUT_URI))
return Request::Method::PUT;
else if (lws_hdr_total_length(wsi, WSI_TOKEN_PATCH_URI))
return Request::Method::PATCH;
else if (lws_hdr_total_length(wsi, WSI_TOKEN_OPTIONS_URI))
return Request::Method::OPTIONS;
#endif
else
return Request::Method::UNKNOWN;
return uri;
}
std::string Session::methodToString(int method)
Session::Method Session::getRequestMethod() const
{
if (lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI))
return Method::GET;
else if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI))
return Method::POST;
#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL)
else if (lws_hdr_total_length(wsi, WSI_TOKEN_PUT_URI))
return Method::PUT;
else if (lws_hdr_total_length(wsi, WSI_TOKEN_PATCH_URI))
return Method::PATCH;
else if (lws_hdr_total_length(wsi, WSI_TOKEN_OPTIONS_URI))
return Method::OPTIONS;
#endif
else
return Method::UNKNOWN;
}
std::string Session::methodToString(Method method)
{
switch (method) {
case Request::Method::POST:
case Method::POST:
return "POST";
case Request::Method::GET:
case Method::GET:
return "GET";
case Request::Method::DELETE:
case Method::DELETE:
return "DELETE";
case Request::Method::PUT:
case Method::PUT:
return "PUT";
case Request::Method::PATCH:
case Method::PATCH:
return "GPATCHET";
case Request::Method::OPTIONS:
case Method::OPTIONS:
return "OPTIONS";
default: