diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..3c316f8 --- /dev/null +++ b/.clang-format @@ -0,0 +1,151 @@ +--- +Language: Cpp +# BasedOnStyle: Google +AccessModifierOffset: -1 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Left +AlignOperands: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: true +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Attach +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: true +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^' + Priority: 2 + - Regex: '^<.*\.h>' + Priority: 1 + - Regex: '^<.*' + Priority: 2 + - Regex: '.*' + Priority: 3 +IncludeIsMainRegex: '([-_](test|unittest))?$' +IndentCaseLabels: true +IndentPPDirectives: None +IndentWidth: 2 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Never +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Left +RawStringFormats: + - Language: Cpp + Delimiters: + - cc + - CC + - cpp + - Cpp + - CPP + - 'c++' + - 'C++' + CanonicalDelimiter: '' + BasedOnStyle: google + - Language: TextProto + Delimiters: + - pb + - PB + - proto + - PROTO + EnclosingFunctions: + - EqualsProto + - EquivToProto + - PARSE_PARTIAL_TEXT_PROTO + - PARSE_TEST_PROTO + - PARSE_TEXT_PROTO + - ParseTextOrDie + - ParseTextProtoOrDie + CanonicalDelimiter: '' + BasedOnStyle: google +ReflowComments: true +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Auto +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 8 +UseTab: Never +... + diff --git a/connection.cc b/connection.cc index 2de81f2..11cc4f7 100644 --- a/connection.cc +++ b/connection.cc @@ -9,143 +9,145 @@ namespace firecgi { -Connection::Connection(int sock, const sockaddr_in6& client_addr, const std::function& callback, int max_request_len) - : sock_(sock), - callback_(callback), - buf_(sock, max_request_len), - request_(this) { - char client_addr_str[INET6_ADDRSTRLEN]; - PCHECK(inet_ntop(AF_INET6, &client_addr.sin6_addr, client_addr_str, sizeof(client_addr_str))); +Connection::Connection(int sock, const sockaddr_in6 &client_addr, + const std::function &callback, + int max_request_len) + : sock_(sock), + callback_(callback), + buf_(sock, max_request_len), + request_(this) { + char client_addr_str[INET6_ADDRSTRLEN]; + PCHECK(inet_ntop(AF_INET6, &client_addr.sin6_addr, client_addr_str, + sizeof(client_addr_str))); - LOG(INFO) << "new connection: [" << client_addr_str << "]:" << ntohs(client_addr.sin6_port); + LOG(INFO) << "new connection: [" << client_addr_str + << "]:" << ntohs(client_addr.sin6_port); } Connection::~Connection() { - PCHECK(close(sock_) == 0); - LOG(INFO) << "connection closed (handled " << requests_ << " requests)"; + PCHECK(close(sock_) == 0); + LOG(INFO) << "connection closed (handled " << requests_ << " requests)"; } -bool Connection::Write(const std::vector& vecs) { - ssize_t total_size = 0; - for (const auto& vec : vecs) { - total_size += vec.iov_len; - } - return writev(sock_, vecs.data(), vecs.size()) == total_size; +bool Connection::Write(const std::vector &vecs) { + ssize_t total_size = 0; + for (const auto &vec : vecs) { + total_size += vec.iov_len; + } + return writev(sock_, vecs.data(), vecs.size()) == total_size; } int Connection::Read() { - if (!buf_.Refill()) { - return sock_; - } + if (!buf_.Refill()) { + return sock_; + } - while (true) { - buf_.ResetRead(); + while (true) { + buf_.ResetRead(); - const auto *header = buf_.ReadObj
(); - if (!header) { - break; - } + const auto *header = buf_.ReadObj
(); + if (!header) { + break; + } - if (header->version != 1) { - LOG(ERROR) << "invalid FastCGI protocol version: " << header->version; - return sock_; - } + if (header->version != 1) { + LOG(ERROR) << "invalid FastCGI protocol version: " << header->version; + return sock_; + } - if (buf_.ReadMaxLen() < header->ContentLength()) { - break; - } + if (buf_.ReadMaxLen() < header->ContentLength()) { + break; + } - switch (header->type) { - case 1: - { - if (header->ContentLength() != sizeof(BeginRequest)) { - LOG(ERROR) << "FCGI_BeginRequestBody is the wrong length: " << header->ContentLength(); - return sock_; - } + switch (header->type) { + case 1: { + if (header->ContentLength() != sizeof(BeginRequest)) { + LOG(ERROR) << "FCGI_BeginRequestBody is the wrong length: " + << header->ContentLength(); + return sock_; + } - const auto *begin_request = CHECK_NOTNULL(buf_.ReadObj()); + const auto *begin_request = CHECK_NOTNULL(buf_.ReadObj()); - if (begin_request->Role() != 1) { - LOG(ERROR) << "unsupported FastCGI role: " << begin_request->Role(); - return sock_; - } + if (begin_request->Role() != 1) { + LOG(ERROR) << "unsupported FastCGI role: " << begin_request->Role(); + return sock_; + } - request_.NewRequest(header->RequestId()); - } - break; + request_.NewRequest(header->RequestId()); + } break; - case 4: - { - if (header->RequestId() != request_.RequestId()) { - LOG(ERROR) << "out of order FCGI_PARAMS record, or client is multiplexing requests (which we don't support)"; - return sock_; - } + case 4: { + if (header->RequestId() != request_.RequestId()) { + LOG(ERROR) << "out of order FCGI_PARAMS record, or client is " + "multiplexing requests (which we don't support)"; + return sock_; + } - firebuf::ConstBuffer param_buf(buf_.Read(header->ContentLength()), header->ContentLength()); - while (param_buf.ReadMaxLen() > 0) { - const auto *param_header = param_buf.ReadObj(); - if (!param_header) { - LOG(ERROR) << "FCGI_PARAMS missing header"; - return sock_; - } + firebuf::ConstBuffer param_buf(buf_.Read(header->ContentLength()), + header->ContentLength()); + while (param_buf.ReadMaxLen() > 0) { + const auto *param_header = param_buf.ReadObj(); + if (!param_header) { + LOG(ERROR) << "FCGI_PARAMS missing header"; + return sock_; + } - const auto *key_buf = param_buf.Read(param_header->key_length); - if (!key_buf) { - LOG(ERROR) << "FCGI_PARAMS missing key"; - return sock_; - } - std::string_view key(key_buf, param_header->key_length); + const auto *key_buf = param_buf.Read(param_header->key_length); + if (!key_buf) { + LOG(ERROR) << "FCGI_PARAMS missing key"; + return sock_; + } + std::string_view key(key_buf, param_header->key_length); - const auto *value_buf = param_buf.Read(param_header->value_length); - if (!value_buf) { - LOG(ERROR) << "FCGI_PARAMS missing value"; - return sock_; - } - std::string_view value(value_buf, param_header->value_length); + const auto *value_buf = param_buf.Read(param_header->value_length); + if (!value_buf) { + LOG(ERROR) << "FCGI_PARAMS missing value"; + return sock_; + } + std::string_view value(value_buf, param_header->value_length); - request_.AddParam(key, value); - } - } - break; + request_.AddParam(key, value); + } + } break; - case 5: - { - if (header->RequestId() != request_.RequestId()) { - LOG(ERROR) << "out of order FCGI_STDIN record, or client is multiplexing requests (which we don't support)"; - return sock_; - } + case 5: { + if (header->RequestId() != request_.RequestId()) { + LOG(ERROR) << "out of order FCGI_STDIN record, or client is " + "multiplexing requests (which we don't support)"; + return sock_; + } - if (header->ContentLength() == 0) { - // Magic signal for completed request (mirrors the HTTP/1.1 protocol) - requests_++; - callback_(&request_); - buf_.Consume(); // discard data and invalidate pointers - } else { - if (!request_.GetBody().empty()) { - LOG(ERROR) << "received multiple stdin records. have you set \"fastcgi_request_buffering on\"?"; - } - request_.SetBody({buf_.Read(header->ContentLength()), header->ContentLength()}); - } - } - break; + if (header->ContentLength() == 0) { + // Magic signal for completed request (mirrors the HTTP/1.1 protocol) + requests_++; + callback_(&request_); + buf_.Consume(); // discard data and invalidate pointers + } else { + if (!request_.GetBody().empty()) { + LOG(ERROR) << "received multiple stdin records. have you set " + "\"fastcgi_request_buffering on\"?"; + } + request_.SetBody( + {buf_.Read(header->ContentLength()), header->ContentLength()}); + } + } break; - default: - LOG(ERROR) << "unknown record type: " << header->type; - return sock_; - } + default: + LOG(ERROR) << "unknown record type: " << header->type; + return sock_; + } - if (!buf_.Discard(header->padding_length)) { - break; - } + if (!buf_.Discard(header->padding_length)) { + break; + } - buf_.Commit(); // we've acted on the bytes read so far - } + buf_.Commit(); // we've acted on the bytes read so far + } - return -1; + return -1; } -uint64_t Connection::Requests() const { - return requests_; -} +uint64_t Connection::Requests() const { return requests_; } -} // namespace firecgi +} // namespace firecgi diff --git a/connection.h b/connection.h index 46978b9..716dfd3 100644 --- a/connection.h +++ b/connection.h @@ -1,7 +1,7 @@ #pragma once -#include #include +#include #include #include @@ -12,23 +12,24 @@ namespace firecgi { class Connection { - public: - Connection(int sock, const sockaddr_in6& client_addr, const std::function& callback, int max_request_len); - ~Connection(); + public: + Connection(int sock, const sockaddr_in6& client_addr, + const std::function& callback, + int max_request_len); + ~Connection(); - [[nodiscard]] int Read(); - [[nodiscard]] bool Write(const std::vector& vecs); + [[nodiscard]] int Read(); + [[nodiscard]] bool Write(const std::vector& vecs); - [[nodiscard]] uint64_t Requests() const; + [[nodiscard]] uint64_t Requests() const; - private: - const int sock_; - const std::function& callback_; - firebuf::StreamBuffer buf_; - Request request_; - - uint64_t requests_ = 0; + private: + const int sock_; + const std::function& callback_; + firebuf::StreamBuffer buf_; + Request request_; + uint64_t requests_ = 0; }; -} // namespace firecgi +} // namespace firecgi diff --git a/connection_afl.cc b/connection_afl.cc index 209b5f5..ff78eb7 100644 --- a/connection_afl.cc +++ b/connection_afl.cc @@ -1,18 +1,20 @@ #include "connection.h" int main(int argc, char* argv[]) { - FLAGS_logtostderr = 1; - FLAGS_minloglevel = 3; - google::InitGoogleLogging(argv[0]); - gflags::ParseCommandLineFlags(&argc, &argv, true); + FLAGS_logtostderr = 1; + FLAGS_minloglevel = 3; + google::InitGoogleLogging(argv[0]); + gflags::ParseCommandLineFlags(&argc, &argv, true); - { - firecgi::Connection conn(STDIN_FILENO, {}, [](firecgi::Request* req) { req->End(); }, {}, 16*1024); - static_cast(conn.Read()); - } + { + firecgi::Connection conn( + STDIN_FILENO, {}, [](firecgi::Request* req) { req->End(); }, {}, + 16 * 1024); + static_cast(conn.Read()); + } - gflags::ShutDownCommandLineFlags(); - google::ShutdownGoogleLogging(); + gflags::ShutDownCommandLineFlags(); + google::ShutdownGoogleLogging(); - return 0; + return 0; } diff --git a/example_simple.cc b/example_simple.cc index 162f3c9..6511417 100644 --- a/example_simple.cc +++ b/example_simple.cc @@ -6,18 +6,21 @@ DEFINE_int32(port, 9000, "TCP port to bind"); DEFINE_int32(threads, 1, "Number of server threads"); -int main(int argc, char *argv[]) { - google::InitGoogleLogging(argv[0]); - gflags::ParseCommandLineFlags(&argc, &argv, true); +int main(int argc, char* argv[]) { + google::InitGoogleLogging(argv[0]); + gflags::ParseCommandLineFlags(&argc, &argv, true); - firecgi::Server server(FLAGS_port, [](firecgi::Request* request) { - request->WriteHeader("Content-Type", "text/plain"); - request->WriteBody("Hello world"); - request->End(); - }, FLAGS_threads); - server.RegisterSignalHandlers(); - server.Serve(); + firecgi::Server server( + FLAGS_port, + [](firecgi::Request* request) { + request->WriteHeader("Content-Type", "text/plain"); + request->WriteBody("Hello world"); + request->End(); + }, + FLAGS_threads); + server.RegisterSignalHandlers(); + server.Serve(); - gflags::ShutDownCommandLineFlags(); - google::ShutdownGoogleLogging(); + gflags::ShutDownCommandLineFlags(); + google::ShutdownGoogleLogging(); } diff --git a/firebuf b/firebuf index 2102147..858b291 160000 --- a/firebuf +++ b/firebuf @@ -1 +1 @@ -Subproject commit 2102147a2f4212a7c361e9d16d985f66ee127946 +Subproject commit 858b291f46b438a48d20e0a11c64195d2e3fd305 diff --git a/fireusage b/fireusage index a70d79e..7972d25 160000 --- a/fireusage +++ b/fireusage @@ -1 +1 @@ -Subproject commit a70d79e869e5a8dabf6bb25f5494695f1a502b9b +Subproject commit 7972d253ab3b7f1eb11383bf4e0c4958c4ad6606 diff --git a/parse.cc b/parse.cc index 815f946..f81c74d 100644 --- a/parse.cc +++ b/parse.cc @@ -3,9 +3,9 @@ namespace firecgi { Header::Header(uint8_t type_in, uint16_t request_id, uint16_t content_length) - : type(type_in) { - SetRequestId(request_id); - SetContentLength(content_length); + : type(type_in) { + SetRequestId(request_id); + SetContentLength(content_length); } -} // namespace firecgi +} // namespace firecgi diff --git a/parse.h b/parse.h index 6bf038f..8af9d45 100644 --- a/parse.h +++ b/parse.h @@ -5,43 +5,46 @@ namespace firecgi { struct Header { - Header(uint8_t type_in, uint16_t request_id, uint16_t content_length); + Header(uint8_t type_in, uint16_t request_id, uint16_t content_length); - uint8_t version = 1; - uint8_t type; - private: - uint16_t request_id_; // network byte order - uint16_t content_length_; // network byte order - public: - uint8_t padding_length = 0; - uint8_t reserved = 0; + uint8_t version = 1; + uint8_t type; - uint16_t RequestId() const { return ntohs(request_id_); } - uint16_t ContentLength() const { return ntohs(content_length_); } + private: + uint16_t request_id_; // network byte order + uint16_t content_length_; // network byte order + public: + uint8_t padding_length = 0; + uint8_t reserved = 0; - void SetRequestId(uint16_t request_id) { request_id_ = htons(request_id); } - void SetContentLength(uint16_t content_length) { content_length_ = htons(content_length); } + uint16_t RequestId() const { return ntohs(request_id_); } + uint16_t ContentLength() const { return ntohs(content_length_); } + + void SetRequestId(uint16_t request_id) { request_id_ = htons(request_id); } + void SetContentLength(uint16_t content_length) { + content_length_ = htons(content_length); + } }; struct BeginRequest { - private: - uint16_t role_; // network byte order - public: - uint8_t flags; - uint8_t reserved[5]; + private: + uint16_t role_; // network byte order + public: + uint8_t flags; + uint8_t reserved[5]; - uint16_t Role() const { return ntohs(role_); } + uint16_t Role() const { return ntohs(role_); } }; struct EndRequest { - uint32_t app_status = htonl(0); // network byte order - uint8_t protocol_status; - uint8_t reserved[3] = {}; + uint32_t app_status = htonl(0); // network byte order + uint8_t protocol_status; + uint8_t reserved[3] = {}; }; struct ParamHeader { - uint8_t key_length; - uint8_t value_length; + uint8_t key_length; + uint8_t value_length; }; -} // namespace firecgi +} // namespace firecgi diff --git a/request.cc b/request.cc index 9924691..d83ad4f 100644 --- a/request.cc +++ b/request.cc @@ -7,137 +7,132 @@ namespace firecgi { namespace { -template void AppendVec(const T& obj, std::vector* vec) { - vec->push_back(iovec{ - .iov_base = (void*)(&obj), - .iov_len = sizeof(obj), - }); +template +void AppendVec(const T& obj, std::vector* vec) { + vec->push_back(iovec{ + .iov_base = (void*)(&obj), + .iov_len = sizeof(obj), + }); } -} // namespace +} // namespace -Request::Request(Connection* conn) - : conn_(conn), - out_buf_(64*1024) {} +Request::Request(Connection* conn) : conn_(conn), out_buf_(64 * 1024) {} Request::~Request() { - if (on_close_) { - on_close_(); - } + if (on_close_) { + on_close_(); + } } void Request::NewRequest(uint16_t request_id) { - if (on_close_) { - on_close_(); - } + if (on_close_) { + on_close_(); + } - request_id_ = request_id; - params_.clear(); - body_ = {}; - on_close_ = nullptr; - out_buf_.Reset(); - body_written_ = false; + request_id_ = request_id; + params_.clear(); + body_ = {}; + on_close_ = nullptr; + out_buf_.Reset(); + body_written_ = false; } -uint16_t Request::RequestId() const { - return request_id_; +uint16_t Request::RequestId() const { return request_id_; } + +void Request::AddParam(const std::string_view& key, + const std::string_view& value) { + params_.try_emplace(key, value); } -void Request::AddParam(const std::string_view& key, const std::string_view& value) { - params_.try_emplace(key, value); -} - -void Request::SetBody(const std::string_view& body) { - body_ = body; -} +void Request::SetBody(const std::string_view& body) { body_ = body; } const std::string_view& Request::GetParam(const std::string_view& key) const { - auto iter = params_.find(key); - if (iter == params_.end()) { - static const std::string_view none; - return none; - } - return iter->second; + auto iter = params_.find(key); + if (iter == params_.end()) { + static const std::string_view none; + return none; + } + return iter->second; } -const std::string_view& Request::GetBody() const { - return body_; -} +const std::string_view& Request::GetBody() const { return body_; } void Request::OnClose(const std::function& on_close) { - on_close_ = on_close; + on_close_ = on_close; } -void Request::WriteHeader(const std::string_view& name, const std::string_view& value) { - std::lock_guard l(output_mu_); +void Request::WriteHeader(const std::string_view& name, + const std::string_view& value) { + std::lock_guard l(output_mu_); - CHECK(!body_written_); - CHECK(out_buf_.Write(name)); - CHECK(out_buf_.Write(": ")); - CHECK(out_buf_.Write(value)); - CHECK(out_buf_.Write("\n")); + CHECK(!body_written_); + CHECK(out_buf_.Write(name)); + CHECK(out_buf_.Write(": ")); + CHECK(out_buf_.Write(value)); + CHECK(out_buf_.Write("\n")); } void Request::WriteBody(const std::string_view& body) { - std::lock_guard l(output_mu_); - if (!body_written_) { - CHECK(out_buf_.Write("\n")); - body_written_ = true; - } - // TODO: make this able to span multiple packets - CHECK(out_buf_.Write(body)); + std::lock_guard l(output_mu_); + if (!body_written_) { + CHECK(out_buf_.Write("\n")); + body_written_ = true; + } + // TODO: make this able to span multiple packets + CHECK(out_buf_.Write(body)); } bool Request::Flush() { - std::lock_guard l(output_mu_); + std::lock_guard l(output_mu_); - std::vector vecs; + std::vector vecs; - auto header = OutputHeader(); - AppendVec(header, &vecs); + auto header = OutputHeader(); + AppendVec(header, &vecs); - vecs.push_back(OutputVec()); + vecs.push_back(OutputVec()); - if (!conn_->Write(vecs)) { - return false; - } - out_buf_.Commit(); - out_buf_.Consume(); - return true; + if (!conn_->Write(vecs)) { + return false; + } + out_buf_.Commit(); + out_buf_.Consume(); + return true; } bool Request::End() { - std::lock_guard l(output_mu_); + std::lock_guard l(output_mu_); - WriteBody(""); + WriteBody(""); - std::vector vecs; + std::vector vecs; - // Must be outside if block, so it lives through Write() below - auto output_header = OutputHeader(); - if (output_header.ContentLength()) { - AppendVec(output_header, &vecs); - vecs.push_back(OutputVec()); - } + // Must be outside if block, so it lives through Write() below + auto output_header = OutputHeader(); + if (output_header.ContentLength()) { + AppendVec(output_header, &vecs); + vecs.push_back(OutputVec()); + } - EndRequest end; - Header end_header(3, request_id_, sizeof(end)); - AppendVec(end_header, &vecs); - AppendVec(end, &vecs); + EndRequest end; + Header end_header(3, request_id_, sizeof(end)); + AppendVec(end_header, &vecs); + AppendVec(end, &vecs); - return conn_->Write(vecs); + return conn_->Write(vecs); } iovec Request::OutputVec() { - const auto output_len = out_buf_.ReadMaxLen(); - return iovec{ - .iov_base = (void *)(CHECK_NOTNULL(out_buf_.Read(output_len))), - .iov_len = output_len, - }; + const auto output_len = out_buf_.ReadMaxLen(); + return iovec{ + .iov_base = (void*)(CHECK_NOTNULL(out_buf_.Read(output_len))), + .iov_len = output_len, + }; } Header Request::OutputHeader() { - return Header(6, request_id_, out_buf_.ReadMaxLen()); + return Header(6, request_id_, out_buf_.ReadMaxLen()); } -} // namespace firecgi +} // namespace firecgi diff --git a/request.h b/request.h index b6a27f4..a6175d0 100644 --- a/request.h +++ b/request.h @@ -13,61 +13,61 @@ namespace firecgi { class Connection; class Request { - public: - Request(Connection *conn); - ~Request(); + public: + Request(Connection* conn); + ~Request(); - void NewRequest(uint16_t request_id); + void NewRequest(uint16_t request_id); - uint16_t RequestId() const; + uint16_t RequestId() const; - void AddParam(const std::string_view& key, const std::string_view& value); - void SetBody(const std::string_view& in); + void AddParam(const std::string_view& key, const std::string_view& value); + void SetBody(const std::string_view& in); - const std::string_view& GetParam(const std::string_view& key) const; - const std::string_view& GetBody() const; + const std::string_view& GetParam(const std::string_view& key) const; + const std::string_view& GetBody() const; - void OnClose(const std::function& callback); + void OnClose(const std::function& callback); - void WriteHeader(const std::string_view& name, const std::string_view& value); - void WriteBody(const std::string_view& body); - [[nodiscard]] bool Flush(); - bool End(); + void WriteHeader(const std::string_view& name, const std::string_view& value); + void WriteBody(const std::string_view& body); + [[nodiscard]] bool Flush(); + bool End(); - template - void WriteBody(const std::string_view& first, Args... more); + template + void WriteBody(const std::string_view& first, Args... more); - template - T InTransaction(const std::function& callback); + template + T InTransaction(const std::function& callback); - private: - Header OutputHeader(); - iovec OutputVec(); + private: + Header OutputHeader(); + iovec OutputVec(); - Connection *conn_; - uint16_t request_id_ = 0; + Connection* conn_; + uint16_t request_id_ = 0; - std::unordered_map params_; - std::string_view body_; + std::unordered_map params_; + std::string_view body_; - std::function on_close_; + std::function on_close_; - firebuf::Buffer out_buf_; - bool body_written_; - std::recursive_mutex output_mu_; + firebuf::Buffer out_buf_; + bool body_written_; + std::recursive_mutex output_mu_; }; -template +template void Request::WriteBody(const std::string_view& first, Args... more) { - std::lock_guard l(output_mu_); - WriteBody(first); - WriteBody(more...); + std::lock_guard l(output_mu_); + WriteBody(first); + WriteBody(more...); } -template +template T Request::InTransaction(const std::function& callback) { - std::lock_guard l(output_mu_); - return callback(); + std::lock_guard l(output_mu_); + return callback(); } -} // namespace firecgi +} // namespace firecgi diff --git a/server.cc b/server.cc index deca4cc..88e6858 100644 --- a/server.cc +++ b/server.cc @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -7,176 +6,180 @@ #include #include #include +#include #include #include "fireusage/usage.h" -#include "server.h" #include "connection.h" +#include "server.h" namespace firecgi { -Server::Server(int port, const std::function& callback, int threads, int max_request_len) - : port_(port), - callback_(callback), - threads_(threads), - max_request_len_(max_request_len), - close_fd_(eventfd(0, 0)) { - CHECK_GE(close_fd_, 0); +Server::Server(int port, const std::function& callback, + int threads, int max_request_len) + : port_(port), + callback_(callback), + threads_(threads), + max_request_len_(max_request_len), + close_fd_(eventfd(0, 0)) { + CHECK_GE(close_fd_, 0); - LOG(INFO) << "listening on [::1]:" << port_; - signal(SIGPIPE, SIG_IGN); + LOG(INFO) << "listening on [::1]:" << port_; + signal(SIGPIPE, SIG_IGN); } -Server::~Server() { - PCHECK(close(close_fd_) == 0); -} +Server::~Server() { PCHECK(close(close_fd_) == 0); } void Server::Serve() { - std::vector threads; - for (int i = 0; i < threads_ - 1; ++i) { - threads.emplace_back([this]() { ServeInt(); }); - } - ServeInt(); - for (auto& thread : threads) { - thread.join(); - } - LOG(INFO) << "all threads shut down"; + std::vector threads; + for (int i = 0; i < threads_ - 1; ++i) { + threads.emplace_back([this]() { ServeInt(); }); + } + ServeInt(); + for (auto& thread : threads) { + thread.join(); + } + LOG(INFO) << "all threads shut down"; } void Server::Shutdown() { - uint64_t shutdown = 1; - PCHECK(write(close_fd_, &shutdown, sizeof(shutdown)) == sizeof(shutdown)); + uint64_t shutdown = 1; + PCHECK(write(close_fd_, &shutdown, sizeof(shutdown)) == sizeof(shutdown)); } namespace { Server* shutdown_server = nullptr; -} // namespace +} // namespace void Server::RegisterSignalHandlers() { - shutdown_server = this; - for (auto sig : {SIGINT, SIGTERM}) { - signal(sig, [](int signum) { - LOG(INFO) << "received " << strsignal(signum); - shutdown_server->Shutdown(); - }); - } + shutdown_server = this; + for (auto sig : {SIGINT, SIGTERM}) { + signal(sig, [](int signum) { + LOG(INFO) << "received " << strsignal(signum); + shutdown_server->Shutdown(); + }); + } } void Server::ServeInt() { - auto epoll_fd = epoll_create1(0); - PCHECK(epoll_fd >= 0) << "epoll_create()"; + auto epoll_fd = epoll_create1(0); + PCHECK(epoll_fd >= 0) << "epoll_create()"; - auto listen_sock = NewListenSock(); + auto listen_sock = NewListenSock(); - char new_conn; - { - struct epoll_event ev{ - .events = EPOLLIN, - .data = { - .ptr = &new_conn, - }, - }; - PCHECK(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_sock, &ev) == 0); - } + char new_conn; + { + struct epoll_event ev { + .events = EPOLLIN, + .data = { + .ptr = &new_conn, + }, + }; + PCHECK(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_sock, &ev) == 0); + } - char shutdown; - { - struct epoll_event ev{ - .events = EPOLLIN, - .data = { - .ptr = &shutdown, - }, - }; - PCHECK(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, close_fd_, &ev) == 0); - } + char shutdown; + { + struct epoll_event ev { + .events = EPOLLIN, + .data = { + .ptr = &shutdown, + }, + }; + PCHECK(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, close_fd_, &ev) == 0); + } - std::unordered_set connections; + std::unordered_set connections; - fireusage::UsageTracker usage_tracker; - usage_tracker.Start(); + fireusage::UsageTracker usage_tracker; + usage_tracker.Start(); - while (true) { - constexpr auto max_events = 256; - struct epoll_event events[max_events]; - auto num_fd = epoll_wait(epoll_fd, events, max_events, -1); - if (num_fd == -1 && errno == EINTR) { - continue; - } - PCHECK(num_fd > 0) << "epoll_wait()"; + while (true) { + constexpr auto max_events = 256; + struct epoll_event events[max_events]; + auto num_fd = epoll_wait(epoll_fd, events, max_events, -1); + if (num_fd == -1 && errno == EINTR) { + continue; + } + PCHECK(num_fd > 0) << "epoll_wait()"; - for (auto i = 0; i < num_fd; ++i) { - if (events[i].data.ptr == &new_conn) { - connections.insert(CHECK_NOTNULL(NewConn(listen_sock, epoll_fd))); - } else if (events[i].data.ptr == &shutdown) { - for (auto& conn : connections) { - usage_tracker.AddEvents(conn->Requests()); - delete conn; - } - usage_tracker.Stop(); - PCHECK(close(listen_sock) == 0); - PCHECK(close(epoll_fd) == 0); - usage_tracker.Log("requests"); - return; - } else { - auto conn = static_cast(events[i].data.ptr); - auto fd = conn->Read(); - if (fd != -1) { - PCHECK(epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, nullptr) == 0); - usage_tracker.AddEvents(conn->Requests()); - connections.erase(conn); - delete conn; - } - } - } - } + for (auto i = 0; i < num_fd; ++i) { + if (events[i].data.ptr == &new_conn) { + connections.insert(CHECK_NOTNULL(NewConn(listen_sock, epoll_fd))); + } else if (events[i].data.ptr == &shutdown) { + for (auto& conn : connections) { + usage_tracker.AddEvents(conn->Requests()); + delete conn; + } + usage_tracker.Stop(); + PCHECK(close(listen_sock) == 0); + PCHECK(close(epoll_fd) == 0); + usage_tracker.Log("requests"); + return; + } else { + auto conn = static_cast(events[i].data.ptr); + auto fd = conn->Read(); + if (fd != -1) { + PCHECK(epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, nullptr) == 0); + usage_tracker.AddEvents(conn->Requests()); + connections.erase(conn); + delete conn; + } + } + } + } } Connection* Server::NewConn(int listen_sock, int epoll_fd) { - sockaddr_in6 client_addr; - socklen_t client_addr_len = sizeof(client_addr); + sockaddr_in6 client_addr; + socklen_t client_addr_len = sizeof(client_addr); - auto client_sock = accept(listen_sock, (sockaddr*) &client_addr, &client_addr_len); - PCHECK(client_sock >= 0) << "accept()"; - CHECK_EQ(client_addr.sin6_family, AF_INET6); + auto client_sock = + accept(listen_sock, (sockaddr*)&client_addr, &client_addr_len); + PCHECK(client_sock >= 0) << "accept()"; + CHECK_EQ(client_addr.sin6_family, AF_INET6); - int flags = 1; - PCHECK(setsockopt(client_sock, SOL_TCP, TCP_NODELAY, &flags, sizeof(flags)) == 0); + int flags = 1; + PCHECK(setsockopt(client_sock, SOL_TCP, TCP_NODELAY, &flags, sizeof(flags)) == + 0); - auto *conn = new Connection(client_sock, client_addr, callback_, max_request_len_); - { - struct epoll_event ev{ - .events = EPOLLIN, - .data = { - .ptr = conn, - }, - }; - PCHECK(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_sock, &ev) == 0); - } + auto* conn = + new Connection(client_sock, client_addr, callback_, max_request_len_); + { + struct epoll_event ev { + .events = EPOLLIN, + .data = { + .ptr = conn, + }, + }; + PCHECK(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_sock, &ev) == 0); + } - return conn; + return conn; } int Server::NewListenSock() { - auto sock = socket(AF_INET6, SOCK_STREAM, 0); - PCHECK(sock >= 0) << "socket()"; + auto sock = socket(AF_INET6, SOCK_STREAM, 0); + PCHECK(sock >= 0) << "socket()"; - { - int optval = 1; - PCHECK(setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)) == 0); - } + { + int optval = 1; + PCHECK(setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &optval, + sizeof(optval)) == 0); + } - { - sockaddr_in6 bind_addr = { - .sin6_family = AF_INET6, - .sin6_port = htons(port_), - .sin6_addr = IN6ADDR_LOOPBACK_INIT, - }; - PCHECK(bind(sock, (sockaddr*) &bind_addr, sizeof(bind_addr)) == 0); - } + { + sockaddr_in6 bind_addr = { + .sin6_family = AF_INET6, + .sin6_port = htons(port_), + .sin6_addr = IN6ADDR_LOOPBACK_INIT, + }; + PCHECK(bind(sock, (sockaddr*)&bind_addr, sizeof(bind_addr)) == 0); + } - PCHECK(listen(sock, 128) == 0); - return sock; + PCHECK(listen(sock, 128) == 0); + return sock; } -} // namespace firecgi +} // namespace firecgi diff --git a/server.h b/server.h index e79ef5d..2f12f12 100644 --- a/server.h +++ b/server.h @@ -9,25 +9,26 @@ namespace firecgi { class Server { - public: - Server(int port, const std::function& callback, int threads=1, int max_request_len=(16*1024)); - ~Server(); + public: + Server(int port, const std::function& callback, + int threads = 1, int max_request_len = (16 * 1024)); + ~Server(); - void Serve(); - void Shutdown(); - void RegisterSignalHandlers(); + void Serve(); + void Shutdown(); + void RegisterSignalHandlers(); - private: - Connection *NewConn(int listen_sock, int epoll_fd); - int NewListenSock(); - void ServeInt(); + private: + Connection* NewConn(int listen_sock, int epoll_fd); + int NewListenSock(); + void ServeInt(); - const int port_; - const std::function callback_; - const int threads_; - const int max_request_len_; + const int port_; + const std::function callback_; + const int threads_; + const int max_request_len_; - int close_fd_; + int close_fd_; }; -} // firecgi +} // namespace firecgi