mirror of
https://github.com/openappsec/openappsec.git
synced 2025-09-30 19:47:44 +03:00
First release of open-appsec source code
This commit is contained in:
4
core/message/CMakeLists.txt
Normal file
4
core/message/CMakeLists.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
link_directories(${ng_module_osrc_openssl_path}/lib)
|
||||
include_directories(${ng_module_osrc_openssl_path}/include)
|
||||
|
||||
add_library(message message.cc http_core.cc http_encoder.cc http_decoder.cc)
|
113
core/message/http_core.cc
Normal file
113
core/message/http_core.cc
Normal file
@@ -0,0 +1,113 @@
|
||||
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "messaging/http_core.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
#include "sasal.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
USE_DEBUG_FLAG(D_HTTP_REQUEST);
|
||||
|
||||
SASAL_START // Communication
|
||||
|
||||
HTTPHeaders::HTTPHeaders(const string &http_data)
|
||||
{
|
||||
static const string end_of_headers = "\r\n\r\n";
|
||||
if (http_data.find(end_of_headers) == string::npos) throw invalid_argument("Invalid headers");
|
||||
|
||||
insertHeaders(http_data);
|
||||
}
|
||||
|
||||
void
|
||||
HTTPHeaders::insertHeader(const string &_header_key, const string &_header_val)
|
||||
{
|
||||
string header_key = _header_key;
|
||||
string header_val = _header_val;
|
||||
// Removing \n from end of the value.
|
||||
if (header_val.back() == '\n') header_val.pop_back();
|
||||
// Removing \r from end of the value.
|
||||
if (header_val.back() == '\r') header_val.pop_back();
|
||||
// Transforming all the keys to lower case.
|
||||
// RFC 2616 - "Hypertext Transfer Protocol -- HTTP/1.1", Section 4.2, "Message Headers":
|
||||
// Each header field consists of a name followed by a colon (":") and the field value.
|
||||
// Field names are case-insensitive.
|
||||
transform(header_key.begin(), header_key.end(), header_key.begin(), ::tolower);
|
||||
dbgTrace(D_HTTP_REQUEST) << "Added HTTP header :'" << header_key << ": " << header_val << "'";
|
||||
headers[header_key] = move(header_val);
|
||||
}
|
||||
|
||||
void
|
||||
HTTPHeaders::insertHeader(const string &header)
|
||||
{
|
||||
if (header.empty()) return;
|
||||
|
||||
auto colon_index = header.find_first_of(":");
|
||||
|
||||
if (colon_index == string::npos) throw invalid_argument(header + " is invalid headers");
|
||||
|
||||
auto header_key = header.substr(0, colon_index);
|
||||
// Including characters of colon and space.
|
||||
auto header_val = header.substr(colon_index + 2);
|
||||
insertHeader(header_key, header_val);
|
||||
}
|
||||
|
||||
void
|
||||
HTTPHeaders::insertHeaders(const string &headers)
|
||||
{
|
||||
string header;
|
||||
stringstream ss(headers);
|
||||
while (getline(ss, header) && header != "\r") { insertHeader(header); }
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
HTTPHeaders::getHeaderVal(const string &header_key)
|
||||
{
|
||||
auto header = headers.find(header_key);
|
||||
if (header == headers.end()) return genError("Header not found.");
|
||||
return header->second;
|
||||
}
|
||||
|
||||
string
|
||||
HTTPHeaders::toString() const
|
||||
{
|
||||
string headers_as_string;
|
||||
for_each(
|
||||
headers.begin(),
|
||||
headers.end(),
|
||||
[&headers_as_string] (const pair<string, string> &header)
|
||||
{
|
||||
headers_as_string += header.first + ": " + header.second + "\r\n";
|
||||
}
|
||||
);
|
||||
return headers_as_string + "\r\n";
|
||||
}
|
||||
|
||||
|
||||
Maybe<HTTPHeaders>
|
||||
HTTPHeaders::createHTTPHeader(const string &http_data)
|
||||
{
|
||||
try {
|
||||
return move(HTTPHeaders(http_data));
|
||||
} catch(const std::exception& e) {
|
||||
return genError(e.what());
|
||||
}
|
||||
dbgAssert(false) << "Failed to create HTTP headers";
|
||||
// To justify the compiler
|
||||
return HTTPHeaders();
|
||||
}
|
||||
|
||||
SASAL_END
|
358
core/message/http_decoder.cc
Executable file
358
core/message/http_decoder.cc
Executable file
@@ -0,0 +1,358 @@
|
||||
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "http_decoder.h"
|
||||
|
||||
#include "sasal.h"
|
||||
|
||||
SASAL_START // Communication
|
||||
|
||||
using namespace std;
|
||||
|
||||
USE_DEBUG_FLAG(D_COMMUNICATION);
|
||||
|
||||
const map<HTTPStatusCode, string> errorCodeMapper = {
|
||||
{ HTTPStatusCode::HTTP_OK, "OK" },
|
||||
{ HTTPStatusCode::HTTP_NO_CONTENT, "No Content" },
|
||||
{ HTTPStatusCode::HTTP_MULTI_STATUS, "Multi Status" },
|
||||
{ HTTPStatusCode::HTTP_BAD_REQUEST, "Bad Request" },
|
||||
{ HTTPStatusCode::HTTP_UNAUTHORIZED, "Unauthorized" },
|
||||
{ HTTPStatusCode::HTTP_FORBIDDEN, "Forbidden" },
|
||||
{ HTTPStatusCode::HTTP_NOT_FOUND, "Not Found" },
|
||||
{ HTTPStatusCode::HTTP_METHOD_NOT_ALLOWED, "Method Not Allowed" },
|
||||
{ HTTPStatusCode::HTTP_PROXY_AUTHENTICATION_REQUIRED, "Proxy Authentication Required"},
|
||||
{ HTTPStatusCode::HTTP_REQUEST_TIME_OUT, "Request Timeout" },
|
||||
{ HTTPStatusCode::HTTP_PAYLOAD_TOO_LARGE, "Payload Too Large" },
|
||||
{ HTTPStatusCode::HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error" },
|
||||
{ HTTPStatusCode::HTTP_NOT_IMPLEMENTED, "Not Implemented" },
|
||||
{ HTTPStatusCode::HTTP_BAD_GATEWAY, "Bad Gateway" },
|
||||
{ HTTPStatusCode::HTTP_SERVICE_UNABAILABLE, "Service Unavailable" },
|
||||
{ HTTPStatusCode::HTTP_GATEWAY_TIMEOUT, "Gateway Timeout" },
|
||||
{ HTTPStatusCode::HTTP_UNKNOWN, "Not supported." }
|
||||
};
|
||||
|
||||
ostream &
|
||||
operator<<(ostream &os, const HTTPResponse::BadRequestResponse &response)
|
||||
{
|
||||
return os
|
||||
<< "[Message]: " << response.getMsg() << " "
|
||||
<< "[Message-ID]: " << response.getID();
|
||||
}
|
||||
|
||||
void
|
||||
HTTPResponse::BadRequestResponse::serialize(cereal::JSONInputArchive &ar)
|
||||
{
|
||||
ar(cereal::make_nvp("message", message));
|
||||
ar(cereal::make_nvp("messageId", message_id));
|
||||
}
|
||||
|
||||
HTTPDecoder::HTTPDecoder(I_Messaging::Method _method)
|
||||
:
|
||||
method(_method),
|
||||
status_code(genError("Not received")),
|
||||
headers(genError("Not received")),
|
||||
response(),
|
||||
body()
|
||||
{
|
||||
}
|
||||
|
||||
Maybe<HTTPResponse>
|
||||
HTTPDecoder::decodeBytes(const string &data)
|
||||
{
|
||||
connection_is_closed = data.empty();
|
||||
response += data;
|
||||
if (!status_code.ok()) status_code = parseStatusLine();
|
||||
if (!status_code.ok()) genError("Failed to parse the status line");
|
||||
if (!headers.ok()) headers = handleHeaders();
|
||||
|
||||
if (handleBody()) return HTTPResponse(status_code.unpack(), move(body));
|
||||
|
||||
return genError("Response not ready!");
|
||||
}
|
||||
|
||||
Maybe<HTTPHeaders>
|
||||
HTTPDecoder::handleHeaders()
|
||||
{
|
||||
auto end_of_headers = response.find("\r\n\r\n");
|
||||
if (end_of_headers == string::npos) return genError("Headers data not found.");
|
||||
end_of_headers += 4;
|
||||
|
||||
auto headers = response.substr(0, end_of_headers);
|
||||
response = response.substr(end_of_headers);
|
||||
|
||||
return HTTPHeaders::createHTTPHeader(headers);
|
||||
}
|
||||
|
||||
bool
|
||||
HTTPDecoder::handleBody()
|
||||
{
|
||||
if (!status_code.ok()) return false;
|
||||
|
||||
if (status_code.unpack() == HTTPStatusCode::HTTP_OK) {
|
||||
if (method == I_Messaging::Method::CONNECT) return true;
|
||||
}
|
||||
|
||||
if (!headers.ok()) return false;
|
||||
|
||||
body_size += response.size();
|
||||
if (status_code.unpack() == HTTPStatusCode::HTTP_NO_CONTENT) {
|
||||
if (body_size != 0) {
|
||||
dbgDebug(D_COMMUNICATION) << "Invalid body.";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
auto unpacked_headers = headers.unpack();
|
||||
auto content_length = unpacked_headers.getHeaderVal("content-length");
|
||||
if (content_length.ok()) {
|
||||
size_t body_length;
|
||||
try{
|
||||
body_length = stoi(content_length.unpack());
|
||||
} catch (const exception& err) {
|
||||
dbgDebug(D_COMMUNICATION)
|
||||
<< "Failed to convert body length to a number. Body length: "
|
||||
<< content_length.unpack();
|
||||
return false;
|
||||
}
|
||||
body += response;
|
||||
response.clear();
|
||||
return body_size == body_length;
|
||||
}
|
||||
|
||||
auto maybe_transfer_encoding = unpacked_headers.getHeaderVal("transfer-encoding");
|
||||
if (maybe_transfer_encoding.ok()) {
|
||||
auto transfer_encoding_type = maybe_transfer_encoding.unpack();
|
||||
if (transfer_encoding_type == "chunked") {
|
||||
if (Singleton::exists<I_Environment>()) {
|
||||
I_Environment *env = Singleton::Consume<I_Environment>::by<HTTPDecoder>();
|
||||
auto is_k8s_env = env->get<bool>("k8s_env");
|
||||
if (is_k8s_env.ok() && *is_k8s_env) {
|
||||
dbgDebug(D_COMMUNICATION) << "Getting Chunked Response in a k8s env";
|
||||
return getChunkedResponseK8s();
|
||||
}
|
||||
}
|
||||
return getChunkedResponse();
|
||||
}
|
||||
}
|
||||
|
||||
auto connection_header = unpacked_headers.getHeaderVal("connection");
|
||||
if (connection_header.ok()) {
|
||||
if (connection_header.unpack() == "close" && connection_is_closed) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
dbgDebug(D_COMMUNICATION) << "Transfer-Encoding method isn't supported.";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
HTTPDecoder::getChunkedResponse()
|
||||
{
|
||||
if(!isLegalChunkedResponse(response)) return false;
|
||||
|
||||
stringstream ss(response);
|
||||
string line;
|
||||
string chunk_body = "";
|
||||
size_t chunk_length = 0;
|
||||
while (getline(ss, line) && line != "\r") {
|
||||
if (chunk_body.length() == chunk_length) {
|
||||
body += chunk_body;
|
||||
chunk_body = "";
|
||||
try {
|
||||
chunk_length = stoi(line, nullptr, 16);
|
||||
} catch (const exception& err) {
|
||||
dbgDebug(D_COMMUNICATION) << "Failed to convert chunk length to a number. Line: " << line;
|
||||
return false;
|
||||
}
|
||||
} else if (chunk_body.length() > chunk_length) {
|
||||
dbgDebug(D_COMMUNICATION) << "Invalid chunked data structure.";
|
||||
return false;
|
||||
} else {
|
||||
if (line.back() == '\r') {
|
||||
line.pop_back();
|
||||
}
|
||||
if (!chunk_body.empty()) {
|
||||
chunk_body += '\n';
|
||||
}
|
||||
chunk_body += line;
|
||||
}
|
||||
}
|
||||
|
||||
if (chunk_length != 0) {
|
||||
dbgDebug(D_COMMUNICATION) << "Invalid chunked data structure.";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// LCOV_EXCL_START Reason: Will be deleted in INXT-31454
|
||||
bool
|
||||
HTTPDecoder::getChunkedResponseK8s()
|
||||
{
|
||||
if(!isLegalChunkedResponse(response)) return false;
|
||||
|
||||
stringstream ss(response);
|
||||
string line;
|
||||
string chunk_body = "";
|
||||
size_t chunk_length = 0;
|
||||
while (getline(ss, line)) {
|
||||
if(line == "\r"){
|
||||
continue;
|
||||
}
|
||||
if (chunk_body.length() == chunk_length) {
|
||||
body += chunk_body;
|
||||
chunk_body = "";
|
||||
try {
|
||||
chunk_length = stoi(line, nullptr, 16);
|
||||
} catch (const exception& err) {
|
||||
dbgDebug(D_COMMUNICATION) << "Failed to convert chunk length to a number. Line: " << line;
|
||||
return false;
|
||||
}
|
||||
} else if (chunk_body.length() > chunk_length) {
|
||||
dbgDebug(D_COMMUNICATION) << "Invalid chunked data structure.";
|
||||
return false;
|
||||
} else {
|
||||
if (line.back() == '\r') {
|
||||
line.pop_back();
|
||||
}
|
||||
if (!chunk_body.empty()) {
|
||||
chunk_body += '\n';
|
||||
chunk_length = chunk_length + 1;
|
||||
}
|
||||
chunk_body += line;
|
||||
}
|
||||
}
|
||||
|
||||
if (chunk_length != 0) {
|
||||
dbgDebug(D_COMMUNICATION) << "Invalid chunked data structure.";
|
||||
if (chunk_body.length() == chunk_length) {
|
||||
body += chunk_body;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
bool
|
||||
HTTPDecoder::isLegalChunkedResponse(const string &res)
|
||||
{
|
||||
auto end_of_data = res.find("0\r\n\r\n");
|
||||
return end_of_data != string::npos && res.length() == end_of_data + 5;
|
||||
}
|
||||
|
||||
Maybe<HTTPStatusCode>
|
||||
HTTPDecoder::parseStatusLine()
|
||||
{
|
||||
auto end_of_first_line = response.find("\r\n");
|
||||
if (end_of_first_line == string::npos) return genError("No Status Line was received.");
|
||||
auto status = response.substr(0, end_of_first_line);
|
||||
// Removing the status
|
||||
response = response.substr(end_of_first_line + 2);
|
||||
// Also status text can be supported at the future.
|
||||
if (status.find("HTTP/1.") != string::npos) {
|
||||
int status_num;
|
||||
try {
|
||||
status_num = stoi(status.substr(9, 3));
|
||||
} catch (const exception& err) {
|
||||
return genError("Failed to convert status code to a number. Status code: " + status.substr(9, 3));
|
||||
}
|
||||
switch (status_num)
|
||||
{
|
||||
case 200: {
|
||||
return HTTPStatusCode::HTTP_OK;
|
||||
}
|
||||
case 204: {
|
||||
return HTTPStatusCode::HTTP_NO_CONTENT;
|
||||
}
|
||||
case 207: {
|
||||
return HTTPStatusCode::HTTP_MULTI_STATUS;
|
||||
}
|
||||
case 400: {
|
||||
return HTTPStatusCode::HTTP_BAD_REQUEST;
|
||||
}
|
||||
case 401: {
|
||||
return HTTPStatusCode::HTTP_UNAUTHORIZED;
|
||||
}
|
||||
case 403: {
|
||||
return HTTPStatusCode::HTTP_FORBIDDEN;
|
||||
}
|
||||
case 404: {
|
||||
return HTTPStatusCode::HTTP_NOT_FOUND;
|
||||
}
|
||||
case 405: {
|
||||
return HTTPStatusCode::HTTP_METHOD_NOT_ALLOWED;
|
||||
}
|
||||
case 408: {
|
||||
return HTTPStatusCode::HTTP_REQUEST_TIME_OUT;
|
||||
}
|
||||
case 413: {
|
||||
return HTTPStatusCode::HTTP_PAYLOAD_TOO_LARGE;
|
||||
}
|
||||
case 500: {
|
||||
return HTTPStatusCode::HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
case 501: {
|
||||
return HTTPStatusCode::HTTP_NOT_IMPLEMENTED;
|
||||
}
|
||||
case 502: {
|
||||
return HTTPStatusCode::HTTP_BAD_GATEWAY;
|
||||
}
|
||||
case 503: {
|
||||
return HTTPStatusCode::HTTP_SERVICE_UNABAILABLE;
|
||||
}
|
||||
case 504: {
|
||||
return HTTPStatusCode::HTTP_GATEWAY_TIMEOUT;
|
||||
}
|
||||
default: {
|
||||
dbgWarning(D_COMMUNICATION) << "Unknown HTTP status code: " << status_num;
|
||||
return HTTPStatusCode::HTTP_UNKNOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
return genError("Status code not found.");
|
||||
}
|
||||
|
||||
HTTPResponse::HTTPResponse(const HTTPStatusCode _status_code, const string &&_body)
|
||||
:
|
||||
status_code(_status_code),
|
||||
body(move(_body))
|
||||
{
|
||||
}
|
||||
|
||||
Maybe<string>
|
||||
HTTPResponse::getResponse() const
|
||||
{
|
||||
if (status_code == HTTPStatusCode::HTTP_OK || status_code == HTTPStatusCode::HTTP_NO_CONTENT) return body;
|
||||
|
||||
try {
|
||||
stringstream in;
|
||||
in << body;
|
||||
cereal::JSONInputArchive in_ar(in);
|
||||
BadRequestResponse response_details;
|
||||
response_details.serialize(in_ar);
|
||||
dbgWarning(D_COMMUNICATION) << "Response details: " << response_details;
|
||||
} catch (...) {}
|
||||
|
||||
string status_code_str = to_string(static_cast<int>(status_code));
|
||||
auto status_code_message = errorCodeMapper.find(status_code);
|
||||
if(status_code_message == errorCodeMapper.end()) {
|
||||
dbgWarning(D_COMMUNICATION) << "Failed to parse HTTP status code message. Status code: " << status_code_str;
|
||||
return genError(string("Request failed, Status code: ") + status_code_str);
|
||||
}
|
||||
return genError(string("Request failed, Error: ") + status_code_str + " " + status_code_message->second);
|
||||
}
|
||||
|
||||
SASAL_END
|
55
core/message/http_decoder.h
Executable file
55
core/message/http_decoder.h
Executable file
@@ -0,0 +1,55 @@
|
||||
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef __HTTP_DECODDER_H__
|
||||
#define __HTTP_DECODDER_H__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "singleton.h"
|
||||
#include "maybe_res.h"
|
||||
#include "messaging/http_core.h"
|
||||
#include "i_message_decoder.h"
|
||||
#include "i_messaging.h"
|
||||
#include "i_environment.h"
|
||||
|
||||
class HTTPDecoder
|
||||
:
|
||||
public I_MessageDecoder <HTTPResponse>,
|
||||
Singleton::Consume<I_Environment>
|
||||
{
|
||||
public:
|
||||
HTTPDecoder(I_Messaging::Method _method);
|
||||
|
||||
Maybe<HTTPResponse> decodeBytes(const std::string &data) override;
|
||||
|
||||
private:
|
||||
Maybe<HTTPHeaders> handleHeaders();
|
||||
Maybe<HTTPStatusCode> parseStatusLine();
|
||||
bool handleBody();
|
||||
|
||||
bool getChunkedResponse();
|
||||
bool getChunkedResponseK8s();
|
||||
bool isLegalChunkedResponse(const std::string &res);
|
||||
|
||||
I_Messaging::Method method;
|
||||
bool connection_is_closed = false;
|
||||
|
||||
Maybe<HTTPStatusCode> status_code;
|
||||
Maybe<HTTPHeaders> headers;
|
||||
std::string response;
|
||||
std::string body;
|
||||
size_t body_size = 0;
|
||||
};
|
||||
|
||||
#endif // __HTTP_DECODDER_H__
|
176
core/message/http_encoder.cc
Executable file
176
core/message/http_encoder.cc
Executable file
@@ -0,0 +1,176 @@
|
||||
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "http_encoder.h"
|
||||
#include "debug.h"
|
||||
#include "sasal.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
SASAL_START // Communication
|
||||
|
||||
USE_DEBUG_FLAG(D_COMMUNICATION);
|
||||
|
||||
HTTPRequest::HTTPRequest(const string &_method_statement, const string &_host, const bool to_proxy)
|
||||
:
|
||||
method_statement(_method_statement)
|
||||
{
|
||||
if (to_proxy) {
|
||||
insertHeader("Accept: */*");
|
||||
insertHeader("Proxy-Connection: Keep-Alive");
|
||||
}
|
||||
insertHeader("Host", _host);
|
||||
}
|
||||
|
||||
HTTPRequest::HTTPRequest(const string &_method_statement)
|
||||
:
|
||||
method_statement(_method_statement)
|
||||
{
|
||||
}
|
||||
|
||||
HTTPRequest &
|
||||
HTTPRequest::insertHeader(const string &header_key, const string &header_val)
|
||||
{
|
||||
headers.insertHeader(header_key, header_val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
HTTPRequest &
|
||||
HTTPRequest::insertHeader(const string &header)
|
||||
{
|
||||
try {
|
||||
headers.insertHeader(header);
|
||||
} catch(const std::exception& e) {
|
||||
dbgWarning(D_COMMUNICATION) << "Failed to insert header. Header: " << header;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
HTTPRequest &
|
||||
HTTPRequest::insertHeaders(const string &rec_headers)
|
||||
{
|
||||
try {
|
||||
headers.insertHeaders(rec_headers);
|
||||
} catch(const std::exception& e) {
|
||||
dbgWarning(D_COMMUNICATION) << "Failed to insert headers. Headers: " << rec_headers;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
HTTPRequest &
|
||||
HTTPRequest::insertBody(const string &reqest_body)
|
||||
{
|
||||
body = reqest_body;
|
||||
return *this;
|
||||
}
|
||||
|
||||
string
|
||||
HTTPRequest::toString() const
|
||||
{
|
||||
string ret = method_statement + "\r\n";
|
||||
ret += headers.toString();
|
||||
ret += body;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ConnectRequest::ConnectRequest(const string &_host, const string &_port)
|
||||
:
|
||||
HTTPRequest("CONNECT " + _host + ":" + _port + " HTTP/1.1")
|
||||
{
|
||||
insertHeader("Host", _host + ":" + _port);
|
||||
}
|
||||
|
||||
PostRequest::PostRequest(const string &_post_path, const string &_host, bool to_proxy)
|
||||
:
|
||||
HTTPRequest("POST " + (to_proxy ? "http://" + _host: "") + _post_path + " HTTP/1.1", _host, to_proxy)
|
||||
{
|
||||
}
|
||||
|
||||
PutRequest::PutRequest(const string &_put_path, const string &_host, bool to_proxy)
|
||||
:
|
||||
HTTPRequest("PUT " + (to_proxy ? "http://" + _host : "") + _put_path + " HTTP/1.1", _host, to_proxy)
|
||||
{
|
||||
}
|
||||
|
||||
GetRequest::GetRequest(const string &_get_path, const string &_host, bool to_proxy)
|
||||
:
|
||||
HTTPRequest("GET " + (to_proxy ? "http://" + _host: "") + _get_path + " HTTP/1.1", _host, to_proxy)
|
||||
{
|
||||
}
|
||||
|
||||
PatchRequest::PatchRequest(const string &_patch_path, const string &_host, bool to_proxy)
|
||||
:
|
||||
HTTPRequest("PATCH " + (to_proxy ? "http://" + _host: "") + _patch_path + " HTTP/1.1", _host, to_proxy)
|
||||
{
|
||||
}
|
||||
|
||||
HTTPEncoder::HTTPEncoder::HTTPEncoder(const string &_host, const string &_port)
|
||||
:
|
||||
host(_host),
|
||||
port(_port)
|
||||
{
|
||||
}
|
||||
|
||||
HTTPRequest &
|
||||
HTTPEncoder::Connect()
|
||||
{
|
||||
request = ConnectRequest(host, port);
|
||||
request.insertHeader("Proxy-Connection: Keep-Alive");
|
||||
return request;
|
||||
}
|
||||
|
||||
HTTPRequest &
|
||||
HTTPEncoder::Post(const string &_post_path)
|
||||
{
|
||||
request = PostRequest(_post_path, host, over_proxy && !over_ssl);
|
||||
return request;
|
||||
}
|
||||
|
||||
HTTPRequest &
|
||||
HTTPEncoder::Put(const string &_put_path)
|
||||
{
|
||||
request = PutRequest(_put_path, host, over_proxy && !over_ssl);
|
||||
return request;
|
||||
}
|
||||
|
||||
HTTPRequest &
|
||||
HTTPEncoder::Patch(const string &_patch_path)
|
||||
{
|
||||
request = PatchRequest(_patch_path, host, over_proxy && !over_ssl);
|
||||
return request;
|
||||
}
|
||||
|
||||
HTTPRequest &
|
||||
HTTPEncoder::Get(const string &_get_path)
|
||||
{
|
||||
request = GetRequest(_get_path, host, over_proxy && !over_ssl);
|
||||
return request;
|
||||
}
|
||||
|
||||
HTTPEncoder &
|
||||
HTTPEncoder::isOverProxy()
|
||||
{
|
||||
over_proxy = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
HTTPEncoder &
|
||||
HTTPEncoder::isOverSSL()
|
||||
{
|
||||
over_ssl = true;
|
||||
return *this;
|
||||
};
|
||||
|
||||
SASAL_END
|
26
core/message/i_message_decoder.h
Normal file
26
core/message/i_message_decoder.h
Normal file
@@ -0,0 +1,26 @@
|
||||
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef __I_MESSAGE_DECODER_H__
|
||||
#define __I_MESSAGE_DECODER_H__
|
||||
|
||||
#include <string>
|
||||
|
||||
template <class T>
|
||||
class I_MessageDecoder
|
||||
{
|
||||
public:
|
||||
virtual Maybe<T> decodeBytes(const std::string &data) = 0;
|
||||
};
|
||||
|
||||
#endif // __I_MESSAGE_DECODER_H__
|
2081
core/message/message.cc
Executable file
2081
core/message/message.cc
Executable file
File diff suppressed because it is too large
Load Diff
58
core/message/message_metric.h
Executable file
58
core/message/message_metric.h
Executable file
@@ -0,0 +1,58 @@
|
||||
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef __MESSAGE_METRIC_H__
|
||||
#define __MESSAGE_METRIC_H__
|
||||
|
||||
#include "generic_metric.h"
|
||||
|
||||
class MessageQueueEvent : public Event<MessageQueueEvent>
|
||||
{
|
||||
public:
|
||||
void
|
||||
setMessageQueueSize(uint64_t _queue_size)
|
||||
{
|
||||
queue_size = _queue_size;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
getMessageQueueSize() const
|
||||
{
|
||||
return queue_size;
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t queue_size;
|
||||
};
|
||||
|
||||
class MessageQueueMetric
|
||||
:
|
||||
public GenericMetric,
|
||||
public Listener<MessageQueueEvent>
|
||||
{
|
||||
public:
|
||||
void
|
||||
upon(const MessageQueueEvent &event) override
|
||||
{
|
||||
max_queue_size.report(event.getMessageQueueSize());
|
||||
avg_queue_size.report(double(event.getMessageQueueSize()));
|
||||
current_queue_size.report(event.getMessageQueueSize());
|
||||
}
|
||||
|
||||
private:
|
||||
MetricCalculations::Max<uint64_t> max_queue_size{this, "messageQueueMaxSizeSample", 0};
|
||||
MetricCalculations::Average<double> avg_queue_size{this, "messageQueueAvgSizeSample"};
|
||||
MetricCalculations::LastReportedValue<uint64_t> current_queue_size{this, "messageQueueCurrentSizeSample"};
|
||||
};
|
||||
|
||||
#endif // __MESSAGE_METRIC_H__
|
74
core/message/smart_bio.h
Normal file
74
core/message/smart_bio.h
Normal file
@@ -0,0 +1,74 @@
|
||||
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef __SMART_BIO_H__
|
||||
#define __SMART_BIO_H__
|
||||
|
||||
#include "openssl/ssl.h"
|
||||
#include "openssl/err.h"
|
||||
#include "openssl/bio.h"
|
||||
#include "openssl/x509v3.h"
|
||||
|
||||
namespace smartBIO
|
||||
{
|
||||
|
||||
template<class T> struct Destrctor;
|
||||
|
||||
template<>
|
||||
struct Destrctor<BIO>
|
||||
{
|
||||
void
|
||||
operator()(BIO *pointer) const
|
||||
{
|
||||
if (pointer != nullptr) BIO_free_all(pointer);
|
||||
}
|
||||
};
|
||||
|
||||
// LCOV_EXCL_START Reason: No ssl ut
|
||||
template<>
|
||||
struct Destrctor<SSL_CTX>
|
||||
{
|
||||
void
|
||||
operator()(SSL_CTX *pointer) const
|
||||
{
|
||||
if (pointer != nullptr) SSL_CTX_free(pointer);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Destrctor<X509>
|
||||
{
|
||||
void
|
||||
operator()(X509 *pointer) const
|
||||
{
|
||||
if (pointer != nullptr) X509_free(pointer);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Destrctor<EVP_PKEY>
|
||||
{
|
||||
void
|
||||
operator()(EVP_PKEY *pointer) const
|
||||
{
|
||||
if (pointer != nullptr) EVP_PKEY_free(pointer);
|
||||
}
|
||||
};
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
template<class OpenSSLType>
|
||||
using BioUniquePtr = std::unique_ptr<OpenSSLType, smartBIO::Destrctor<OpenSSLType>>;
|
||||
|
||||
} // namespace SmartBIO
|
||||
|
||||
#endif // __SMART_BIO_H__
|
Reference in New Issue
Block a user