| /** @file | |
| A brief file description | |
| @section license License | |
| 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. | |
| */ | |
| /*************************************************************************** | |
| * | |
| * FetchSM.h header file for Fetch Page | |
| * | |
| ****************************************************************************/ | |
| #pragma once | |
| #include "proxy/http/HttpSM.h" | |
| #include "proxy/http/HttpTunnel.h" | |
| class PluginVC; | |
| class FetchSM : public Continuation | |
| { | |
| public: | |
| FetchSM() {} | |
| /** Indicate whether FetchSM dependencies have been initialized by ATS. | |
| * @return True if FetchSM dependencies have been initialized, false otherwise. | |
| */ | |
| static bool is_initialized(); | |
| void | |
| init_comm() | |
| { | |
| cont_mutex.clear(); | |
| req_buffer = new_MIOBuffer(HTTP_HEADER_BUFFER_SIZE_INDEX); | |
| req_reader = req_buffer->alloc_reader(); | |
| resp_buffer = new_MIOBuffer(BUFFER_SIZE_INDEX_32K); | |
| resp_reader = resp_buffer->alloc_reader(); | |
| http_parser_init(&http_parser); | |
| client_response_hdr.create(HTTPType::RESPONSE); | |
| SET_HANDLER(&FetchSM::fetch_handler); | |
| } | |
| void | |
| init(Continuation *cont, TSFetchWakeUpOptions options, TSFetchEvent events, const char *headers, int length, sockaddr const *addr) | |
| { | |
| static DbgCtl dbg_ctl{"FetchSM"}; | |
| Dbg(dbg_ctl, "[%s] FetchSM initialized for request with headers\n--\n%.*s\n--", __FUNCTION__, length, headers); | |
| init_comm(); | |
| contp = cont; | |
| callback_events = events; | |
| callback_options = options; | |
| _addr.assign(addr); | |
| writeRequest(headers, length); | |
| mutex = new_ProxyMutex(); | |
| // | |
| // We had dropped response_buffer/response_reader to avoid unnecessary | |
| // memory copying. But for the original TSFetchURL() API, PluginVC may | |
| // stop adding data to resp_buffer when the pending data in resp_buffer | |
| // reach its water_mark. | |
| // | |
| // So we should set the water_mark of resp_buffer with a large value, | |
| // INT64_MAX would be reasonable. | |
| resp_buffer->water_mark = INT64_MAX; | |
| } | |
| void | |
| set_fetch_flags(int flags) | |
| { | |
| fetch_flags = flags; | |
| } | |
| int fetch_handler(int event, void *data); | |
| void process_fetch_read(int event); | |
| void process_fetch_write(int event); | |
| void httpConnect(); | |
| void cleanUp(); | |
| void get_info_from_buffer(IOBufferReader *reader); | |
| char *resp_get(int *length); | |
| TSMBuffer resp_hdr_bufp(); | |
| TSMLoc resp_hdr_mloc(); | |
| // | |
| // Extended APIs for FetchSM | |
| // | |
| // *flags* can be bitwise OR of several TSFetchFlags | |
| // | |
| void ext_init(Continuation *cont, const char *method, const char *url, const char *version, const sockaddr *client_addr, | |
| int flags); | |
| void ext_add_header(const char *name, int name_len, const char *value, int value_len); | |
| void ext_launch(); | |
| void ext_destroy(); | |
| ssize_t ext_read_data(char *buf, size_t len); | |
| void ext_write_data(const void *data, size_t len); | |
| void ext_set_user_data(void *data); | |
| void *ext_get_user_data(); | |
| bool | |
| get_internal_request() | |
| { | |
| return is_internal_request; | |
| } | |
| void | |
| set_internal_request(bool val) | |
| { | |
| is_internal_request = val; | |
| } | |
| private: | |
| int InvokePlugin(int event, void *data); | |
| void InvokePluginExt(int error_event = 0); | |
| void | |
| writeRequest(const char *headers, int length) | |
| { | |
| if (length == -1) | |
| req_buffer->write(headers, strlen(headers)); | |
| else | |
| req_buffer->write(headers, length); | |
| } | |
| int64_t | |
| getReqLen() const | |
| { | |
| return req_reader->read_avail(); | |
| } | |
| /// Check if the comma supporting MIME field @a name has @a value in it. | |
| bool check_for_field_value(const char *name, size_t name_len, char const *value, size_t value_len); | |
| bool has_body(); | |
| bool check_body_done(); | |
| bool check_chunked(); | |
| bool check_connection_close(); | |
| int dechunk_body(); | |
| int recursion = 0; | |
| PluginVC *http_vc = nullptr; | |
| VIO *read_vio = nullptr; | |
| VIO *write_vio = nullptr; | |
| MIOBuffer *req_buffer = nullptr; | |
| IOBufferReader *req_reader = nullptr; | |
| char *client_response = nullptr; | |
| int client_bytes = 0; | |
| MIOBuffer *resp_buffer = nullptr; // response to HttpConnect Call | |
| IOBufferReader *resp_reader = nullptr; | |
| Continuation *contp = nullptr; | |
| Ptr<ProxyMutex> cont_mutex; | |
| HTTPParser http_parser; | |
| HTTPHdr client_response_hdr; | |
| ChunkedHandler chunked_handler; | |
| TSFetchEvent callback_events{}; | |
| TSFetchWakeUpOptions callback_options = NO_CALLBACK; | |
| bool req_finished = false; | |
| bool header_done = false; | |
| bool is_method_head = false; | |
| bool is_internal_request = true; | |
| bool destroyed = false; | |
| IpEndpoint _addr; | |
| int resp_is_chunked = -1; | |
| int resp_received_close = -1; | |
| int fetch_flags = 0; | |
| void *user_data = nullptr; | |
| bool has_sent_header = false; | |
| int64_t req_content_length = 0; | |
| int64_t resp_content_length = -1; | |
| int64_t resp_received_body_len = 0; | |
| }; |