| /* | |
| Licensed to the Apache Software Foundation (ASF) under one | |
| or more contributor license agreements. See the NOTICE file | |
| distributed with this work for additional information | |
| regarding copyright ownership. The ASF licenses this file | |
| to you under the Apache License, Version 2.0 (the | |
| "License"); you may not use this file except in compliance | |
| with 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. | |
| */ | |
| #pragma once | |
| #include <array> | |
| #include <memory> | |
| #include <variant> | |
| #include "ts/ts.h" | |
| #include "ts/remap.h" | |
| #include "cripts/Instance.hpp" | |
| #include "cripts/Headers.hpp" | |
| #include "cripts/Urls.hpp" | |
| #include "cripts/Connections.hpp" | |
| // These are pretty arbitrary for now | |
| constexpr int CONTEXT_DATA_SLOTS = 16; | |
| namespace cripts | |
| { | |
| class Context | |
| { | |
| using self_type = Context; | |
| using DataType = std::variant<integer, double, boolean, void *, cripts::string>; | |
| public: | |
| Context() = delete; | |
| Context(const self_type &) = delete; | |
| void operator=(const self_type &) = delete; | |
| // This will, and should, only be called via the ProxyAllocator as used in the factory. | |
| Context(TSHttpTxn txn_ptr, TSHttpSsn ssn_ptr, TSRemapRequestInfo *rri_ptr, cripts::Instance &inst) | |
| : rri(rri_ptr), p_instance(inst), _client(this), _server(this), _cache(this), _urls(this, _client.url) | |
| { | |
| state.txnp = txn_ptr; | |
| state.ssnp = ssn_ptr; | |
| state.context = this; | |
| } | |
| // Clear the cached header mloc's etc. | |
| void reset(); | |
| // This uses the ProxyAllocator to create a new Context object. | |
| static self_type *Factory(TSHttpTxn txn_ptr, TSHttpSsn ssn_ptr, TSRemapRequestInfo *rri_ptr, cripts::Instance &inst); | |
| void Release(); | |
| // These fields are preserving the parameters as setup in DoRemap() | |
| cripts::Transaction state; // This is the transaction state | |
| std::array<DataType, CONTEXT_DATA_SLOTS> data; // Context data | |
| TSCont contp = nullptr; // Remap or global continuation | |
| TSRemapRequestInfo *rri = nullptr; // This may be nullptr, if not a remap | |
| cripts::Instance &p_instance; // p_ == public_, since we can't use "instance" | |
| bool | |
| rriValid() const | |
| { | |
| return rri && rri->requestBufp && rri->requestHdrp && rri->requestUrl; | |
| } | |
| // These are private, but needs to be visible to our friend classes that | |
| // depends on the Context. | |
| friend class Client::Request; | |
| friend class Client::Response; | |
| friend class Client::Connection; | |
| friend class Client::URL; | |
| friend class Remap::From::URL; | |
| friend class Remap::To::URL; | |
| friend class Server::Request; | |
| friend class Server::Response; | |
| friend class Server::Connection; | |
| friend class Server::Response; | |
| friend class Cache::Response; | |
| friend class Cache::URL; | |
| friend class Pristine::URL; | |
| friend class Parent::URL; | |
| friend class Plugin::Remap; | |
| // These are "pre-allocated", but not initialized. They will be initialized | |
| // when used via a factory. | |
| struct _ClientBlock { | |
| cripts::Client::Response response; | |
| cripts::Client::Request request; | |
| cripts::Client::Connection connection; | |
| cripts::Client::URL url; | |
| _ClientBlock(Context *ctx) | |
| { | |
| response.set_state(&ctx->state); | |
| request.set_state(&ctx->state); | |
| connection.set_state(&ctx->state); | |
| } | |
| } _client; | |
| struct _ServerBlock { | |
| cripts::Server::Response response; | |
| cripts::Server::Request request; | |
| cripts::Server::Connection connection; | |
| _ServerBlock(Context *ctx) | |
| { | |
| response.set_state(&ctx->state); | |
| request.set_state(&ctx->state); | |
| connection.set_state(&ctx->state); | |
| } | |
| } _server; | |
| struct _CacheBlock { | |
| cripts::Cache::Response response; | |
| cripts::Cache::URL url; | |
| _CacheBlock(Context *ctx) | |
| { | |
| response.set_state(&ctx->state); | |
| url.set_context(ctx); | |
| } | |
| } _cache; | |
| struct _UrlBlock { | |
| cripts::Client::URL &request; | |
| std::unique_ptr<cripts::Pristine::URL> pristine; | |
| std::unique_ptr<cripts::Parent::URL> parent; | |
| struct { | |
| std::unique_ptr<cripts::Remap::From::URL> from; | |
| std::unique_ptr<cripts::Remap::To::URL> to; | |
| } remap; | |
| _UrlBlock(Context *ctx, cripts::Client::URL &alias) : request(alias) { request.set_context(ctx); } | |
| } _urls; | |
| }; // End class Context | |
| } // namespace cripts | |
| // This may be weird, but oh well for now. | |
| #define Get() _get(context) | |
| #define Set(_value, ...) _set(context, _value __VA_OPT__(, ) __VA_ARGS__) | |
| #define Update() _update(context) | |
| #define RunRemap() _runRemap(context) | |
| #define Activate() _activate(context->p_instance) | |
| #define CDebug(...) context->p_instance.debug(__VA_ARGS__) | |
| #define CDebugOn() context->p_instance.debugOn() | |
| #define DisableCallback(cb) context->state.disableCallback(cb) | |
| #define transaction context->state | |
| #define txn_data context->data | |
| #define instance context->p_instance |