You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by zw...@apache.org on 2019/07/22 14:38:54 UTC
[trafficserver] 02/07: Removes the buffer_upload plugin. See #5395
This is an automated email from the ASF dual-hosted git repository.
zwoop pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
commit 2642638bf22be8db20712767665cf58e6fd0e50a
Author: Leif Hedstrom <zw...@apache.org>
AuthorDate: Fri Jul 19 13:38:26 2019 -0600
Removes the buffer_upload plugin. See #5395
---
doc/admin-guide/plugins/buffer_upload.en.rst | 82 --
doc/admin-guide/plugins/index.en.rst | 4 -
.../admin-guide/plugins/buffer_upload.en.po | 135 ---
.../ja/LC_MESSAGES/admin-guide/plugins/index.en.po | 4 -
plugins/Makefile.am | 1 -
plugins/experimental/buffer_upload/Makefile.inc | 20 -
plugins/experimental/buffer_upload/README | 77 --
.../experimental/buffer_upload/buffer_upload.cc | 1251 --------------------
8 files changed, 1574 deletions(-)
diff --git a/doc/admin-guide/plugins/buffer_upload.en.rst b/doc/admin-guide/plugins/buffer_upload.en.rst
deleted file mode 100644
index 6f22d80..0000000
--- a/doc/admin-guide/plugins/buffer_upload.en.rst
+++ /dev/null
@@ -1,82 +0,0 @@
-.. _admin-plugins-buffer-upload:
-
-Buffer Upload Plugin
-********************
-
-.. 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.
-
-The Buffer Upload plugin offers the following features
-
-Installation
-============
-
-Configuration can be explicitly specified as a parameter in ``plugin.config`` ::
-
- buffer_upload.so /FOOBAR/upload.conf
-
-Memory buffering (buffer the entire POST data in IOBuffer before connecting to OS)
-==================================================================================
-
-Memory buffer size is configured with "mem_buffer_size" in config file. Default and minimum value is 32K. You can
-increase it in the config file. If the size of a request is larger than the "mem_buffer_size" value specified in the
-config file, then the upload proxy feature will be disabled for this particular request
-
-Disk buffering (buffer the entire POST data on disk before connecting to OS)
-============================================================================
-
-1. Disk async IO is used. AIO api call only involves certain amount of threads. The number of threads is configurable in
-plugin's config file (default is 4)
-
-2. Directories and files are generated on disk . Base directory is /FOOBAR/var/buffer_upload_tmp/ (configurable in
-config file). Number of subdirectories is 64 (configurable in config file). Filename are randomly generated. Files will
-be removed when the entire data have been sent out to OS . At startup time, dangling files are removed (left on disk due
-to transaction interruption or traffic server crash)
-
-3. Default chunk size when reading from disk is 16K, configurable in config file
-
-Trigger POST buffering on certain URLs
-======================================
-
-1. Certain URLs will be provided in a plain text file (one URL each line)
-2. Specify filename in config file by "url_list_file"
-3. max length of each URL is 4096 (configurable in config file)
-4. use exact match, don't support regex for now
-
-Other Features
-==============
-
-1. Default buffering mode is disk aio buffering mode. To turn off disk buffering, add a "use_disk_buffer 0" line in
-config file
-
-2. All request headers including cookies plus the entire POST data will be buffered (either in memory or on disk)
-
-Configuration File
-==================
-
-sample config file ::
-
- use_disk_buffer 1
- convert_url 1
- chunk_size 1024
- url_list_file /tmp/url_list.conf
- max_url_length 10000
- base_dir /tmp/test1
- subdir_num 100
- thread_num 10
- mem_buffer_size 40000
-
diff --git a/doc/admin-guide/plugins/index.en.rst b/doc/admin-guide/plugins/index.en.rst
index ff078b4..fecae96 100644
--- a/doc/admin-guide/plugins/index.en.rst
+++ b/doc/admin-guide/plugins/index.en.rst
@@ -144,7 +144,6 @@ directory of the |TS| source tree. Experimental plugins can be compiled by passi
:hidden:
Access Control <access_control.en>
- Buffer Upload <buffer_upload.en>
Certifier <certifier.en>
Cert Reporting Tool <cert_reporting_tool.en>
Collapsed-Forwarding <collapsed_forwarding.en>
@@ -172,9 +171,6 @@ directory of the |TS| source tree. Experimental plugins can be compiled by passi
:doc:`Access Control <access_control.en>`
Access control plugin that handles various access control use-cases.
-:doc:`Buffer Upload <buffer_upload.en>`
- Buffers POST data before connecting to the Origin server.
-
:doc:`Certifier <certifier.en>`
Manages and/or generates certificates for incoming HTTPS requests.
diff --git a/doc/locale/ja/LC_MESSAGES/admin-guide/plugins/buffer_upload.en.po b/doc/locale/ja/LC_MESSAGES/admin-guide/plugins/buffer_upload.en.po
deleted file mode 100644
index b8074d7..0000000
--- a/doc/locale/ja/LC_MESSAGES/admin-guide/plugins/buffer_upload.en.po
+++ /dev/null
@@ -1,135 +0,0 @@
-# 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.
-#
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: Apache Traffic Server 6.2\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2016-01-02 21:32+0000\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME <EM...@ADDRESS>\n"
-"Language-Team: LANGUAGE <LL...@li.org>\n"
-"Language: ja_JP\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=utf-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.1.1\n"
-
-#: ../../admin-guide/plugins/buffer_upload.en.rst:42
-msgid ""
-"1. Disk async IO is used. AIO api call only involves certain amount of "
-"threads. The number of threads is configurable in plugin's config file "
-"(default is 4)"
-msgstr ""
-
-#: ../../admin-guide/plugins/buffer_upload.en.rst:4
-msgid "Buffer Upload Plugin"
-msgstr ""
-
-#: ../../admin-guide/plugins/buffer_upload.en.rst:28
-msgid ""
-"Configuration can be explicitly specified as a parameter in ``plugin."
-"config`` ::"
-msgstr ""
-
-#: ../../admin-guide/plugins/buffer_upload.en.rst:26
-msgid "Installation"
-msgstr "インストール"
-
-#: ../../admin-guide/plugins/buffer_upload.en.rst:23
-msgid "The Buffer Upload plugin offers the following features"
-msgstr ""
-
-#: ../../admin-guide/plugins/buffer_upload.en.rst:63
-msgid ""
-"1. Default buffering mode is disk aio buffering mode. To turn off disk "
-"buffering, add a \"use_disk_buffer 0\" line in config file"
-msgstr ""
-
-#: ../../admin-guide/plugins/buffer_upload.en.rst:45
-msgid ""
-"2. Directories and files are generated on disk . Base directory is /FOOBAR/"
-"var/buffer_upload_tmp/ (configurable in config file). Number of "
-"subdirectories is 64 (configurable in config file). Filename are randomly "
-"generated. Files will be removed when the entire data have been sent out to "
-"OS . At startup time, dangling files are removed (left on disk due to "
-"transaction interruption or traffic server crash)"
-msgstr ""
-
-#: ../../admin-guide/plugins/buffer_upload.en.rst:55
-msgid "Certain URLs will be provided in a plain text file (one URL each line)"
-msgstr ""
-
-#: ../../admin-guide/plugins/buffer_upload.en.rst:50
-msgid ""
-"Default chunk size when reading from disk is 16K, configurable in config "
-"file"
-msgstr ""
-
-#: ../../admin-guide/plugins/buffer_upload.en.rst:35
-msgid ""
-"Memory buffer size is configured with \"mem_buffer_size\" in config file. "
-"Default and minimum value is 32K. You can increase it in the config file. "
-"If the size of a request is larger than the \"mem_buffer_size\" value "
-"specifiied in the config file, then the upload proxy feature will be "
-"disabled for this particular request"
-msgstr ""
-
-#: ../../admin-guide/plugins/buffer_upload.en.rst:33
-msgid ""
-"Memory buffering (buffer the entire POST data in IOBuffer before connecting "
-"to OS)"
-msgstr ""
-
-#: ../../admin-guide/plugins/buffer_upload.en.rst:66
-msgid ""
-"All request headers inlcuding cookies plus the entire POST data will be "
-"buffered (either in memory or on disk)"
-msgstr ""
-
-#: ../../admin-guide/plugins/buffer_upload.en.rst:40
-msgid ""
-"Disk buffering (buffer the entire POST data on disk before connecting to OS)"
-msgstr ""
-
-#: ../../admin-guide/plugins/buffer_upload.en.rst:69
-msgid "Configuration File"
-msgstr ""
-
-#: ../../admin-guide/plugins/buffer_upload.en.rst:61
-msgid "Other Features"
-msgstr ""
-
-#: ../../admin-guide/plugins/buffer_upload.en.rst:56
-msgid "Specify filename in config file by \"url_list_file\""
-msgstr ""
-
-#: ../../admin-guide/plugins/buffer_upload.en.rst:53
-msgid "Trigger POST buffering on certain URLs"
-msgstr ""
-
-#: ../../admin-guide/plugins/buffer_upload.en.rst:57
-msgid "max length of each URL is 4096 (configurable in config file)"
-msgstr ""
-
-#: ../../admin-guide/plugins/buffer_upload.en.rst:71
-msgid "sample config file ::"
-msgstr ""
-
-#: ../../admin-guide/plugins/buffer_upload.en.rst:58
-msgid "use exact match, don't support regex for now"
-msgstr ""
diff --git a/doc/locale/ja/LC_MESSAGES/admin-guide/plugins/index.en.po b/doc/locale/ja/LC_MESSAGES/admin-guide/plugins/index.en.po
index 2eb3788..7f2da51 100644
--- a/doc/locale/ja/LC_MESSAGES/admin-guide/plugins/index.en.po
+++ b/doc/locale/ja/LC_MESSAGES/admin-guide/plugins/index.en.po
@@ -183,10 +183,6 @@ msgid "Balances requests across multiple origin servers."
msgstr ""
#: ../../../admin-guide/plugins/index.en.rst:138
-msgid ":doc:`Buffer Upload <buffer_upload.en>`"
-msgstr ""
-
-#: ../../../admin-guide/plugins/index.en.rst:138
msgid "Buffers POST data before connecting to the Origin server."
msgstr ""
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index d868692..89cbdb2 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -58,7 +58,6 @@ if BUILD_EXPERIMENTAL_PLUGINS
include experimental/access_control/Makefile.inc
include experimental/acme/Makefile.inc
-include experimental/buffer_upload/Makefile.inc
include experimental/cert_reporting_tool/Makefile.inc
include experimental/collapsed_forwarding/Makefile.inc
include experimental/cookie_remap/Makefile.inc
diff --git a/plugins/experimental/buffer_upload/Makefile.inc b/plugins/experimental/buffer_upload/Makefile.inc
deleted file mode 100644
index ee820e2..0000000
--- a/plugins/experimental/buffer_upload/Makefile.inc
+++ /dev/null
@@ -1,20 +0,0 @@
-# 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.
-
-pkglib_LTLIBRARIES += experimental/buffer_upload/buffer_upload.la
-
-experimental_buffer_upload_buffer_upload_la_SOURCES = \
- experimental/buffer_upload/buffer_upload.cc
diff --git a/plugins/experimental/buffer_upload/README b/plugins/experimental/buffer_upload/README
deleted file mode 100644
index 24d4b41..0000000
--- a/plugins/experimental/buffer_upload/README
+++ /dev/null
@@ -1,77 +0,0 @@
-Version 0.3 (11/02/11)
- - fixed some pointer comparisons in an attempt to prevent a crash where INKHandleStringRelease was called on a bad char*
-
-Version 0.2 (10/31/11)
- - fixed lots of memory leaks
-
-Version 0.1 (04/20/10)
- - initial version
-
-Upload proxy specs for phase I:
-
-1. Memory buffering (buffer the entire POST data in IOBuffer before connecting to OS)
- 1.1. Memory buffer size is configured with "mem_buffer_size" in config file. Default and minimum value is 32K
- You can increase it in the config file. If a request's size is larger than "mem_buffer_size" specified
- in config file, then the upload proxy feature will be disabled for this particular request
-
-2. Disk buffering (buffer the entire POST data on disk before connecting to OS)
- 2.1. Use disk async IO. This involved some changes in ATS core
- . new APIs wrapping around ink_aio_read() and ink_aio_write()
- . change to distinguish between api call's AIO and cache's AIO
- . guarantee api call's AIO only involves certain amount of threads
- . the number of threads is configurable in plugin's config file (default is 4)
-
- 2.2. Directories and files generated on disk
- . base directory: FOOBAR/var/buffer_upload_tmp/ (configurable in config file)
- . number of subdirectories: 64 (configurable in config file)
- . filename are randomly generated
- . files will be removed when the entire data have been sent out to OS
- . remove dangling files (left on disk due to transaction interruption or traffic server crash) at startup time
-
- 2.3. Default chunk size when reading from disk: 16K, configurable in config file
-
-3. Default buffering mode: disk aio buffering mode
- 3.1. to turn off disk buffering, add a "use_disk_buffer 0" line in config file
-
-4. Trigger POST buffering on certain URLs
- 4.1. certain URLs will be provided in a plain text file (one URL each line)
- 4.2. specify filename in config file by "url_list_file"
- 4.3. max length of each URL: 4096 (configurable in config file)
- 4.4. use exact match, don't support regex for now
-
-5. URL conversion for Mail's specific URL format
- 5.1. for now check if the "host" part in the URL is same as the proxy server name, then will do this conversion
- 5.2. To turn on URL conversion feature, set "convert_url 1" in config file
-
-6. All request headers including cookies plus the entire POST data will be buffered (either in memory or on disk)
-
-7. Config file can be explicitly specified as a parameter in command line (in plugin.config file)
-
-
-a sample config file:
-
-use_disk_buffer 1
-convert_url 1
-chunk_size 1024
-url_list_file /tmp/url_list.conf
-max_url_length 10000
-base_dir /tmp/test1
-subdir_num 100
-thread_num 10
-mem_buffer_size 40000
-
-
-default config file: FOOBAR/etc/upload.conf
-
-default config values:
-use_disk_buffer 1
-convert_url 0
-chunk_size 16384
-url_list_file none
-max_url_length 4096
-base_dir FOOBAR/var/buffer_upload_tmp
-subdir_num 64
-thread_num 4
-mem_buffer_size 32768
-
-
diff --git a/plugins/experimental/buffer_upload/buffer_upload.cc b/plugins/experimental/buffer_upload/buffer_upload.cc
deleted file mode 100644
index 92e64fd..0000000
--- a/plugins/experimental/buffer_upload/buffer_upload.cc
+++ /dev/null
@@ -1,1251 +0,0 @@
-/** @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.
- */
-
-/* buffer_upload.c - plugin for buffering POST data on proxy server
- * before connecting to origin server. It supports two types of buffering:
- * memory-only buffering and disk buffering
- *
- */
-
-#include <cstdio>
-#include <cstring>
-#include <cctype>
-#include <climits>
-#include <ts/ts.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <cerrno>
-#include <dirent.h>
-#include <unistd.h>
-#include <cstdlib>
-#include <cinttypes>
-
-/* #define DEBUG 1 */
-#define DEBUG_TAG "buffer_upload-dbg"
-
-/**************************************************
- Log macros for error code return verification
-**************************************************/
-#define PLUGIN_NAME "buffer_upload"
-//#define LOG_SET_FUNCTION_NAME(NAME) const char * FUNCTION_NAME = NAME
-#define LOG_ERROR(API_NAME) \
- { \
- TSError("[%s] %s %s %s File %s, line number %d", PLUGIN_NAME, API_NAME, "APIFAIL", __FUNCTION__, __FILE__, __LINE__); \
- }
-#define LOG_ERROR_AND_RETURN(API_NAME) \
- { \
- LOG_ERROR(API_NAME); \
- return TS_ERROR; \
- }
-
-#define VALID_PTR(X) (NULL != X)
-#define NOT_VALID_PTR(X) (NULL == X)
-
-struct upload_config_t {
- bool use_disk_buffer;
- bool convert_url;
- int64_t mem_buffer_size;
- int64_t chunk_size;
- char *url_list_file;
- int64_t max_url_length;
- int url_num;
- char **urls;
- char *base_dir;
- int subdir_num;
- int thread_num;
-};
-
-using upload_config = struct upload_config_t;
-
-enum config_type {
- TYPE_INT,
- TYPE_UINT,
- TYPE_LONG,
- TYPE_ULONG,
- TYPE_STRING,
- TYPE_BOOL,
-};
-
-struct config_val_ul {
- const char *str;
- enum config_type type;
- void *val;
-};
-
-static int upload_vc_count;
-
-static upload_config *uconfig = nullptr;
-
-struct pvc_state_t {
- TSVConn p_vc;
- TSVIO p_read_vio;
- TSVIO p_write_vio;
-
- TSVConn net_vc;
- TSVIO n_read_vio;
- TSVIO n_write_vio;
-
- TSIOBuffer req_buffer;
- TSIOBufferReader req_reader;
-
- TSIOBuffer resp_buffer;
- TSIOBufferReader resp_reader;
-
- TSIOBufferReader req_hdr_reader;
- TSIOBuffer req_hdr_buffer;
-
- TSMutex disk_io_mutex;
-
- int fd;
-
- int64_t req_finished;
- int64_t resp_finished;
- int64_t nbytes_to_consume;
- int64_t req_size;
- int64_t size_written;
- int64_t size_read;
-
- int64_t write_offset;
- int64_t read_offset;
-
- char *chunk_buffer; // buffer to store the data read from disk
- int is_reading_from_disk;
-
- TSHttpTxn http_txnp;
-};
-
-using pvc_state = struct pvc_state_t;
-
-// print IOBuffer for test purpose
-/*
-static void
-print_buffer(TSIOBufferReader reader)
-{
- TSIOBufferBlock block;
- int64_t size;
- const char *ptr;
-
- block = TSIOBufferReaderStart(reader);
- while (block != NULL) {
- ptr = TSIOBufferBlockReadStart(block, reader, &size);
- TSDebug(DEBUG_TAG, "buffer size: %d", size);
- TSDebug(DEBUG_TAG, "buffer: %.*s", size, ptr);
- block = TSIOBufferBlockNext(block);
- }
-}
-*/
-
-static int
-write_buffer_to_disk(TSIOBufferReader reader, pvc_state *my_state, TSCont contp)
-{
- TSIOBufferBlock block;
- int64_t size;
- const char *ptr;
- char *pBuf;
-
- // LOG_SET_FUNCTION_NAME("write_buffer_to_disk");
- block = TSIOBufferReaderStart(reader);
- while (block != nullptr) {
- ptr = TSIOBufferBlockReadStart(block, reader, &size);
- pBuf = (char *)TSmalloc(sizeof(char) * size);
- if (pBuf == nullptr) {
- LOG_ERROR_AND_RETURN("TSAIOWrite");
- }
- memcpy(pBuf, ptr, size);
- if (TSAIOWrite(my_state->fd, my_state->write_offset, pBuf, size, contp) == TS_ERROR) {
- LOG_ERROR_AND_RETURN("TSAIOWrite");
- }
- my_state->write_offset += size;
- block = TSIOBufferBlockNext(block);
- }
- return TS_SUCCESS;
-}
-
-static int
-call_httpconnect(TSCont contp, pvc_state *my_state)
-{
- // LOG_SET_FUNCTION_NAME("call_httpconnect");
-
- // unsigned int client_ip = TSHttpTxnClientIPGet(my_state->http_txnp);
- sockaddr const *client_ip = TSHttpTxnClientAddrGet(my_state->http_txnp);
-
- TSDebug(DEBUG_TAG, "call TSHttpConnect()");
- if ((my_state->net_vc = TSHttpConnect(client_ip)) == nullptr) {
- LOG_ERROR_AND_RETURN("TSHttpConnect");
- }
- my_state->p_write_vio = TSVConnWrite(my_state->p_vc, contp, my_state->resp_reader, INT_MAX);
- if (my_state->p_write_vio == nullptr) {
- LOG_ERROR_AND_RETURN("TSVConnWrite");
- }
- my_state->n_read_vio = TSVConnRead(my_state->net_vc, contp, my_state->resp_buffer, INT_MAX);
- if (my_state->n_read_vio == nullptr) {
- LOG_ERROR_AND_RETURN("TSVConnRead");
- }
- my_state->n_write_vio = TSVConnWrite(my_state->net_vc, contp, my_state->req_reader, INT_MAX);
- if (my_state->n_write_vio == nullptr) {
- LOG_ERROR_AND_RETURN("TSVConnWrite");
- }
- return TS_SUCCESS;
-}
-
-static void
-pvc_cleanup(TSCont contp, pvc_state *my_state)
-{
- if (my_state->req_buffer) {
- TSIOBufferReaderFree(my_state->req_reader);
- my_state->req_reader = nullptr;
- TSIOBufferDestroy(my_state->req_buffer);
- my_state->req_buffer = nullptr;
- }
-
- if (my_state->resp_buffer) {
- TSIOBufferReaderFree(my_state->resp_reader);
- my_state->resp_reader = nullptr;
- TSIOBufferDestroy(my_state->resp_buffer);
- my_state->resp_buffer = nullptr;
- }
-
- if (my_state->req_hdr_buffer) {
- TSIOBufferReaderFree(my_state->req_hdr_reader);
- my_state->req_hdr_reader = nullptr;
- TSIOBufferDestroy(my_state->req_hdr_buffer);
- my_state->req_hdr_buffer = nullptr;
- }
-
- if (uconfig->use_disk_buffer && my_state->fd != -1) {
- close(my_state->fd);
- my_state->fd = -1;
- }
-
- if (my_state->chunk_buffer) {
- TSfree(my_state->chunk_buffer);
- my_state->chunk_buffer = nullptr;
- }
-
- TSfree(my_state);
- TSContDestroy(contp);
-
- /* Decrement upload_vc_count */
- TSStatIntDecrement(upload_vc_count, 1);
-}
-
-static void
-pvc_check_done(TSCont contp, pvc_state *my_state)
-{
- if (my_state->req_finished && my_state->resp_finished) {
- TSVConnClose(my_state->p_vc);
- TSVConnClose(my_state->net_vc);
- pvc_cleanup(contp, my_state);
- }
-}
-
-static void
-pvc_process_accept(TSCont contp, int event, void *edata, pvc_state *my_state)
-{
- TSDebug(DEBUG_TAG, "plugin called: pvc_process_accept with event %d", event);
-
- if (event == TS_EVENT_NET_ACCEPT) {
- my_state->p_vc = (TSVConn)edata;
-
- my_state->req_buffer = TSIOBufferCreate();
- my_state->req_reader = TSIOBufferReaderAlloc(my_state->req_buffer);
- // set the maximum memory buffer size for request (both request header and post data), default is 32K
- // only apply to memory buffer mode
- if (uconfig->use_disk_buffer == 0) {
- TSIOBufferWaterMarkSet(my_state->req_buffer, uconfig->mem_buffer_size);
- }
- my_state->resp_buffer = TSIOBufferCreate();
- my_state->resp_reader = TSIOBufferReaderAlloc(my_state->resp_buffer);
-
- if ((my_state->req_reader == nullptr) || (my_state->resp_reader == nullptr)) {
- LOG_ERROR("TSIOBufferReaderAlloc");
- TSVConnClose(my_state->p_vc);
- pvc_cleanup(contp, my_state);
- } else {
- my_state->p_read_vio = TSVConnRead(my_state->p_vc, contp, my_state->req_buffer, INT_MAX);
- if (my_state->p_read_vio == nullptr) {
- LOG_ERROR("TSVConnRead");
- }
- }
- } else if (event == TS_EVENT_NET_ACCEPT_FAILED) {
- pvc_cleanup(contp, my_state);
- } else {
- TSReleaseAssert(!"Unexpected Event");
- }
-}
-
-static void
-pvc_process_p_read(TSCont contp, TSEvent event, pvc_state *my_state)
-{
- int size, consume_size;
-
- // TSDebug(DEBUG_TAG, "plugin called: pvc_process_p_read with event %d", event);
-
- switch (event) {
- case TS_EVENT_VCONN_READ_READY:
- // Here we need to replace the server request header with client request header
- // print_buffer(my_state->req_reader);
- if (my_state->nbytes_to_consume == -1) { // -1 is the initial value
- my_state->nbytes_to_consume = TSHttpTxnServerReqHdrBytesGet(my_state->http_txnp);
- }
- size = TSIOBufferReaderAvail(my_state->req_reader);
- if (my_state->nbytes_to_consume > 0) {
- consume_size = (my_state->nbytes_to_consume < size) ? my_state->nbytes_to_consume : size;
- TSIOBufferReaderConsume(my_state->req_reader, consume_size);
- my_state->nbytes_to_consume -= consume_size;
- size -= consume_size;
- }
- if (my_state->nbytes_to_consume == 0) { // the entire server request header has been consumed
- if (uconfig->use_disk_buffer) {
- TSMutexLock(my_state->disk_io_mutex);
- if (write_buffer_to_disk(my_state->req_hdr_reader, my_state, contp) == TS_ERROR) {
- LOG_ERROR("write_buffer_to_disk");
- uconfig->use_disk_buffer = false;
- close(my_state->fd);
- my_state->fd = -1;
- }
- TSMutexUnlock(my_state->disk_io_mutex);
- }
- if (size > 0) {
- if (uconfig->use_disk_buffer) {
- TSMutexLock(my_state->disk_io_mutex);
- if (write_buffer_to_disk(my_state->req_reader, my_state, contp) == TS_ERROR) {
- TSDebug(DEBUG_TAG, "Error in writing to disk");
- }
- TSMutexUnlock(my_state->disk_io_mutex);
- } else {
- // never get chance to test this line, didn't get a test case to fall into this situation
- TSIOBufferCopy(my_state->req_hdr_buffer, my_state->req_reader, size, 0);
- }
- TSIOBufferReaderConsume(my_state->req_reader, size);
- }
- if (!uconfig->use_disk_buffer) {
- size = TSIOBufferReaderAvail(my_state->req_hdr_reader);
- TSIOBufferCopy(my_state->req_buffer, my_state->req_hdr_reader, size, 0);
- }
- my_state->nbytes_to_consume = -2; // -2 indicates the header replacement is done
- }
- if (my_state->nbytes_to_consume == -2) {
- size = TSIOBufferReaderAvail(my_state->req_reader);
- if (uconfig->use_disk_buffer) {
- if (size > 0) {
- TSMutexLock(my_state->disk_io_mutex);
- if (write_buffer_to_disk(my_state->req_reader, my_state, contp) == TS_ERROR) {
- TSDebug(DEBUG_TAG, "Error in writing to disk");
- }
- TSIOBufferReaderConsume(my_state->req_reader, size);
- TSMutexUnlock(my_state->disk_io_mutex);
- }
- } else {
- // if the entire post data had been read in memory, then connect to origin server.
- if (size >= my_state->req_size) {
- if (call_httpconnect(contp, my_state) == TS_ERROR) {
- LOG_ERROR("call_httpconnect");
- }
- }
- }
- }
-
- break;
- case TS_EVENT_VCONN_READ_COMPLETE:
- case TS_EVENT_VCONN_EOS:
- case TS_EVENT_ERROR: {
- /* We're finished reading from the plugin vc */
- int ndone;
-
- ndone = TSVIONDoneGet(my_state->p_read_vio);
- if (ndone == TS_ERROR) {
- LOG_ERROR("TSVIODoneGet");
- }
-
- my_state->p_read_vio = nullptr;
-
- TSVConnShutdown(my_state->p_vc, 1, 0);
- // if client aborted the uploading in middle, need to cleanup the file from disk
- if (event == TS_EVENT_VCONN_EOS && uconfig->use_disk_buffer && my_state->fd != -1) {
- close(my_state->fd);
- my_state->fd = -1;
- }
-
- break;
- }
- default:
- TSReleaseAssert(!"Unexpected Event");
- break;
- }
-}
-
-static void
-pvc_process_n_write(TSCont contp, TSEvent event, pvc_state *my_state)
-{
- int size;
-
- // TSDebug(DEBUG_TAG, "plugin called: pvc_process_n_write with event %d", event);
-
- switch (event) {
- case TS_EVENT_VCONN_WRITE_READY:
- // print_buffer(my_state->req_reader);
- if (uconfig->use_disk_buffer) {
- TSMutexLock(my_state->disk_io_mutex);
- size = (my_state->req_size - my_state->read_offset) > uconfig->chunk_size ? uconfig->chunk_size :
- (my_state->req_size - my_state->read_offset);
- if (size > 0 && !my_state->is_reading_from_disk) {
- my_state->is_reading_from_disk = 1;
- TSAIORead(my_state->fd, my_state->read_offset, my_state->chunk_buffer, size, contp);
- my_state->read_offset += size;
- }
- TSMutexUnlock(my_state->disk_io_mutex);
- }
- break;
- case TS_EVENT_ERROR:
- if (my_state->p_read_vio) {
- TSVConnShutdown(my_state->p_vc, 1, 0);
- my_state->p_read_vio = nullptr;
- }
- /* FALL THROUGH */
- case TS_EVENT_VCONN_WRITE_COMPLETE:
- /* We should have already shutdown read pvc side */
- TSAssert(my_state->p_read_vio == nullptr);
- TSVConnShutdown(my_state->net_vc, 0, 1);
- my_state->req_finished = 1;
-
- if (uconfig->use_disk_buffer && my_state->fd != -1) {
- close(my_state->fd);
- my_state->fd = -1;
- }
- pvc_check_done(contp, my_state);
- break;
-
- default:
- TSReleaseAssert(!"Unexpected Event");
- break;
- }
-}
-
-static void
-pvc_process_n_read(TSCont contp, TSEvent event, pvc_state *my_state)
-{
- // TSDebug(DEBUG_TAG, "plugin called: pvc_process_n_read with event %d", event);
-
- switch (event) {
- case TS_EVENT_VCONN_READ_READY:
- // print_buffer(my_state->resp_reader);
- TSVIOReenable(my_state->p_write_vio);
- break;
- case TS_EVENT_VCONN_READ_COMPLETE:
- case TS_EVENT_VCONN_EOS:
- case TS_EVENT_ERROR: {
- /* We're finished reading from the plugin vc */
- int ndone;
- int todo;
-
- ndone = TSVIONDoneGet(my_state->n_read_vio);
- if (ndone == TS_ERROR) {
- LOG_ERROR("TSVIODoneGet");
- }
-
- my_state->n_read_vio = nullptr;
- TSVIONBytesSet(my_state->p_write_vio, ndone);
- TSVConnShutdown(my_state->net_vc, 1, 0);
-
- todo = TSVIONTodoGet(my_state->p_write_vio);
- if (todo == TS_ERROR) {
- LOG_ERROR("TSVIOTodoGet");
- /* Error so set it to 0 to cleanup */
- todo = 0;
- }
-
- if (todo == 0) {
- my_state->resp_finished = 1;
- TSVConnShutdown(my_state->p_vc, 0, 1);
- pvc_check_done(contp, my_state);
- } else {
- TSVIOReenable(my_state->p_write_vio);
- }
-
- break;
- }
- default:
- TSReleaseAssert(!"Unexpected Event");
- break;
- }
-}
-
-static void
-pvc_process_p_write(TSCont contp, TSEvent event, pvc_state *my_state)
-{
- // TSDebug(DEBUG_TAG, "plugin called: pvc_process_p_write with event %d", event);
-
- switch (event) {
- case TS_EVENT_VCONN_WRITE_READY:
- if (my_state->n_read_vio) {
- TSVIOReenable(my_state->n_read_vio);
- }
- break;
- case TS_EVENT_ERROR:
- if (my_state->n_read_vio) {
- TSVConnShutdown(my_state->net_vc, 1, 0);
- my_state->n_read_vio = nullptr;
- }
- /* FALL THROUGH */
- case TS_EVENT_VCONN_WRITE_COMPLETE:
- /* We should have already shutdown read net side */
- TSAssert(my_state->n_read_vio == nullptr);
- TSVConnShutdown(my_state->p_vc, 0, 1);
- my_state->resp_finished = 1;
- pvc_check_done(contp, my_state);
- break;
- default:
- TSReleaseAssert(!"Unexpected Event");
- break;
- }
-}
-
-static int
-pvc_plugin(TSCont contp, TSEvent event, void *edata)
-{
- pvc_state *my_state = static_cast<pvc_state *>(TSContDataGet(contp));
- TSAIOCallback callback = static_cast<TSAIOCallback>(edata);
-
- if (my_state == nullptr) {
- TSReleaseAssert(!"Unexpected: my_state is NULL");
- return 0;
- }
-
- if (event == TS_EVENT_NET_ACCEPT || event == TS_EVENT_NET_ACCEPT_FAILED) {
- pvc_process_accept(contp, event, edata, my_state);
- } else if (edata == my_state->p_read_vio) {
- pvc_process_p_read(contp, event, my_state);
- } else if (edata == my_state->p_write_vio) {
- pvc_process_p_write(contp, event, my_state);
- } else if (edata == my_state->n_read_vio) {
- pvc_process_n_read(contp, event, my_state);
- } else if (edata == my_state->n_write_vio) {
- pvc_process_n_write(contp, event, my_state);
- } else if (event == TS_EVENT_AIO_DONE && uconfig->use_disk_buffer) {
- TSMutexLock(my_state->disk_io_mutex);
- int size = TSAIONBytesGet(callback);
- char *buf = TSAIOBufGet(callback);
- if (buf != my_state->chunk_buffer) {
- // this TS_EVENT_AIO_DONE event is from TSAIOWrite()
- TSDebug(DEBUG_TAG, "aio write size: %d", size);
- my_state->size_written += size;
- if (buf != nullptr) {
- TSfree(buf);
- }
- if (my_state->size_written >= my_state->req_size) {
- // the entire post data had been written to disk already, make the connection now
- if (call_httpconnect(contp, my_state) == TS_ERROR) {
- TSDebug(DEBUG_TAG, "call_httpconnect");
- }
- }
- } else {
- // this TS_EVENT_AIO_DONE event is from TSAIORead()
- TSDebug(DEBUG_TAG, "aio read size: %d", size);
- TSIOBufferWrite(my_state->req_buffer, my_state->chunk_buffer, size);
- my_state->size_read += size;
- if (my_state->size_read >= my_state->req_size && my_state->fd != -1) {
- close(my_state->fd);
- my_state->fd = -1;
- }
- my_state->is_reading_from_disk = 0;
- TSVIOReenable(my_state->n_write_vio);
- }
- TSMutexUnlock(my_state->disk_io_mutex);
-
- } else {
- TSDebug(DEBUG_TAG, "event: %d", event);
- TSReleaseAssert(!"Unexpected Event");
- }
-
- return 0;
-}
-
-/*
- * Convert specific URL format
- */
-static void
-convert_url_func(TSMBuffer req_bufp, TSMLoc req_loc)
-{
- TSMLoc url_loc;
- TSMLoc field_loc;
- const char *str;
- int len, port;
-
- if (TSHttpHdrUrlGet(req_bufp, req_loc, &url_loc) == TS_ERROR) {
- return;
- }
-
- const char *hostname = getenv("HOSTNAME");
- if (hostname == nullptr) {
- return;
- }
-
- // in reverse proxy mode, TSUrlHostGet returns NULL here
- str = TSUrlHostGet(req_bufp, url_loc, &len);
-
- port = TSUrlPortGet(req_bufp, url_loc);
-
- // for now we assume the <upload proxy service domain> in the format is the hostname
- // but this needs to be verified later
- if ((NOT_VALID_PTR(str) || !strncmp(str, hostname, len)) && strlen(hostname) == (size_t)len) {
- const char *slash;
- const char *colon;
- // if (VALID_PTR(str))
- // TSHandleStringRelease(req_bufp, url_loc, str);
- str = TSUrlPathGet(req_bufp, url_loc, &len);
- slash = strstr(str, "/");
- if (slash == nullptr) {
- // if (VALID_PTR(str))
- // TSHandleStringRelease(req_bufp, url_loc, str);
- TSHandleMLocRelease(req_bufp, req_loc, url_loc);
- return;
- }
- char pathTmp[len + 1];
- memcpy(pathTmp, str, len);
- pathTmp[len] = '\0';
- TSDebug(DEBUG_TAG, "convert_url_func working on path: %s", pathTmp);
- colon = strstr(str, ":");
- if (colon != nullptr && colon < slash) {
- char *port_str = (char *)TSmalloc(sizeof(char) * (slash - colon));
- strncpy(port_str, colon + 1, slash - colon - 1);
- port_str[slash - colon - 1] = '\0';
- TSUrlPortSet(req_bufp, url_loc, atoi(port_str));
- TSfree(port_str);
- } else {
- int length = 0;
- const char *scheme = TSUrlSchemeGet(req_bufp, url_loc, &length);
-
- if ((length == TS_URL_LEN_HTTP && strncmp(TS_URL_SCHEME_HTTP, scheme, length) == 0 && port != 80) ||
- (length == TS_URL_LEN_HTTPS && strncmp(TS_URL_SCHEME_HTTPS, scheme, length) == 0 && port != 443)) {
- TSUrlPortSet(req_bufp, url_loc, port);
- }
- colon = slash;
- }
-
- TSUrlHostSet(req_bufp, url_loc, str, colon - str);
- TSUrlPathSet(req_bufp, url_loc, slash + 1, len - (slash - str) - 1);
- if ((field_loc = TSMimeHdrFieldFind(req_bufp, req_loc, TS_MIME_FIELD_HOST, TS_MIME_LEN_HOST)) != TS_NULL_MLOC &&
- field_loc != nullptr) {
- TSMimeHdrFieldValueStringSet(req_bufp, req_loc, field_loc, 0, str, slash - str);
- TSHandleMLocRelease(req_bufp, req_loc, field_loc);
- }
- } else {
- // if (VALID_PTR(str))
- // TSHandleStringRelease(req_bufp, url_loc, str);
- }
-
- TSHandleMLocRelease(req_bufp, req_loc, url_loc);
-}
-
-static int
-attach_pvc_plugin(TSCont /* contp ATS_UNUSED */, TSEvent event, void *edata)
-{
- TSHttpTxn txnp = (TSHttpTxn)edata;
- TSMutex mutex;
- TSCont new_cont;
- pvc_state *my_state;
- TSMBuffer req_bufp;
- TSMLoc req_loc;
- TSMLoc field_loc;
- TSMLoc url_loc;
- char *url;
- int url_len;
- int content_length = 0;
- const char *method;
- int method_len;
- const char *host_str;
- int host_str_len;
- const char *host_hdr_str_val;
- int host_hdr_str_val_len;
-
- TSDebug(DEBUG_TAG, "inside attach_pvc_plugin");
- switch (event) {
- case TS_EVENT_HTTP_READ_REQUEST_PRE_REMAP:
-
- // if the request is issued by the TSHttpConnect() in this plugin, don't get in the endless cycle.
- if (TSHttpTxnIsInternal(txnp)) {
- TSDebug(DEBUG_TAG, "internal request");
- break;
- }
-
- if (TSHttpTxnClientReqGet(txnp, &req_bufp, &req_loc) == TS_ERROR) {
- LOG_ERROR("Error while retrieving client request header");
- break;
- }
-
- method = TSHttpHdrMethodGet(req_bufp, req_loc, &method_len);
- TSDebug(DEBUG_TAG, "inside handler");
-
- if (NOT_VALID_PTR(method) || method_len == 0) {
- TSDebug(DEBUG_TAG, "invalid method");
-
- TSHandleMLocRelease(req_bufp, TS_NULL_MLOC, req_loc);
- break;
- }
- // only deal with POST method
- TSDebug(DEBUG_TAG, "method: %s", method);
-
- if (static_cast<size_t>(method_len) != strlen(TS_HTTP_METHOD_POST) ||
- strncasecmp(method, TS_HTTP_METHOD_POST, method_len) != 0) {
- TSDebug(DEBUG_TAG, "Not POST method");
-
- // TSHandleStringRelease(req_bufp, req_loc, method);
- TSHandleMLocRelease(req_bufp, TS_NULL_MLOC, req_loc);
- break;
- }
-
- // TSHandleStringRelease(req_bufp, req_loc, method);
-
- TSDebug(DEBUG_TAG, "Got POST req");
- if (uconfig->url_list_file != nullptr) {
- TSDebug(DEBUG_TAG, "url_list_file != NULL");
- // check against URL list
- if (TSHttpHdrUrlGet(req_bufp, req_loc, &url_loc) == TS_ERROR) {
- LOG_ERROR("Couldn't get the url");
- TSHandleMLocRelease(req_bufp, TS_NULL_MLOC, req_loc);
- break;
- }
- host_str = TSUrlHostGet(req_bufp, url_loc, &host_str_len);
- if (NOT_VALID_PTR(host_str) || host_str_len <= 0) {
- // reverse proxy mode
- field_loc = TSMimeHdrFieldFind(req_bufp, req_loc, TS_MIME_FIELD_HOST, -1);
- if (NOT_VALID_PTR(field_loc)) {
- // if (VALID_PTR(str))
- // TSHandleStringRelease(req_bufp, url_loc, str);
- LOG_ERROR("Host field not found");
- TSHandleMLocRelease(req_bufp, req_loc, url_loc);
- TSHandleMLocRelease(req_bufp, TS_NULL_MLOC, req_loc);
- break;
- }
- host_hdr_str_val = TSMimeHdrFieldValueStringGet(req_bufp, req_loc, field_loc, -1, &host_hdr_str_val_len);
- if (NOT_VALID_PTR(host_hdr_str_val) || host_hdr_str_val_len <= 0) {
- // if (VALID_PTR(str))
- // TSHandleStringRelease(req_bufp, field_loc, str);
- TSHandleMLocRelease(req_bufp, req_loc, field_loc);
- TSHandleMLocRelease(req_bufp, req_loc, url_loc);
- TSHandleMLocRelease(req_bufp, TS_NULL_MLOC, req_loc);
- break;
- }
-
- char replacement_host_str[host_hdr_str_val_len + 1];
- memcpy(replacement_host_str, host_hdr_str_val, host_hdr_str_val_len);
- replacement_host_str[host_hdr_str_val_len] = '\0';
- TSDebug(DEBUG_TAG, "Adding host to request url: %s", replacement_host_str);
-
- const char *colon = strchr(replacement_host_str, ':');
- if (colon != nullptr && colon[1] != '\0') {
- int length = 0;
- const char *scheme = TSUrlSchemeGet(req_bufp, url_loc, &length);
- int port_str_val = atoi(colon + 1);
-
- if ((length == TS_URL_LEN_HTTP && strncmp(TS_URL_SCHEME_HTTP, scheme, length) == 0 && port_str_val != 80) ||
- (length == TS_URL_LEN_HTTPS && strncmp(TS_URL_SCHEME_HTTPS, scheme, length) == 0 && port_str_val != 443)) {
- TSUrlPortSet(req_bufp, url_loc, port_str_val);
- }
- host_hdr_str_val_len = colon - replacement_host_str;
- }
- TSUrlHostSet(req_bufp, url_loc, host_hdr_str_val, host_hdr_str_val_len);
-
- // TSHandleStringRelease(req_bufp, field_loc, str);
- TSHandleMLocRelease(req_bufp, req_loc, field_loc);
- } else {
- // TSHandleStringRelease(req_bufp, url_loc, str);
- }
-
- int i = uconfig->url_num;
- url = TSUrlStringGet(req_bufp, url_loc, &url_len);
- if (VALID_PTR(url)) {
- char urlStr[url_len + 1];
- memcpy(urlStr, url, url_len);
- urlStr[url_len] = '\0';
- TSDebug(DEBUG_TAG, "Request url: %s", urlStr);
-
- for (i = 0; i < uconfig->url_num; i++) {
- TSDebug(DEBUG_TAG, "uconfig url: %s", uconfig->urls[i]);
- if (strncmp(url, uconfig->urls[i], url_len) == 0) {
- break;
- }
- }
-
- TSfree(url);
- }
- TSHandleMLocRelease(req_bufp, req_loc, url_loc);
-
- if (uconfig->url_num > 0 && i == uconfig->url_num) {
- TSDebug(DEBUG_TAG, "breaking: url_num > 0 and i== url_num, URL match not found");
- TSHandleMLocRelease(req_bufp, TS_NULL_MLOC, req_loc);
- break;
- }
- }
-
- if (uconfig->convert_url) {
- TSDebug(DEBUG_TAG, "doing convert url");
- convert_url_func(req_bufp, req_loc);
- }
-
- field_loc = TSMimeHdrFieldFind(req_bufp, req_loc, TS_MIME_FIELD_CONTENT_LENGTH, TS_MIME_LEN_CONTENT_LENGTH);
- if (field_loc == nullptr) {
- TSHandleMLocRelease(req_bufp, TS_NULL_MLOC, req_loc);
- LOG_ERROR("TSMimeHdrFieldRetrieve");
- break;
- }
-
- content_length = TSMimeHdrFieldValueIntGet(req_bufp, req_loc, field_loc, 0);
- /*{
- TSHandleMLocRelease(req_bufp, req_loc, field_loc);
- TSHandleMLocRelease(req_bufp, TS_NULL_MLOC, req_loc);
- LOG_ERROR("TSMimeFieldValueGet");
-} else
- */
- // content_length = value;
-
- mutex = TSMutexCreate();
- if (NOT_VALID_PTR(mutex)) {
- TSHandleMLocRelease(req_bufp, req_loc, field_loc);
- TSHandleMLocRelease(req_bufp, TS_NULL_MLOC, req_loc);
- LOG_ERROR("TSMutexCreate");
- break;
- }
-
- new_cont = TSContCreate(pvc_plugin, mutex);
- if (NOT_VALID_PTR(new_cont)) {
- TSHandleMLocRelease(req_bufp, req_loc, field_loc);
- TSHandleMLocRelease(req_bufp, TS_NULL_MLOC, req_loc);
- LOG_ERROR("TSContCreate");
- break;
- }
-
- my_state = (pvc_state *)TSmalloc(sizeof(pvc_state));
- my_state->req_size = content_length;
- my_state->p_vc = nullptr;
- my_state->p_read_vio = nullptr;
- my_state->p_write_vio = nullptr;
-
- my_state->net_vc = nullptr;
- my_state->n_read_vio = nullptr;
- my_state->n_write_vio = nullptr;
-
- my_state->req_buffer = nullptr;
- my_state->req_reader = nullptr;
- my_state->resp_buffer = nullptr;
- my_state->resp_reader = nullptr;
- my_state->fd = -1;
- my_state->disk_io_mutex = nullptr;
-
- my_state->http_txnp = txnp; // not in use now, may need in the future
-
- my_state->req_finished = 0;
- my_state->resp_finished = 0;
- my_state->nbytes_to_consume =
- -1; // the length of server request header to remove from incoming stream (will replace with client request header)
-
- my_state->size_written = 0;
- my_state->size_read = 0;
- my_state->write_offset = 0;
- my_state->read_offset = 0;
- my_state->is_reading_from_disk = 0;
-
- my_state->chunk_buffer = (char *)TSmalloc(sizeof(char) * uconfig->chunk_size);
-
- my_state->disk_io_mutex = TSMutexCreate();
- if (NOT_VALID_PTR(my_state->disk_io_mutex)) {
- LOG_ERROR("TSMutexCreate");
- }
-
- my_state->req_hdr_buffer = TSIOBufferCreate();
- my_state->req_hdr_reader = TSIOBufferReaderAlloc(my_state->req_hdr_buffer);
- TSHttpHdrPrint(req_bufp, req_loc, my_state->req_hdr_buffer);
- // print_buffer(my_state->req_hdr_reader);
-
- my_state->req_size += TSIOBufferReaderAvail(my_state->req_hdr_reader);
-
- /* Increment upload_vc_count */
- TSStatIntIncrement(upload_vc_count, 1);
-
- if (!uconfig->use_disk_buffer && my_state->req_size > uconfig->mem_buffer_size) {
- TSDebug(DEBUG_TAG,
- "The request size %" PRId64 " is larger than memory buffer size %" PRId64
- ", bypass upload proxy feature for this request",
- my_state->req_size, uconfig->mem_buffer_size);
-
- pvc_cleanup(new_cont, my_state);
- TSHandleMLocRelease(req_bufp, req_loc, field_loc);
- TSHandleMLocRelease(req_bufp, TS_NULL_MLOC, req_loc);
- break;
- }
-
- TSContDataSet(new_cont, my_state);
-
- if (uconfig->use_disk_buffer) {
- char path[500];
- // coverity[dont_call]
- int index = (int)(random() % uconfig->subdir_num);
-
- sprintf(path, "%s/%02X/tmp-XXXXXX", uconfig->base_dir, index);
-
- my_state->fd = mkstemp(path);
- unlink(path);
- if (my_state->fd < 0) {
- LOG_ERROR("open");
- uconfig->use_disk_buffer = false;
- my_state->fd = -1;
- } else {
- TSDebug(DEBUG_TAG, "temp filename: %s", path);
- }
- }
-
- TSDebug(DEBUG_TAG, "calling TSHttpTxnIntercept()");
- TSHttpTxnIntercept(new_cont, txnp);
-
- break;
- default:
- TSReleaseAssert(!"Unexpected Event");
- break;
- }
-
- TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
- return 0;
-}
-
-static int
-create_directory()
-{
- char str[10];
- char cwd[4096];
- int i;
- DIR *dir;
- struct dirent *d;
-
- if (getcwd(cwd, 4096) == nullptr) {
- TSError("[%s] getcwd fails", PLUGIN_NAME);
- return 0;
- }
-
- if (chdir(uconfig->base_dir) < 0) {
- if (mkdir(uconfig->base_dir, S_IRWXU | S_IRWXG | S_IRWXO) < 0) {
- TSError("[%s] Unable to enter or create %s", PLUGIN_NAME, uconfig->base_dir);
- goto error_out;
- }
- if (chdir(uconfig->base_dir) < 0) {
- TSError("[%s] Unable enter %s", PLUGIN_NAME, uconfig->base_dir);
- goto error_out;
- }
- }
- for (i = 0; i < uconfig->subdir_num; i++) {
- snprintf(str, 10, "%02X", i);
- if (chdir(str) < 0) {
- if (mkdir(str, S_IRWXU | S_IRWXG | S_IRWXO) < 0) {
- TSError("[%s] Unable to enter or create %s/%s", PLUGIN_NAME, uconfig->base_dir, str);
- goto error_out;
- }
- if (chdir(str) < 0) {
- TSError("[%s] Unable to enter %s/%s", PLUGIN_NAME, uconfig->base_dir, str);
- goto error_out;
- }
- }
- dir = opendir(".");
- if (dir == nullptr) {
- goto error_out;
- }
- while ((d = readdir(dir))) {
- if (remove(d->d_name) < 0) {
- TSError("[%s] Unable to remove '%s': %s", PLUGIN_NAME, d->d_name, strerror(errno));
- closedir(dir);
- goto error_out;
- }
- }
- closedir(dir);
- if (chdir("..") == -1) {
- return 0;
- }
- }
-
- if (chdir(cwd) == -1) {
- return 0;
- }
-
- return 1;
-
-error_out:
- /* Debian's compiler chain complains about not using the return
- value of chdir() and cannot be silenced
- The reason is the combination of -D_FORTIFY_SOURCE=2 -O
- */
- if (chdir(cwd) == -1) {
- return 0;
- }
-
- return 0;
-}
-
-static void
-load_urls(char *filename)
-{
- TSFile file;
- char *url_buf;
- char *eol;
- int i;
-
- url_buf = (char *)TSmalloc(sizeof(char) * (uconfig->max_url_length + 1));
- url_buf[uconfig->max_url_length] = '\0';
-
- for (i = 0; i < 2; i++) {
- if ((file = TSfopen(filename, "r")) == nullptr) {
- TSfree(url_buf);
- TSError("[%s] Fail to open %s", PLUGIN_NAME, filename);
- return;
- }
- if (i == 0) { // first round
- uconfig->url_num = 0;
- while (TSfgets(file, url_buf, uconfig->max_url_length) != nullptr) {
- uconfig->url_num++;
- }
- uconfig->urls = (char **)TSmalloc(sizeof(char *) * uconfig->url_num);
- } else { // second round
- int idx = 0;
- while (TSfgets(file, url_buf, uconfig->max_url_length) != nullptr && idx < uconfig->url_num) {
- if ((eol = strstr(url_buf, "\r\n")) != nullptr) {
- /* To handle newlines on Windows */
- *eol = '\0';
- } else if ((eol = strchr(url_buf, '\n')) != nullptr) {
- *eol = '\0';
- } else {
- /* Not a valid line, skip it */
- continue;
- }
- uconfig->urls[idx] = TSstrdup(url_buf);
- idx++;
- }
- uconfig->url_num = idx;
- }
- TSfclose(file);
- }
- TSfree(url_buf);
-}
-
-void
-parse_config_line(char *line, const struct config_val_ul *cv)
-{
- const char *delim = "\t\r\n ";
- char *save = nullptr;
- char *tok = strtok_r(line, delim, &save);
-
- while (tok && cv->str) {
- if (!strcmp(tok, cv->str)) {
- tok = strtok_r(nullptr, delim, &save);
- if (tok) {
- switch (cv->type) {
- case TYPE_INT: {
- char *end = tok;
- int iv = strtol(tok, &end, 10);
- if (end && *end == '\0') {
- *((int *)cv->val) = iv;
- TSError("[%s] Parsed int config value %s : %d", PLUGIN_NAME, cv->str, iv);
- TSDebug(DEBUG_TAG, "Parsed int config value %s : %d", cv->str, iv);
- }
- break;
- }
- case TYPE_UINT: {
- char *end = tok;
- unsigned int uiv = strtoul(tok, &end, 10);
- if (end && *end == '\0') {
- *((unsigned int *)cv->val) = uiv;
- TSError("[%s] Parsed uint config value %s : %u", PLUGIN_NAME, cv->str, uiv);
- TSDebug(DEBUG_TAG, "Parsed uint config value %s : %u", cv->str, uiv);
- }
- break;
- }
- case TYPE_LONG: {
- char *end = tok;
- long lv = strtol(tok, &end, 10);
- if (end && *end == '\0') {
- *((long *)cv->val) = lv;
- TSError("[%s] Parsed long config value %s : %ld", PLUGIN_NAME, cv->str, lv);
- TSDebug(DEBUG_TAG, "Parsed long config value %s : %ld", cv->str, lv);
- }
- break;
- }
- case TYPE_ULONG: {
- char *end = tok;
- unsigned long ulv = strtoul(tok, &end, 10);
- if (end && *end == '\0') {
- *((unsigned long *)cv->val) = ulv;
- TSError("[%s] Parsed ulong config value %s : %lu", PLUGIN_NAME, cv->str, ulv);
- TSDebug(DEBUG_TAG, "Parsed ulong config value %s : %lu", cv->str, ulv);
- }
- break;
- }
- case TYPE_STRING: {
- size_t len = strlen(tok);
- if (len > 0) {
- *((char **)cv->val) = (char *)TSmalloc(len + 1);
- strcpy(*((char **)cv->val), tok);
- TSError("[%s] Parsed string config value %s : %s", PLUGIN_NAME, cv->str, tok);
- TSDebug(DEBUG_TAG, "Parsed string config value %s : %s", cv->str, tok);
- }
- break;
- }
- case TYPE_BOOL: {
- size_t len = strlen(tok);
- if (len > 0) {
- if (*tok == '1' || *tok == 't') {
- *((bool *)cv->val) = true;
- } else {
- *((bool *)cv->val) = false;
- }
- TSError("[%s] Parsed bool config value %s : %d", PLUGIN_NAME, cv->str, *((bool *)cv->val));
- TSDebug(DEBUG_TAG, "Parsed bool config value %s : %d", cv->str, *((bool *)cv->val));
- }
- break;
- }
- default:
- break;
- }
- }
- }
- cv++;
- }
-}
-
-bool
-read_upload_config(const char *file_name)
-{
- TSDebug(DEBUG_TAG, "read_upload_config: %s", file_name);
- uconfig = (upload_config *)TSmalloc(sizeof(upload_config));
- uconfig->use_disk_buffer = true;
- uconfig->convert_url = false;
- uconfig->chunk_size = 16 * 1024;
- uconfig->mem_buffer_size = 32 * 1024;
- uconfig->url_list_file = nullptr;
- uconfig->max_url_length = 4096;
- uconfig->url_num = 0;
- uconfig->urls = nullptr;
- uconfig->base_dir = nullptr;
- uconfig->subdir_num = 64;
- uconfig->thread_num = 4;
-
- struct config_val_ul config_vals[] = {{"use_disk_buffer", TYPE_BOOL, &(uconfig->use_disk_buffer)},
- {"convert_url", TYPE_BOOL, &(uconfig->convert_url)},
- {"chunk_size", TYPE_ULONG, &(uconfig->chunk_size)},
- {"mem_buffer_size", TYPE_ULONG, &(uconfig->mem_buffer_size)},
- {"url_list_file", TYPE_STRING, &(uconfig->url_list_file)},
- {"max_url_length", TYPE_ULONG, &(uconfig->max_url_length)},
- {"base_dir", TYPE_STRING, &(uconfig->base_dir)},
- {"subdir_num", TYPE_UINT, &(uconfig->subdir_num)},
- {"thread_num", TYPE_UINT, &(uconfig->thread_num)},
- {nullptr, TYPE_LONG, nullptr}};
- TSFile conf_file;
- conf_file = TSfopen(file_name, "r");
-
- if (conf_file != nullptr) {
- TSDebug(DEBUG_TAG, "opened config: %s", file_name);
- char buf[1024];
- while (TSfgets(conf_file, buf, sizeof(buf) - 1) != nullptr) {
- if (buf[0] != '#') {
- parse_config_line(buf, config_vals);
- }
- }
- TSfclose(conf_file);
- } else {
- TSError("[%s] Failed to open upload config file %s", PLUGIN_NAME, file_name);
- // if fail to open config file, use the default config
- }
-
- if (uconfig->base_dir == nullptr) {
- uconfig->base_dir = TSstrdup("/FOOBAR/var/buffer_upload_tmp");
- } else {
- // remove the "/" at the end.
- if (uconfig->base_dir[strlen(uconfig->base_dir) - 1] == '/') {
- uconfig->base_dir[strlen(uconfig->base_dir) - 1] = '\0';
- }
- }
-
- if (uconfig->subdir_num <= 0) {
- // default value
- uconfig->subdir_num = 64;
- }
-
- if (uconfig->thread_num <= 0) {
- // default value
- uconfig->thread_num = 4;
- }
-
- return true;
-}
-
-void
-TSPluginInit(int argc, const char *argv[])
-{
- TSPluginRegistrationInfo info;
- TSCont contp;
- char default_filename[1024];
- const char *conf_filename;
-
- if (argc > 1) {
- conf_filename = argv[1];
- } else {
- sprintf(default_filename, "%s/upload.conf", TSPluginDirGet());
- conf_filename = default_filename;
- }
-
- if (!read_upload_config(conf_filename) || !uconfig) {
- if (argc > 1) {
- TSError("[%s] Failed to read upload config %s", PLUGIN_NAME, argv[1]);
- } else {
- TSError("[%s] No config file specified. Specify conf file in plugin.conf: "
- "'buffer_upload.so /path/to/upload.conf'",
- PLUGIN_NAME);
- }
- }
- // set the num of threads for disk AIO
- if (TSAIOThreadNumSet(uconfig->thread_num) == TS_ERROR) {
- TSError("[%s] Failed to set thread number", PLUGIN_NAME);
- }
-
- TSDebug(DEBUG_TAG, "uconfig->url_list_file: %s", uconfig->url_list_file);
- if (uconfig->url_list_file) {
- load_urls(uconfig->url_list_file);
- TSDebug(DEBUG_TAG, "loaded uconfig->url_list_file, num urls: %d", uconfig->url_num);
- }
-
- info.plugin_name = const_cast<char *>("buffer_upload");
- info.vendor_name = const_cast<char *>("Apache Software Foundation");
- info.support_email = const_cast<char *>("dev@trafficserver.apache.org");
-
- if (uconfig->use_disk_buffer && !create_directory()) {
- TSError("[%s] Directory creation failed", PLUGIN_NAME);
- uconfig->use_disk_buffer = false;
- }
-
- if (TSPluginRegister(&info) != TS_SUCCESS) {
- TSError("[%s] Plugin registration failed", PLUGIN_NAME);
- }
-
- /* create the statistic variables */
- upload_vc_count = TSStatCreate("upload_vc.count", TS_RECORDDATATYPE_INT, TS_STAT_NON_PERSISTENT, TS_STAT_SYNC_SUM);
-
- contp = TSContCreate(attach_pvc_plugin, nullptr);
- TSHttpHookAdd(TS_HTTP_PRE_REMAP_HOOK, contp);
-}