X7ROOT File Manager
Current Path:
/opt/cpanel/ea-ruby27/src/passenger-release-6.1.2/src/agent/Core
opt
/
cpanel
/
ea-ruby27
/
src
/
passenger-release-6.1.2
/
src
/
agent
/
Core
/
??
..
??
ApiServer.h
(25.58 KB)
??
ApplicationPool
??
Config.h
(26.29 KB)
??
ConfigChange.cpp
(10.58 KB)
??
ConfigChange.h
(2.33 KB)
??
Controller
??
Controller.h
(16.99 KB)
??
CoreMain.cpp
(42.44 KB)
??
OptionParser.h
(22.59 KB)
??
ResponseCache.h
(18.78 KB)
??
SecurityUpdateChecker.h
(25.93 KB)
??
SpawningKit
??
TelemetryCollector.h
(19.45 KB)
Editing: Controller.h
/* * Phusion Passenger - https://www.phusionpassenger.com/ * Copyright (c) 2011-2025 Asynchronous B.V. * * "Passenger", "Phusion Passenger" and "Union Station" are registered * trademarks of Asynchronous B.V. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef _PASSENGER_CORE_CONTROLLER_H_ #define _PASSENGER_CORE_CONTROLLER_H_ //#define DEBUG_CC_EVENT_LOOP_BLOCKING #define CC_BENCHMARK_POINT(client, req, value) \ do { \ if (OXT_UNLIKELY(mainConfig.benchmarkMode == value)) { \ writeBenchmarkResponse(&client, &req); \ return; \ } \ } while (false) #include <boost/shared_ptr.hpp> #include <boost/make_shared.hpp> #include <boost/cstdint.hpp> #include <oxt/macros.hpp> #include <ev++.h> #include <sys/types.h> #include <sys/uio.h> #include <utility> #include <exception> #include <cstdio> #include <cstdlib> #include <cstddef> #include <LoggingKit/LoggingKit.h> #include <IOTools/MessageSerialization.h> #include <Constants.h> #include <ConfigKit/ConfigKit.h> #include <ServerKit/Errors.h> #include <ServerKit/HttpServer.h> #include <ServerKit/HttpHeaderParser.h> #include <MemoryKit/palloc.h> #include <DataStructures/LString.h> #include <DataStructures/StringKeyTable.h> #include <WrapperRegistry/Registry.h> #include <StaticString.h> #include <Utils.h> #include <StrIntTools/StrIntUtils.h> #include <IOTools/IOUtils.h> #include <JsonTools/JsonUtils.h> #include <Utils/HttpConstants.h> #include <Utils/Timer.h> #include <Core/Controller/Config.h> #include <Core/Controller/Client.h> #include <Core/Controller/AppResponse.h> #include <Core/Controller/TurboCaching.h> namespace Passenger { using namespace std; using namespace boost; using namespace oxt; using namespace ApplicationPool2; namespace ServerKit { extern const HashedStaticString HTTP_COOKIE; extern const HashedStaticString HTTP_SET_COOKIE; } namespace Core { class Controller: public ServerKit::HttpServer<Controller, Client> { private: typedef ServerKit::HttpServer<Controller, Client> ParentClass; typedef ServerKit::Channel Channel; typedef ServerKit::FdSinkChannel FdSinkChannel; typedef ServerKit::FdSourceChannel FdSourceChannel; typedef ServerKit::FileBufferedChannel FileBufferedChannel; typedef ServerKit::FileBufferedFdSinkChannel FileBufferedFdSinkChannel; ControllerMainConfig mainConfig; ControllerRequestConfigPtr requestConfig; StringKeyTable< boost::shared_ptr<Options> > poolOptionsCache; HashedStaticString PASSENGER_APP_GROUP_NAME; HashedStaticString PASSENGER_ENV_VARS; HashedStaticString PASSENGER_MAX_REQUESTS; HashedStaticString PASSENGER_SHOW_VERSION_IN_HEADER; HashedStaticString PASSENGER_STICKY_SESSIONS; HashedStaticString PASSENGER_STICKY_SESSIONS_COOKIE_NAME; HashedStaticString PASSENGER_STICKY_SESSIONS_COOKIE_ATTRIBUTES; HashedStaticString PASSENGER_REQUEST_OOB_WORK; HashedStaticString REMOTE_ADDR; HashedStaticString REMOTE_PORT; HashedStaticString REMOTE_USER; HashedStaticString FLAGS; HashedStaticString HTTP_COOKIE; HashedStaticString HTTP_DATE; HashedStaticString HTTP_HOST; HashedStaticString HTTP_CONTENT_LENGTH; HashedStaticString HTTP_CONTENT_TYPE; HashedStaticString HTTP_EXPECT; HashedStaticString HTTP_CONNECTION; HashedStaticString HTTP_STATUS; HashedStaticString HTTP_TRANSFER_ENCODING; friend class TurboCaching<Request>; friend class ResponseCache<Request>; struct ev_check checkWatcher; TurboCaching<Request> turboCaching; ConfigKit::Store *singleAppModeConfig; #ifdef DEBUG_CC_EVENT_LOOP_BLOCKING struct ev_prepare prepareWatcher; ev_tstamp timeBeforeBlocking; #endif /****** Initialization and shutdown ******/ void preinitialize(); /****** Stage: initialize request ******/ struct RequestAnalysis; void initializeFlags(Client *client, Request *req, RequestAnalysis &analysis); bool respondFromTurboCache(Client *client, Request *req); void initializePoolOptions(Client *client, Request *req, RequestAnalysis &analysis); void fillPoolOptionsFromConfigCaches(Options &options, psg_pool_t *pool, const ControllerRequestConfigPtr &requestConfigCache); static void fillPoolOption(Request *req, StaticString &field, const HashedStaticString &name); static void fillPoolOption(Request *req, int &field, const HashedStaticString &name); static void fillPoolOption(Request *req, bool &field, const HashedStaticString &name); static void fillPoolOption(Request *req, unsigned int &field, const HashedStaticString &name); static void fillPoolOption(Request *req, unsigned long &field, const HashedStaticString &name); static void fillPoolOption(Request *req, long &field, const HashedStaticString &name); static void fillPoolOptionSecToMsec(Request *req, unsigned int &field, const HashedStaticString &name); void createNewPoolOptions(Client *client, Request *req, const HashedStaticString &appGroupName); void setStickySessionId(Client *client, Request *req); const LString *getStickySessionCookieName(Request *req); /****** Stage: buffering body ******/ void beginBufferingBody(Client *client, Request *req); Channel::Result whenBufferingBody_onRequestBody(Client *client, Request *req, const MemoryKit::mbuf &buffer, int errcode); static void _bodyBufferFlushed(FileBufferedChannel *_channel); /****** Stage: checkout session ******/ void checkoutSession(Client *client, Request *req); static void sessionCheckedOut(const AbstractSessionPtr &session, const ExceptionPtr &e, void *userData); void sessionCheckedOutFromAnotherThread(Client *client, Request *req, AbstractSessionPtr session, ExceptionPtr e); void sessionCheckedOutFromEventLoopThread(Client *client, Request *req, const AbstractSessionPtr &session, const ExceptionPtr &e); void maybeSend100Continue(Client *client, Request *req); void initiateSession(Client *client, Request *req); void finishInitiatingSession(Client *client, Request *req); static void onSessionSocketConnected(EV_P_ ev_io *io, int revents); static void onSessionSocketConnectTimeout(EV_P_ ev_timer *io, int flag); static void checkoutSessionLater(Request *req); void reportSessionCheckoutError(Client *client, Request *req, const ExceptionPtr &e); void handleSessionInitiationError(Client *client, Request *req, const std::exception &e); int lookupCodeFromHeader(Request *req, const char* header, int statusCode); void writeRequestQueueFullExceptionErrorResponse(Client *client, Request *req, const boost::shared_ptr<RequestQueueFullException> &e); void writeSpawnExceptionErrorResponse(Client *client, Request *req, const boost::shared_ptr<SpawningKit::SpawnException> &e); void writeOtherExceptionErrorResponse(Client *client, Request *req, const ExceptionPtr &e); void endRequestWithErrorResponse(Client **c, Request **r, const SpawningKit::SpawnException &e, int statusCode); const LString* customErrorPageEnabled(Request *req); bool friendlyErrorPagesEnabled(Request *req); /****** Stage: send request to application ******/ struct SessionProtocolWorkingState; struct HttpHeaderConstructionCache; void sendHeaderToApp(Client *client, Request *req); void sendHeaderToAppWithSessionProtocol(Client *client, Request *req); static void sendBodyToAppWhenAppSinkIdle(Channel *_channel, unsigned int size); unsigned int determineMaxHeaderSizeForSessionProtocol(Request *req, SessionProtocolWorkingState &state, string delta_monotonic); bool constructHeaderForSessionProtocol(Request *req, char * restrict buffer, unsigned int &size, const SessionProtocolWorkingState &state, string delta_monotonic); void sendHeaderToAppWithHttpProtocol(Client *client, Request *req); bool constructHeaderBuffersForHttpProtocol(Request *req, struct iovec *buffers, unsigned int maxbuffers, unsigned int & restrict_ref nbuffers, unsigned int & restrict_ref dataSize, HttpHeaderConstructionCache &cache); bool sendHeaderToAppWithHttpProtocolAndWritev(Request *req, ssize_t &bytesWritten, HttpHeaderConstructionCache &cache); void sendHeaderToAppWithHttpProtocolWithBuffering(Request *req, unsigned int offset, HttpHeaderConstructionCache &cache); void sendBodyToApp(Client *client, Request *req); void maybeHalfCloseAppSinkBecauseRequestBodyEndReached(Client *client, Request *req); Channel::Result whenSendingRequest_onRequestBody(Client *client, Request *req, const MemoryKit::mbuf &buffer, int errcode); static void resumeRequestBodyChannelWhenAppSinkIdle(Channel *_channel, unsigned int size); void startBodyChannel(Client *client, Request *req); void stopBodyChannel(Client *client, Request *req); void logAppSocketWriteError(Client *client, int errcode); /****** Stage: forward application response to client ******/ static Channel::Result _onAppSourceData(Channel *_channel, const MemoryKit::mbuf &buffer, int errcode); Channel::Result onAppSourceData(Client *client, Request *req, const MemoryKit::mbuf &buffer, int errcode); void onAppResponseBegin(Client *client, Request *req); void prepareAppResponseCaching(Client *client, Request *req); void onAppResponse100Continue(Client *client, Request *req); bool constructHeaderBuffersForResponse(Request *req, struct iovec *buffers, unsigned int maxbuffers, unsigned int & restrict_ref nbuffers, unsigned int & restrict_ref dataSize, unsigned int & restrict_ref nCacheableBuffers); unsigned int constructDateHeaderBuffersForResponse(char *dateStr, unsigned int bufsize); bool sendResponseHeaderWithWritev(Client *client, Request *req, ssize_t &bytesWritten); void sendResponseHeaderWithBuffering(Client *client, Request *req, unsigned int offset); void logResponseHeaders(Client *client, Request *req, struct iovec *buffers, unsigned int nbuffers, unsigned int dataSize); void markHeaderBuffersForTurboCaching(Client *client, Request *req, struct iovec *buffers, unsigned int nbuffers); static ServerKit::HttpHeaderParser<AppResponse, ServerKit::HttpParseResponse> createAppResponseHeaderParser(ServerKit::Context *ctx, Request *req); static ServerKit::HttpChunkedBodyParser createAppResponseChunkedBodyParser( Request *req); static unsigned int formatAppResponseChunkedBodyParserLoggingPrefix(char *buf, unsigned int bufsize, void *userData); void prepareAppResponseChunkedBodyParsing(Client *client, Request *req); void writeResponseAndMarkForTurboCaching(Client *client, Request *req, const MemoryKit::mbuf &buffer); void markResponsePartForTurboCaching(Client *client, Request *req, const MemoryKit::mbuf &buffer); void maybeThrottleAppSource(Client *client, Request *req); static void _outputBuffersFlushed(FileBufferedChannel *_channel); void outputBuffersFlushed(Client *client, Request *req); static void _outputDataFlushed(FileBufferedChannel *_channel); void outputDataFlushed(Client *client, Request *req); void handleAppResponseBodyEnd(Client *client, Request *req); OXT_FORCE_INLINE void keepAliveAppConnection(Client *client, Request *req); void storeAppResponseInTurboCache(Client *client, Request *req); /***** Hooks ******/ static Channel::Result onBodyBufferData(Channel *_channel, const MemoryKit::mbuf &buffer, int errcode); #ifdef DEBUG_CC_EVENT_LOOP_BLOCKING static void onEventLoopPrepare(EV_P_ struct ev_prepare *w, int revents); #endif static void onEventLoopCheck(EV_P_ struct ev_check *w, int revents); /****** Internal utility functions ******/ void disconnectWithClientSocketWriteError(Client **client, int e); void disconnectWithAppSocketIncompleteResponseError(Client **client); void disconnectWithAppSocketReadError(Client **client, int e); void disconnectWithAppSocketWriteError(Client **client, int e); void endRequestWithAppSocketIncompleteResponse(Client **client, Request **req); void endRequestWithAppSocketReadError(Client **client, Request **req, int e); ServerKit::HeaderTable getHeadersWithContentType(Request *req); const string getFormattedMessage(Request *req, const StaticString &body); void endRequestWithSimpleResponse(Client **c, Request **r, const StaticString &body, int code = 200); void endRequestAsBadGateway(Client **client, Request **req); void endRequestAsGatewayTimeout(Client **client, Request **req); void writeBenchmarkResponse(Client **client, Request **req, bool end = true); bool getBoolOption(Request *req, const HashedStaticString &name, bool defaultValue = false); template<typename Number> static Number clamp(Number value, Number min, Number max); static void gatherBuffers(char * restrict dest, unsigned int size, const struct iovec *buffers, unsigned int nbuffers); static LString *resolveSymlink(const StaticString &path, psg_pool_t *pool); void parseCookieHeader(psg_pool_t *pool, const LString *headerValue, vector< pair<StaticString, StaticString> > &cookies) const; #ifdef DEBUG_CC_EVENT_LOOP_BLOCKING void reportLargeTimeDiff(Client *client, const char *name, ev_tstamp fromTime, ev_tstamp toTime); #endif protected: /****** Stage: initialize request ******/ virtual void onRequestBegin(Client *client, Request *req); /****** Hooks ******/ virtual void onClientAccepted(Client *client); virtual void onRequestObjectCreated(Client *client, Request *req); virtual void deinitializeClient(Client *client); virtual void reinitializeRequest(Client *client, Request *req); virtual void deinitializeRequest(Client *client, Request *req); void reinitializeAppResponse(Client *client, Request *req); void deinitializeAppResponse(Client *client, Request *req); virtual Channel::Result onRequestBody(Client *client, Request *req, const MemoryKit::mbuf &buffer, int errcode); virtual void onNextRequestEarlyReadError(Client *client, Request *req, int errcode); virtual bool shouldDisconnectClientOnShutdown(Client *client); virtual bool shouldAutoDechunkBody(Client *client, Request *req); virtual bool supportsUpgrade(Client *client, Request *req); /****** Marked virtual so that unit tests can mock these ******/ virtual void asyncGetFromApplicationPool(Request *req, ApplicationPool2::GetCallback callback); virtual int getSessionSocketConnectIoWatchConditions() const; virtual double getSessionSocketEffectiveConnectTimeout(Request *req) const; public: // If you change this value, make sure that Request::sessionCheckoutTry // has enough bits. static constexpr unsigned int MAX_SESSION_CHECKOUT_TRY = 10; typedef ControllerConfigChangeRequest ConfigChangeRequest; // Dependencies ResourceLocator *resourceLocator; WrapperRegistry::Registry *wrapperRegistry; PoolPtr appPool; /****** Initialization and shutdown ******/ Controller(ServerKit::Context *context, const ControllerSchema &schema, const Json::Value &initialConfig, const ConfigKit::Translator &translator1 = ConfigKit::DummyTranslator(), const ControllerSingleAppModeSchema *singleAppModeSchema = NULL, const Json::Value *_singleAppModeConfig = NULL, const ConfigKit::Translator &translator2 = ConfigKit::DummyTranslator() ) : ParentClass(context, schema, initialConfig, translator1), mainConfig(config), requestConfig(new ControllerRequestConfig(config)), poolOptionsCache(4), turboCaching(), singleAppModeConfig(NULL), resourceLocator(NULL) /**************************/ { if (mainConfig.singleAppMode) { singleAppModeConfig = new ConfigKit::Store(*singleAppModeSchema, *_singleAppModeConfig, translator2); } preinitialize(); } virtual ~Controller(); virtual void initialize(); /****** Hooks ******/ virtual unsigned int getClientName(const Client *client, char *buf, size_t size) const; virtual StaticString getServerName() const; /****** Configuration handling ******/ bool prepareConfigChange(const Json::Value &updates, vector<ConfigKit::Error> &errors, ControllerConfigChangeRequest &req); void commitConfigChange(ControllerConfigChangeRequest &req) BOOST_NOEXCEPT_OR_NOTHROW; /****** State and configuration ******/ unsigned int getThreadNumber() const; // Thread-safe virtual Json::Value inspectStateAsJson() const; virtual Json::Value inspectClientStateAsJson(const Client *client) const; virtual Json::Value inspectRequestStateAsJson(const Request *req) const; /****** Miscellaneous *******/ void disconnectLongRunningConnections(const StaticString &gupid); }; } // namespace Core } // namespace Passenger #endif /* _PASSENGER_CORE_CONTROLLER_H_ */
Upload File
Create Folder