Re-use Request, instead of re-create. Add asan target.

This commit is contained in:
flamingcow
2019-05-07 22:56:00 -07:00
parent c571e47bae
commit a4171b0ae1
9 changed files with 37 additions and 24 deletions

View File

@@ -37,3 +37,7 @@ test_connection: connection_afl
@echo "Running $$(ls testcases | wc -l) tests" @echo "Running $$(ls testcases | wc -l) tests"
for FILE in testcases/*; do ./connection_afl < $$FILE; done for FILE in testcases/*; do ./connection_afl < $$FILE; done
@printf '\033[0;32mALL TESTS PASSED\033[0m\n' @printf '\033[0;32mALL TESTS PASSED\033[0m\n'
asan:
$(MAKE) clean
FIRE_CXXFLAGS="-O1 -g -fsanitize=address -fno-omit-frame-pointer -std=gnu++2a -Wall -Werror" $(MAKE) all

View File

@@ -9,11 +9,12 @@
namespace firecgi { namespace firecgi {
Connection::Connection(int sock, const sockaddr_in6& client_addr, const std::function<void(std::unique_ptr<Request>)>& callback, const std::unordered_set<std::string_view>& headers) Connection::Connection(int sock, const sockaddr_in6& client_addr, const std::function<void(Request*)>& callback, const std::unordered_set<std::string_view>& headers)
: sock_(sock), : sock_(sock),
callback_(callback), callback_(callback),
headers_(headers), headers_(headers),
buf_(sock, max_record_len) { buf_(sock, max_record_len),
request_(this) {
char client_addr_str[INET6_ADDRSTRLEN]; char client_addr_str[INET6_ADDRSTRLEN];
PCHECK(inet_ntop(AF_INET6, &client_addr.sin6_addr, client_addr_str, sizeof(client_addr_str))); PCHECK(inet_ntop(AF_INET6, &client_addr.sin6_addr, client_addr_str, sizeof(client_addr_str)));
@@ -70,13 +71,13 @@ int Connection::Read() {
return sock_; return sock_;
} }
request_.reset(new Request(header->RequestId(), this)); request_.NewRequest(header->RequestId());
} }
break; break;
case 4: case 4:
{ {
if (request_ == nullptr || header->RequestId() != request_->RequestId()) { if (header->RequestId() != request_.RequestId()) {
LOG(ERROR) << "out of order FCGI_PARAMS record, or client is multiplexing requests (which we don't support)"; LOG(ERROR) << "out of order FCGI_PARAMS record, or client is multiplexing requests (which we don't support)";
return sock_; return sock_;
} }
@@ -104,7 +105,7 @@ int Connection::Read() {
std::string_view value(value_buf, param_header->value_length); std::string_view value(value_buf, param_header->value_length);
if (headers_.find(key) != headers_.end()) { if (headers_.find(key) != headers_.end()) {
request_->AddParam(key, value); request_.AddParam(key, value);
} }
} }
} }
@@ -112,7 +113,7 @@ int Connection::Read() {
case 5: case 5:
{ {
if (request_ == nullptr || header->RequestId() != request_->RequestId()) { if (header->RequestId() != request_.RequestId()) {
LOG(ERROR) << "out of order FCGI_STDIN record, or client is multiplexing requests (which we don't support)"; LOG(ERROR) << "out of order FCGI_STDIN record, or client is multiplexing requests (which we don't support)";
return sock_; return sock_;
} }
@@ -120,10 +121,10 @@ int Connection::Read() {
if (header->ContentLength() == 0) { if (header->ContentLength() == 0) {
// Magic signal for completed request (mirrors the HTTP/1.1 protocol) // Magic signal for completed request (mirrors the HTTP/1.1 protocol)
requests_++; requests_++;
callback_(std::move(request_)); callback_(&request_);
} else { } else {
std::string_view in(buf_.Read(header->ContentLength()), header->ContentLength()); std::string_view in(buf_.Read(header->ContentLength()), header->ContentLength());
request_->AddIn(in); request_.AddIn(in);
} }
} }
break; break;

View File

@@ -13,7 +13,7 @@ namespace firecgi {
class Connection { class Connection {
public: public:
Connection(int sock, const sockaddr_in6& client_addr, const std::function<void(std::unique_ptr<Request>)>& callback, const std::unordered_set<std::string_view>& headers); Connection(int sock, const sockaddr_in6& client_addr, const std::function<void(Request*)>& callback, const std::unordered_set<std::string_view>& headers);
~Connection(); ~Connection();
[[nodiscard]] int Read(); [[nodiscard]] int Read();
@@ -21,14 +21,13 @@ class Connection {
private: private:
const int sock_; const int sock_;
const std::function<void(std::unique_ptr<Request>)>& callback_; const std::function<void(Request*)>& callback_;
const std::unordered_set<std::string_view>& headers_; const std::unordered_set<std::string_view>& headers_;
firebuf::StreamBuffer buf_;
Request request_;
uint64_t requests_ = 0; uint64_t requests_ = 0;
firebuf::StreamBuffer buf_;
std::unique_ptr<Request> request_;
}; };
} // namespace firecgi } // namespace firecgi

View File

@@ -10,7 +10,7 @@ int main(int argc, char *argv[]) {
google::InitGoogleLogging(argv[0]); google::InitGoogleLogging(argv[0]);
gflags::ParseCommandLineFlags(&argc, &argv, true); gflags::ParseCommandLineFlags(&argc, &argv, true);
firecgi::Server server(FLAGS_port, [](std::unique_ptr<firecgi::Request> request) { firecgi::Server server(FLAGS_port, [](firecgi::Request* request) {
request->WriteHeader("Content-Type", "text/plain"); request->WriteHeader("Content-Type", "text/plain");
request->WriteBody("Hello world"); request->WriteBody("Hello world");
request->End(); request->End();

Submodule firebuf updated: acc75058c6...fa20ad9d29

View File

@@ -11,7 +11,7 @@
namespace firecgi { namespace firecgi {
Server::Server(int port, const std::function<void(std::unique_ptr<Request>)>& callback, int threads, const std::unordered_set<std::string_view>& headers) Server::Server(int port, const std::function<void(Request*)>& callback, int threads, const std::unordered_set<std::string_view>& headers)
: port_(port), : port_(port),
callback_(callback), callback_(callback),
threads_(threads), threads_(threads),

View File

@@ -10,7 +10,7 @@ namespace firecgi {
class Server { class Server {
public: public:
Server(int port, const std::function<void(std::unique_ptr<Request>)>& callback, int threads=1, const std::unordered_set<std::string_view>& headers={}); Server(int port, const std::function<void(Request*)>& callback, int threads=1, const std::unordered_set<std::string_view>& headers={});
void Serve(); void Serve();
private: private:
@@ -19,7 +19,7 @@ class Server {
void ServeInt(); void ServeInt();
const int port_; const int port_;
const std::function<void(std::unique_ptr<Request>)> callback_; const std::function<void(Request*)> callback_;
const int threads_; const int threads_;
const std::unordered_set<std::string_view> headers_; const std::unordered_set<std::string_view> headers_;
}; };

View File

@@ -16,11 +16,18 @@ template<class T> void AppendVec(const T& obj, std::vector<iovec>* vec) {
} // namespace } // namespace
Request::Request(uint16_t request_id, Connection* conn) Request::Request(Connection* conn)
: request_id_(request_id), : conn_(conn),
conn_(conn),
out_buf_(max_record_len) {} out_buf_(max_record_len) {}
void Request::NewRequest(uint16_t request_id) {
request_id_ = request_id;
params_.clear();
in_.clear();
out_buf_.Reset();
body_written_ = false;
}
uint16_t Request::RequestId() { uint16_t Request::RequestId() {
return request_id_; return request_id_;
} }

View File

@@ -12,7 +12,9 @@ class Connection;
class Request { class Request {
public: public:
Request(uint16_t request_id, Connection *conn); Request(Connection *conn);
void NewRequest(uint16_t request_id);
uint16_t RequestId(); uint16_t RequestId();
@@ -30,14 +32,14 @@ class Request {
Header OutputHeader(); Header OutputHeader();
iovec OutputVec(); iovec OutputVec();
const uint16_t request_id_;
Connection *conn_; Connection *conn_;
uint16_t request_id_ = 0;
std::unordered_map<std::string, std::string> params_; std::unordered_map<std::string, std::string> params_;
std::string in_; std::string in_;
firebuf::Buffer out_buf_; firebuf::Buffer out_buf_;
bool body_written_ = false; bool body_written_;
}; };
} // namespace firecgi } // namespace firecgi