Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

8800 lines (7290 sloc) 254.452 kB
/** @file
Implements callin functions for TSAPI plugins.
@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.
*/
#include <stdio.h>
#include "ts/ink_platform.h"
#include "ts/ink_base64.h"
#include "ts/I_Layout.h"
#include "ts.h"
#include "InkAPIInternal.h"
#include "Log.h"
#include "URL.h"
#include "MIME.h"
#include "HTTP.h"
#include "HttpClientSession.h"
#include "Http2ClientSession.h"
#include "HttpServerSession.h"
#include "HttpSM.h"
#include "HttpConfig.h"
#include "P_Net.h"
#include "P_UDPNet.h"
#include "P_HostDB.h"
#include "StatSystem.h"
#include "P_Cache.h"
#include "I_RecCore.h"
#include "I_RecSignals.h"
#include "ProxyConfig.h"
#include "Plugin.h"
#include "LogObject.h"
#include "LogConfig.h"
//#include "UserNameCache.h"
#include "PluginVC.h"
#include "api/ts/experimental.h"
#include "ICP.h"
#include "HttpSessionAccept.h"
#include "PluginVC.h"
#include "FetchSM.h"
#include "HttpDebugNames.h"
#include "I_AIO.h"
#include "I_Tasks.h"
#include "I_RecDefs.h"
#include "I_RecCore.h"
#include "HttpProxyServerMain.h"
/****************************************************************
* IMPORTANT - READ ME
* Any plugin using the IO Core must enter
* with a held mutex. SDK 1.0, 1.1 & 2.0 did not
* have this restriction so we need to add a mutex
* to Plugin's Continuation if it trys to use the IOCore
* Not only does the plugin have to have a mutex
* before entering the IO Core. The mutex needs to be held.
* We now take out the mutex on each call to ensure it is
* held for the entire duration of the IOCore call
***************************************************************/
// helper macro for setting HTTPHdr data
#define SET_HTTP_HDR(_HDR, _BUF_PTR, _OBJ_PTR) \
_HDR.m_heap = ((HdrHeapSDKHandle *)_BUF_PTR)->m_heap; \
_HDR.m_http = (HTTPHdrImpl *)_OBJ_PTR; \
_HDR.m_mime = _HDR.m_http->m_fields_impl;
// Globals for new librecords stats
static volatile int api_rsb_index = 0;
static RecRawStatBlock *api_rsb;
// Library init functions needed for API.
extern void ts_session_protocol_well_known_name_indices_init();
// Globals for the Sessions/Transaction index registry
static volatile int next_argv_index = 0;
struct _STATE_ARG_TABLE {
char *name;
size_t name_len;
char *description;
} state_arg_table[HTTP_SSN_TXN_MAX_USER_ARG];
/* URL schemes */
tsapi const char *TS_URL_SCHEME_FILE;
tsapi const char *TS_URL_SCHEME_FTP;
tsapi const char *TS_URL_SCHEME_GOPHER;
tsapi const char *TS_URL_SCHEME_HTTP;
tsapi const char *TS_URL_SCHEME_HTTPS;
tsapi const char *TS_URL_SCHEME_MAILTO;
tsapi const char *TS_URL_SCHEME_NEWS;
tsapi const char *TS_URL_SCHEME_NNTP;
tsapi const char *TS_URL_SCHEME_PROSPERO;
tsapi const char *TS_URL_SCHEME_TELNET;
tsapi const char *TS_URL_SCHEME_TUNNEL;
tsapi const char *TS_URL_SCHEME_WAIS;
tsapi const char *TS_URL_SCHEME_PNM;
tsapi const char *TS_URL_SCHEME_RTSP;
tsapi const char *TS_URL_SCHEME_RTSPU;
tsapi const char *TS_URL_SCHEME_MMS;
tsapi const char *TS_URL_SCHEME_MMSU;
tsapi const char *TS_URL_SCHEME_MMST;
/* URL schemes string lengths */
tsapi int TS_URL_LEN_FILE;
tsapi int TS_URL_LEN_FTP;
tsapi int TS_URL_LEN_GOPHER;
tsapi int TS_URL_LEN_HTTP;
tsapi int TS_URL_LEN_HTTPS;
tsapi int TS_URL_LEN_MAILTO;
tsapi int TS_URL_LEN_NEWS;
tsapi int TS_URL_LEN_NNTP;
tsapi int TS_URL_LEN_PROSPERO;
tsapi int TS_URL_LEN_TELNET;
tsapi int TS_URL_LEN_TUNNEL;
tsapi int TS_URL_LEN_WAIS;
tsapi int TS_URL_LEN_PNM;
tsapi int TS_URL_LEN_RTSP;
tsapi int TS_URL_LEN_RTSPU;
tsapi int TS_URL_LEN_MMS;
tsapi int TS_URL_LEN_MMSU;
tsapi int TS_URL_LEN_MMST;
/* MIME fields */
tsapi const char *TS_MIME_FIELD_ACCEPT;
tsapi const char *TS_MIME_FIELD_ACCEPT_CHARSET;
tsapi const char *TS_MIME_FIELD_ACCEPT_ENCODING;
tsapi const char *TS_MIME_FIELD_ACCEPT_LANGUAGE;
tsapi const char *TS_MIME_FIELD_ACCEPT_RANGES;
tsapi const char *TS_MIME_FIELD_AGE;
tsapi const char *TS_MIME_FIELD_ALLOW;
tsapi const char *TS_MIME_FIELD_APPROVED;
tsapi const char *TS_MIME_FIELD_AUTHORIZATION;
tsapi const char *TS_MIME_FIELD_BYTES;
tsapi const char *TS_MIME_FIELD_CACHE_CONTROL;
tsapi const char *TS_MIME_FIELD_CLIENT_IP;
tsapi const char *TS_MIME_FIELD_CONNECTION;
tsapi const char *TS_MIME_FIELD_CONTENT_BASE;
tsapi const char *TS_MIME_FIELD_CONTENT_ENCODING;
tsapi const char *TS_MIME_FIELD_CONTENT_LANGUAGE;
tsapi const char *TS_MIME_FIELD_CONTENT_LENGTH;
tsapi const char *TS_MIME_FIELD_CONTENT_LOCATION;
tsapi const char *TS_MIME_FIELD_CONTENT_MD5;
tsapi const char *TS_MIME_FIELD_CONTENT_RANGE;
tsapi const char *TS_MIME_FIELD_CONTENT_TYPE;
tsapi const char *TS_MIME_FIELD_CONTROL;
tsapi const char *TS_MIME_FIELD_COOKIE;
tsapi const char *TS_MIME_FIELD_DATE;
tsapi const char *TS_MIME_FIELD_DISTRIBUTION;
tsapi const char *TS_MIME_FIELD_ETAG;
tsapi const char *TS_MIME_FIELD_EXPECT;
tsapi const char *TS_MIME_FIELD_EXPIRES;
tsapi const char *TS_MIME_FIELD_FOLLOWUP_TO;
tsapi const char *TS_MIME_FIELD_FROM;
tsapi const char *TS_MIME_FIELD_HOST;
tsapi const char *TS_MIME_FIELD_IF_MATCH;
tsapi const char *TS_MIME_FIELD_IF_MODIFIED_SINCE;
tsapi const char *TS_MIME_FIELD_IF_NONE_MATCH;
tsapi const char *TS_MIME_FIELD_IF_RANGE;
tsapi const char *TS_MIME_FIELD_IF_UNMODIFIED_SINCE;
tsapi const char *TS_MIME_FIELD_KEEP_ALIVE;
tsapi const char *TS_MIME_FIELD_KEYWORDS;
tsapi const char *TS_MIME_FIELD_LAST_MODIFIED;
tsapi const char *TS_MIME_FIELD_LINES;
tsapi const char *TS_MIME_FIELD_LOCATION;
tsapi const char *TS_MIME_FIELD_MAX_FORWARDS;
tsapi const char *TS_MIME_FIELD_MESSAGE_ID;
tsapi const char *TS_MIME_FIELD_NEWSGROUPS;
tsapi const char *TS_MIME_FIELD_ORGANIZATION;
tsapi const char *TS_MIME_FIELD_PATH;
tsapi const char *TS_MIME_FIELD_PRAGMA;
tsapi const char *TS_MIME_FIELD_PROXY_AUTHENTICATE;
tsapi const char *TS_MIME_FIELD_PROXY_AUTHORIZATION;
tsapi const char *TS_MIME_FIELD_PROXY_CONNECTION;
tsapi const char *TS_MIME_FIELD_PUBLIC;
tsapi const char *TS_MIME_FIELD_RANGE;
tsapi const char *TS_MIME_FIELD_REFERENCES;
tsapi const char *TS_MIME_FIELD_REFERER;
tsapi const char *TS_MIME_FIELD_REPLY_TO;
tsapi const char *TS_MIME_FIELD_RETRY_AFTER;
tsapi const char *TS_MIME_FIELD_SENDER;
tsapi const char *TS_MIME_FIELD_SERVER;
tsapi const char *TS_MIME_FIELD_SET_COOKIE;
tsapi const char *TS_MIME_FIELD_STRICT_TRANSPORT_SECURITY;
tsapi const char *TS_MIME_FIELD_SUBJECT;
tsapi const char *TS_MIME_FIELD_SUMMARY;
tsapi const char *TS_MIME_FIELD_TE;
tsapi const char *TS_MIME_FIELD_TRANSFER_ENCODING;
tsapi const char *TS_MIME_FIELD_UPGRADE;
tsapi const char *TS_MIME_FIELD_USER_AGENT;
tsapi const char *TS_MIME_FIELD_VARY;
tsapi const char *TS_MIME_FIELD_VIA;
tsapi const char *TS_MIME_FIELD_WARNING;
tsapi const char *TS_MIME_FIELD_WWW_AUTHENTICATE;
tsapi const char *TS_MIME_FIELD_XREF;
tsapi const char *TS_MIME_FIELD_X_FORWARDED_FOR;
/* MIME fields string lengths */
tsapi int TS_MIME_LEN_ACCEPT;
tsapi int TS_MIME_LEN_ACCEPT_CHARSET;
tsapi int TS_MIME_LEN_ACCEPT_ENCODING;
tsapi int TS_MIME_LEN_ACCEPT_LANGUAGE;
tsapi int TS_MIME_LEN_ACCEPT_RANGES;
tsapi int TS_MIME_LEN_AGE;
tsapi int TS_MIME_LEN_ALLOW;
tsapi int TS_MIME_LEN_APPROVED;
tsapi int TS_MIME_LEN_AUTHORIZATION;
tsapi int TS_MIME_LEN_BYTES;
tsapi int TS_MIME_LEN_CACHE_CONTROL;
tsapi int TS_MIME_LEN_CLIENT_IP;
tsapi int TS_MIME_LEN_CONNECTION;
tsapi int TS_MIME_LEN_CONTENT_BASE;
tsapi int TS_MIME_LEN_CONTENT_ENCODING;
tsapi int TS_MIME_LEN_CONTENT_LANGUAGE;
tsapi int TS_MIME_LEN_CONTENT_LENGTH;
tsapi int TS_MIME_LEN_CONTENT_LOCATION;
tsapi int TS_MIME_LEN_CONTENT_MD5;
tsapi int TS_MIME_LEN_CONTENT_RANGE;
tsapi int TS_MIME_LEN_CONTENT_TYPE;
tsapi int TS_MIME_LEN_CONTROL;
tsapi int TS_MIME_LEN_COOKIE;
tsapi int TS_MIME_LEN_DATE;
tsapi int TS_MIME_LEN_DISTRIBUTION;
tsapi int TS_MIME_LEN_ETAG;
tsapi int TS_MIME_LEN_EXPECT;
tsapi int TS_MIME_LEN_EXPIRES;
tsapi int TS_MIME_LEN_FOLLOWUP_TO;
tsapi int TS_MIME_LEN_FROM;
tsapi int TS_MIME_LEN_HOST;
tsapi int TS_MIME_LEN_IF_MATCH;
tsapi int TS_MIME_LEN_IF_MODIFIED_SINCE;
tsapi int TS_MIME_LEN_IF_NONE_MATCH;
tsapi int TS_MIME_LEN_IF_RANGE;
tsapi int TS_MIME_LEN_IF_UNMODIFIED_SINCE;
tsapi int TS_MIME_LEN_KEEP_ALIVE;
tsapi int TS_MIME_LEN_KEYWORDS;
tsapi int TS_MIME_LEN_LAST_MODIFIED;
tsapi int TS_MIME_LEN_LINES;
tsapi int TS_MIME_LEN_LOCATION;
tsapi int TS_MIME_LEN_MAX_FORWARDS;
tsapi int TS_MIME_LEN_MESSAGE_ID;
tsapi int TS_MIME_LEN_NEWSGROUPS;
tsapi int TS_MIME_LEN_ORGANIZATION;
tsapi int TS_MIME_LEN_PATH;
tsapi int TS_MIME_LEN_PRAGMA;
tsapi int TS_MIME_LEN_PROXY_AUTHENTICATE;
tsapi int TS_MIME_LEN_PROXY_AUTHORIZATION;
tsapi int TS_MIME_LEN_PROXY_CONNECTION;
tsapi int TS_MIME_LEN_PUBLIC;
tsapi int TS_MIME_LEN_RANGE;
tsapi int TS_MIME_LEN_REFERENCES;
tsapi int TS_MIME_LEN_REFERER;
tsapi int TS_MIME_LEN_REPLY_TO;
tsapi int TS_MIME_LEN_RETRY_AFTER;
tsapi int TS_MIME_LEN_SENDER;
tsapi int TS_MIME_LEN_SERVER;
tsapi int TS_MIME_LEN_SET_COOKIE;
tsapi int TS_MIME_LEN_STRICT_TRANSPORT_SECURITY;
tsapi int TS_MIME_LEN_SUBJECT;
tsapi int TS_MIME_LEN_SUMMARY;
tsapi int TS_MIME_LEN_TE;
tsapi int TS_MIME_LEN_TRANSFER_ENCODING;
tsapi int TS_MIME_LEN_UPGRADE;
tsapi int TS_MIME_LEN_USER_AGENT;
tsapi int TS_MIME_LEN_VARY;
tsapi int TS_MIME_LEN_VIA;
tsapi int TS_MIME_LEN_WARNING;
tsapi int TS_MIME_LEN_WWW_AUTHENTICATE;
tsapi int TS_MIME_LEN_XREF;
tsapi int TS_MIME_LEN_X_FORWARDED_FOR;
/* HTTP miscellaneous values */
tsapi const char *TS_HTTP_VALUE_BYTES;
tsapi const char *TS_HTTP_VALUE_CHUNKED;
tsapi const char *TS_HTTP_VALUE_CLOSE;
tsapi const char *TS_HTTP_VALUE_COMPRESS;
tsapi const char *TS_HTTP_VALUE_DEFLATE;
tsapi const char *TS_HTTP_VALUE_GZIP;
tsapi const char *TS_HTTP_VALUE_IDENTITY;
tsapi const char *TS_HTTP_VALUE_KEEP_ALIVE;
tsapi const char *TS_HTTP_VALUE_MAX_AGE;
tsapi const char *TS_HTTP_VALUE_MAX_STALE;
tsapi const char *TS_HTTP_VALUE_MIN_FRESH;
tsapi const char *TS_HTTP_VALUE_MUST_REVALIDATE;
tsapi const char *TS_HTTP_VALUE_NONE;
tsapi const char *TS_HTTP_VALUE_NO_CACHE;
tsapi const char *TS_HTTP_VALUE_NO_STORE;
tsapi const char *TS_HTTP_VALUE_NO_TRANSFORM;
tsapi const char *TS_HTTP_VALUE_ONLY_IF_CACHED;
tsapi const char *TS_HTTP_VALUE_PRIVATE;
tsapi const char *TS_HTTP_VALUE_PROXY_REVALIDATE;
tsapi const char *TS_HTTP_VALUE_PUBLIC;
tsapi const char *TS_HTTP_VALUE_S_MAXAGE;
/* HTTP miscellaneous values string lengths */
tsapi int TS_HTTP_LEN_BYTES;
tsapi int TS_HTTP_LEN_CHUNKED;
tsapi int TS_HTTP_LEN_CLOSE;
tsapi int TS_HTTP_LEN_COMPRESS;
tsapi int TS_HTTP_LEN_DEFLATE;
tsapi int TS_HTTP_LEN_GZIP;
tsapi int TS_HTTP_LEN_IDENTITY;
tsapi int TS_HTTP_LEN_KEEP_ALIVE;
tsapi int TS_HTTP_LEN_MAX_AGE;
tsapi int TS_HTTP_LEN_MAX_STALE;
tsapi int TS_HTTP_LEN_MIN_FRESH;
tsapi int TS_HTTP_LEN_MUST_REVALIDATE;
tsapi int TS_HTTP_LEN_NONE;
tsapi int TS_HTTP_LEN_NO_CACHE;
tsapi int TS_HTTP_LEN_NO_STORE;
tsapi int TS_HTTP_LEN_NO_TRANSFORM;
tsapi int TS_HTTP_LEN_ONLY_IF_CACHED;
tsapi int TS_HTTP_LEN_PRIVATE;
tsapi int TS_HTTP_LEN_PROXY_REVALIDATE;
tsapi int TS_HTTP_LEN_PUBLIC;
tsapi int TS_HTTP_LEN_S_MAXAGE;
/* HTTP methods */
tsapi const char *TS_HTTP_METHOD_CONNECT;
tsapi const char *TS_HTTP_METHOD_DELETE;
tsapi const char *TS_HTTP_METHOD_GET;
tsapi const char *TS_HTTP_METHOD_HEAD;
tsapi const char *TS_HTTP_METHOD_ICP_QUERY;
tsapi const char *TS_HTTP_METHOD_OPTIONS;
tsapi const char *TS_HTTP_METHOD_POST;
tsapi const char *TS_HTTP_METHOD_PURGE;
tsapi const char *TS_HTTP_METHOD_PUT;
tsapi const char *TS_HTTP_METHOD_TRACE;
tsapi const char *TS_HTTP_METHOD_PUSH;
/* HTTP methods string lengths */
tsapi int TS_HTTP_LEN_CONNECT;
tsapi int TS_HTTP_LEN_DELETE;
tsapi int TS_HTTP_LEN_GET;
tsapi int TS_HTTP_LEN_HEAD;
tsapi int TS_HTTP_LEN_ICP_QUERY;
tsapi int TS_HTTP_LEN_OPTIONS;
tsapi int TS_HTTP_LEN_POST;
tsapi int TS_HTTP_LEN_PURGE;
tsapi int TS_HTTP_LEN_PUT;
tsapi int TS_HTTP_LEN_TRACE;
tsapi int TS_HTTP_LEN_PUSH;
/* MLoc Constants */
tsapi const TSMLoc TS_NULL_MLOC = (TSMLoc)NULL;
HttpAPIHooks *http_global_hooks = NULL;
SslAPIHooks *ssl_hooks = NULL;
LifecycleAPIHooks *lifecycle_hooks = NULL;
ConfigUpdateCbTable *global_config_cbs = NULL;
static char traffic_server_version[128] = "";
static int ts_major_version = 0;
static int ts_minor_version = 0;
static int ts_patch_version = 0;
static ClassAllocator<APIHook> apiHookAllocator("apiHookAllocator");
static ClassAllocator<INKContInternal> INKContAllocator("INKContAllocator");
static ClassAllocator<INKVConnInternal> INKVConnAllocator("INKVConnAllocator");
static ClassAllocator<MIMEFieldSDKHandle> mHandleAllocator("MIMEFieldSDKHandle");
////////////////////////////////////////////////////////////////////
//
// API error logging
//
////////////////////////////////////////////////////////////////////
void
TSError(const char *fmt, ...)
{
va_list args;
if (is_action_tag_set("deft") || is_action_tag_set("sdk_vbos_errors")) {
va_start(args, fmt);
diags->print_va(NULL, DL_Error, NULL, fmt, args);
va_end(args);
}
va_start(args, fmt);
Log::va_error((char *)fmt, args);
va_end(args);
}
// Assert in debug AND optim
void
_TSReleaseAssert(const char *text, const char *file, int line)
{
_ink_assert(text, file, line);
}
// Assert only in debug
int
#ifdef DEBUG
_TSAssert(const char *text, const char *file, int line)
{
_ink_assert(text, file, line);
return 0;
}
#else
_TSAssert(const char *, const char *, int)
{
return 0;
}
#endif
// This assert is for internal API use only.
#if TS_USE_FAST_SDK
#define sdk_assert(EX) (void)(EX)
#else
#define sdk_assert(EX) ((void)((EX) ? (void)0 : _TSReleaseAssert(#EX, __FILE__, __LINE__)))
#endif
////////////////////////////////////////////////////////////////////
//
// SDK Interoperability Support
//
// ----------------------------------------------------------------
//
// Standalone Fields (SDK Version-Interoperability Hack)
//
//
// A "standalone" field is an ugly hack for portability with old
// versions of the SDK that mirrored the old header system. In
// the old system, you could create arbitrary tiny little field
// objects, distinct from MIME header objects, and link them
// together. In the new header system, all fields are internal
// constituents of the MIME header. To preserve the semantics of
// the old SDK, we need to maintain the concept of fields that
// are created outside of a MIME header. Whenever a field is
// "attached" to a MIME header, it is copied into the MIME header
// field's slot, and the handle to the field is updated to refer
// to the new field.
//
// Hopefully, we can eliminate this old compatibility interface and
// migrate users to the newer semantics quickly.
//
// ----------------------------------------------------------------
//
// MIMEField SDK Handles (SDK Version-Interoperability Hack)
//
// MIMEField "handles" are used by the SDK as an indirect reference
// to the MIMEField. Because versions 1 & 2 of the SDK allowed
// standalone fields that existed without associated MIME headers,
// and because the version 3 SDK requires an associated MIME header
// for all field mutation operations (for presence bits, etc.) we
// need a data structure that:
//
// * identifies standalone fields and stores field name/value
// information for fields that are not yet in a header
// * redirects the field to a real header field when the field
// is inserted into a header
// * maintains the associated MIMEHdrImpl when returning field
// slots from lookup and create functions
//
// If the MIMEHdrImpl pointer is NULL, then the handle points
// to a standalone field, otherwise the handle points to a field
// within the MIME header.
//
////////////////////////////////////////////////////////////////////
/*****************************************************************/
/* Handles to headers are impls, but need to handle MIME or HTTP */
/*****************************************************************/
inline MIMEHdrImpl *
_hdr_obj_to_mime_hdr_impl(HdrHeapObjImpl *obj)
{
MIMEHdrImpl *impl;
if (obj->m_type == HDR_HEAP_OBJ_HTTP_HEADER)
impl = ((HTTPHdrImpl *)obj)->m_fields_impl;
else if (obj->m_type == HDR_HEAP_OBJ_MIME_HEADER)
impl = (MIMEHdrImpl *)obj;
else {
ink_release_assert(!"mloc not a header type");
impl = NULL; /* gcc does not know about 'ink_release_assert' - make it happy */
}
return impl;
}
inline MIMEHdrImpl *
_hdr_mloc_to_mime_hdr_impl(TSMLoc mloc)
{
return _hdr_obj_to_mime_hdr_impl((HdrHeapObjImpl *)mloc);
}
TSReturnCode
sdk_sanity_check_field_handle(TSMLoc field, TSMLoc parent_hdr = NULL)
{
if (field == TS_NULL_MLOC)
return TS_ERROR;
MIMEFieldSDKHandle *field_handle = (MIMEFieldSDKHandle *)field;
if (field_handle->m_type != HDR_HEAP_OBJ_FIELD_SDK_HANDLE)
return TS_ERROR;
if (parent_hdr != NULL) {
MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(parent_hdr);
if (field_handle->mh != mh)
return TS_ERROR;
}
return TS_SUCCESS;
}
TSReturnCode
sdk_sanity_check_mbuffer(TSMBuffer bufp)
{
HdrHeapSDKHandle *handle = (HdrHeapSDKHandle *)bufp;
if ((handle == NULL) || (handle->m_heap == NULL) || (handle->m_heap->m_magic != HDR_BUF_MAGIC_ALIVE))
return TS_ERROR;
return TS_SUCCESS;
}
TSReturnCode
sdk_sanity_check_mime_hdr_handle(TSMLoc field)
{
if (field == TS_NULL_MLOC)
return TS_ERROR;
MIMEFieldSDKHandle *field_handle = (MIMEFieldSDKHandle *)field;
if (field_handle->m_type != HDR_HEAP_OBJ_MIME_HEADER)
return TS_ERROR;
return TS_SUCCESS;
}
TSReturnCode
sdk_sanity_check_url_handle(TSMLoc field)
{
if (field == TS_NULL_MLOC)
return TS_ERROR;
MIMEFieldSDKHandle *field_handle = (MIMEFieldSDKHandle *)field;
if (field_handle->m_type != HDR_HEAP_OBJ_URL)
return TS_ERROR;
return TS_SUCCESS;
}
TSReturnCode
sdk_sanity_check_http_hdr_handle(TSMLoc field)
{
if (field == TS_NULL_MLOC)
return TS_ERROR;
HTTPHdrImpl *field_handle = (HTTPHdrImpl *)field;
if (field_handle->m_type != HDR_HEAP_OBJ_HTTP_HEADER)
return TS_ERROR;
return TS_SUCCESS;
}
TSReturnCode
sdk_sanity_check_continuation(TSCont cont)
{
if ((cont == NULL) || (((INKContInternal *)cont)->m_free_magic == INKCONT_INTERN_MAGIC_DEAD))
return TS_ERROR;
return TS_SUCCESS;
}
TSReturnCode
sdk_sanity_check_fetch_sm(TSFetchSM fetch_sm)
{
if (fetch_sm == NULL)
return TS_ERROR;
return TS_SUCCESS;
}
TSReturnCode
sdk_sanity_check_http_ssn(TSHttpSsn ssnp)
{
if (ssnp == NULL)
return TS_ERROR;
return TS_SUCCESS;
}
TSReturnCode
sdk_sanity_check_txn(TSHttpTxn txnp)
{
if ((txnp != NULL) && (((HttpSM *)txnp)->magic == HTTP_SM_MAGIC_ALIVE))
return TS_SUCCESS;
return TS_ERROR;
}
TSReturnCode
sdk_sanity_check_mime_parser(TSMimeParser parser)
{
if (parser == NULL)
return TS_ERROR;
return TS_SUCCESS;
}
TSReturnCode
sdk_sanity_check_http_parser(TSHttpParser parser)
{
if (parser == NULL)
return TS_ERROR;
return TS_SUCCESS;
}
TSReturnCode
sdk_sanity_check_alt_info(TSHttpAltInfo info)
{
if (info == NULL)
return TS_ERROR;
return TS_SUCCESS;
}
TSReturnCode
sdk_sanity_check_hook_id(TSHttpHookID id)
{
return HttpAPIHooks::is_valid(id) ? TS_SUCCESS : TS_ERROR;
}
TSReturnCode
sdk_sanity_check_lifecycle_hook_id(TSLifecycleHookID id)
{
return LifecycleAPIHooks::is_valid(id) ? TS_SUCCESS : TS_ERROR;
}
TSReturnCode
sdk_sanity_check_ssl_hook_id(TSHttpHookID id)
{
if (id < TS_SSL_FIRST_HOOK || id > TS_SSL_LAST_HOOK)
return TS_ERROR;
return TS_SUCCESS;
}
TSReturnCode
sdk_sanity_check_null_ptr(void *ptr)
{
if (ptr == NULL)
return TS_ERROR;
return TS_SUCCESS;
}
/**
The function checks if the buffer is Modifiable and returns true if
it is modifiable, else returns false.
*/
bool
isWriteable(TSMBuffer bufp)
{
if (bufp != NULL) {
return ((HdrHeapSDKHandle *)bufp)->m_heap->m_writeable;
}
return false;
}
/******************************************************/
/* Allocators for field handles and standalone fields */
/******************************************************/
static MIMEFieldSDKHandle *
sdk_alloc_field_handle(TSMBuffer /* bufp ATS_UNUSED */, MIMEHdrImpl *mh)
{
MIMEFieldSDKHandle *handle = mHandleAllocator.alloc();
// TODO: Should remove this when memory allocation can't fail.
sdk_assert(sdk_sanity_check_null_ptr((void *)handle) == TS_SUCCESS);
obj_init_header(handle, HDR_HEAP_OBJ_FIELD_SDK_HANDLE, sizeof(MIMEFieldSDKHandle), 0);
handle->mh = mh;
return handle;
}
static void
sdk_free_field_handle(TSMBuffer bufp, MIMEFieldSDKHandle *field_handle)
{
if (sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS) {
mHandleAllocator.free(field_handle);
}
}
////////////////////////////////////////////////////////////////////
//
// FileImpl
//
////////////////////////////////////////////////////////////////////
FileImpl::FileImpl() : m_fd(-1), m_mode(CLOSED), m_buf(NULL), m_bufsize(0), m_bufpos(0)
{
}
FileImpl::~FileImpl()
{
fclose();
}
int
FileImpl::fopen(const char *filename, const char *mode)
{
if (mode[0] == '\0') {
return 0;
} else if (mode[0] == 'r') {
if (mode[1] != '\0') {
return 0;
}
m_mode = READ;
m_fd = open(filename, O_RDONLY);
} else if (mode[0] == 'w') {
if (mode[1] != '\0') {
return 0;
}
m_mode = WRITE;
m_fd = open(filename, O_WRONLY | O_CREAT, 0644);
} else if (mode[0] == 'a') {
if (mode[1] != '\0') {
return 0;
}
m_mode = WRITE;
m_fd = open(filename, O_WRONLY | O_CREAT | O_APPEND, 0644);
}
if (m_fd < 0) {
m_mode = CLOSED;
return 0;
} else {
return 1;
}
}
void
FileImpl::fclose()
{
if (m_fd != -1) {
fflush();
close(m_fd);
m_fd = -1;
m_mode = CLOSED;
}
if (m_buf) {
ats_free(m_buf);
m_buf = NULL;
m_bufsize = 0;
m_bufpos = 0;
}
}
int
FileImpl::fread(void *buf, int length)
{
int64_t amount;
int64_t err;
if ((m_mode != READ) || (m_fd == -1)) {
return -1;
}
if (!m_buf) {
m_bufpos = 0;
m_bufsize = 1024;
m_buf = (char *)ats_malloc(m_bufsize);
}
if (m_bufpos < length) {
amount = length;
if (amount < 1024) {
amount = 1024;
}
if (amount > (m_bufsize - m_bufpos)) {
while (amount > (m_bufsize - m_bufpos)) {
m_bufsize *= 2;
}
m_buf = (char *)ats_realloc(m_buf, m_bufsize);
}
do {
err = read(m_fd, &m_buf[m_bufpos], amount);
} while ((err < 0) && (errno == EINTR));
if (err < 0) {
return -1;
}
m_bufpos += err;
}
if (buf) {
amount = length;
if (amount > m_bufpos) {
amount = m_bufpos;
}
memcpy(buf, m_buf, amount);
memmove(m_buf, &m_buf[amount], m_bufpos - amount);
m_bufpos -= amount;
return amount;
} else {
return m_bufpos;
}
}
int
FileImpl::fwrite(const void *buf, int length)
{
const char *p, *e;
int64_t avail;
if ((m_mode != WRITE) || (m_fd == -1)) {
return -1;
}
if (!m_buf) {
m_bufpos = 0;
m_bufsize = 1024;
m_buf = (char *)ats_malloc(m_bufsize);
}
p = (const char *)buf;
e = p + length;
while (p != e) {
avail = m_bufsize - m_bufpos;
if (avail > length) {
avail = length;
}
memcpy(&m_buf[m_bufpos], p, avail);
m_bufpos += avail;
p += avail;
length -= avail;
if ((length > 0) && (m_bufpos > 0)) {
if (fflush() <= 0) {
break;
}
}
}
return (p - (const char *)buf);
}
int
FileImpl::fflush()
{
char *p, *e;
int err = 0;
if ((m_mode != WRITE) || (m_fd == -1)) {
return -1;
}
if (m_buf) {
p = m_buf;
e = &m_buf[m_bufpos];
while (p != e) {
do {
err = write(m_fd, p, e - p);
} while ((err < 0) && (errno == EINTR));
if (err < 0) {
break;
}
p += err;
}
err = p - m_buf;
memmove(m_buf, &m_buf[err], m_bufpos - err);
m_bufpos -= err;
}
return err;
}
char *
FileImpl::fgets(char *buf, int length)
{
char *e;
int pos;
if (length == 0) {
return NULL;
}
if (!m_buf || (m_bufpos < (length - 1))) {
pos = m_bufpos;
fread(NULL, length - 1);
if (!m_bufpos && (pos == m_bufpos)) {
return NULL;
}
}
e = (char *)memchr(m_buf, '\n', m_bufpos);
if (e) {
e += 1;
if (length > (e - m_buf + 1)) {
length = e - m_buf + 1;
}
}
pos = fread(buf, length - 1);
buf[pos] = '\0';
return buf;
}
////////////////////////////////////////////////////////////////////
//
// INKContInternal
//
////////////////////////////////////////////////////////////////////
INKContInternal::INKContInternal()
: DummyVConnection(NULL), mdata(NULL), m_event_func(NULL), m_event_count(0), m_closed(1), m_deletable(0), m_deleted(0),
m_free_magic(INKCONT_INTERN_MAGIC_ALIVE)
{
}
INKContInternal::INKContInternal(TSEventFunc funcp, TSMutex mutexp)
: DummyVConnection((ProxyMutex *)mutexp), mdata(NULL), m_event_func(funcp), m_event_count(0), m_closed(1), m_deletable(0),
m_deleted(0), m_free_magic(INKCONT_INTERN_MAGIC_ALIVE)
{
SET_HANDLER(&INKContInternal::handle_event);
}
void
INKContInternal::init(TSEventFunc funcp, TSMutex mutexp)
{
SET_HANDLER(&INKContInternal::handle_event);
mutex = (ProxyMutex *)mutexp;
m_event_func = funcp;
}
void
INKContInternal::destroy()
{
if (m_free_magic == INKCONT_INTERN_MAGIC_DEAD) {
ink_release_assert(!"Plugin tries to use a continuation which is deleted");
}
m_deleted = 1;
if (m_deletable) {
this->mutex = NULL;
m_free_magic = INKCONT_INTERN_MAGIC_DEAD;
INKContAllocator.free(this);
} else {
// TODO: Should this schedule on some other "thread" ?
// TODO: we don't care about the return action?
TSContSchedule((TSCont) this, 0, TS_THREAD_POOL_DEFAULT);
}
}
void
INKContInternal::handle_event_count(int event)
{
if ((event == EVENT_IMMEDIATE) || (event == EVENT_INTERVAL)) {
int val;
m_deletable = (m_closed != 0);
val = ink_atomic_increment((int *)&m_event_count, -1);
if (val <= 0) {
ink_assert(!"not reached");
}
m_deletable = m_deletable && (val == 1);
}
}
int
INKContInternal::handle_event(int event, void *edata)
{
if (m_free_magic == INKCONT_INTERN_MAGIC_DEAD) {
ink_release_assert(!"Plugin tries to use a continuation which is deleted");
}
handle_event_count(event);
if (m_deleted) {
if (m_deletable) {
this->mutex = NULL;
m_free_magic = INKCONT_INTERN_MAGIC_DEAD;
INKContAllocator.free(this);
}
} else {
return m_event_func((TSCont) this, (TSEvent)event, edata);
}
return EVENT_DONE;
}
////////////////////////////////////////////////////////////////////
//
// INKVConnInternal
//
////////////////////////////////////////////////////////////////////
INKVConnInternal::INKVConnInternal() : INKContInternal(), m_read_vio(), m_write_vio(), m_output_vc(NULL)
{
m_closed = 0;
}
INKVConnInternal::INKVConnInternal(TSEventFunc funcp, TSMutex mutexp)
: INKContInternal(funcp, mutexp), m_read_vio(), m_write_vio(), m_output_vc(NULL)
{
m_closed = 0;
SET_HANDLER(&INKVConnInternal::handle_event);
}
void
INKVConnInternal::init(TSEventFunc funcp, TSMutex mutexp)
{
INKContInternal::init(funcp, mutexp);
SET_HANDLER(&INKVConnInternal::handle_event);
}
void
INKVConnInternal::destroy()
{
m_deleted = 1;
if (m_deletable) {
this->mutex = NULL;
m_read_vio.set_continuation(NULL);
m_write_vio.set_continuation(NULL);
INKVConnAllocator.free(this);
}
}
int
INKVConnInternal::handle_event(int event, void *edata)
{
handle_event_count(event);
if (m_deleted) {
if (m_deletable) {
this->mutex = NULL;
m_read_vio.set_continuation(NULL);
m_write_vio.set_continuation(NULL);
INKVConnAllocator.free(this);
}
} else {
return m_event_func((TSCont) this, (TSEvent)event, edata);
}
return EVENT_DONE;
}
VIO *
INKVConnInternal::do_io_read(Continuation *c, int64_t nbytes, MIOBuffer *buf)
{
m_read_vio.buffer.writer_for(buf);
m_read_vio.op = VIO::READ;
m_read_vio.set_continuation(c);
m_read_vio.nbytes = nbytes;
m_read_vio.ndone = 0;
m_read_vio.vc_server = this;
if (ink_atomic_increment((int *)&m_event_count, 1) < 0) {
ink_assert(!"not reached");
}
eventProcessor.schedule_imm(this, ET_NET);
return &m_read_vio;
}
VIO *
INKVConnInternal::do_io_write(Continuation *c, int64_t nbytes, IOBufferReader *buf, bool owner)
{
ink_assert(!owner);
m_write_vio.buffer.reader_for(buf);
m_write_vio.op = VIO::WRITE;
m_write_vio.set_continuation(c);
m_write_vio.nbytes = nbytes;
m_write_vio.ndone = 0;
m_write_vio.vc_server = this;
if (m_write_vio.buffer.reader()->read_avail() > 0) {
if (ink_atomic_increment((int *)&m_event_count, 1) < 0) {
ink_assert(!"not reached");
}
eventProcessor.schedule_imm(this, ET_NET);
}
return &m_write_vio;
}
void
INKVConnInternal::do_io_transform(VConnection *vc)
{
m_output_vc = vc;
}
void
INKVConnInternal::do_io_close(int error)
{
if (ink_atomic_increment((int *)&m_event_count, 1) < 0) {
ink_assert(!"not reached");
}
INK_WRITE_MEMORY_BARRIER;
if (error != -1) {
lerrno = error;
m_closed = TS_VC_CLOSE_ABORT;
} else {
m_closed = TS_VC_CLOSE_NORMAL;
}
m_read_vio.op = VIO::NONE;
m_read_vio.buffer.clear();
m_write_vio.op = VIO::NONE;
m_write_vio.buffer.clear();
if (m_output_vc) {
m_output_vc->do_io_close(error);
}
eventProcessor.schedule_imm(this, ET_NET);
}
void
INKVConnInternal::do_io_shutdown(ShutdownHowTo_t howto)
{
if ((howto == IO_SHUTDOWN_READ) || (howto == IO_SHUTDOWN_READWRITE)) {
m_read_vio.op = VIO::NONE;
m_read_vio.buffer.clear();
}
if ((howto == IO_SHUTDOWN_WRITE) || (howto == IO_SHUTDOWN_READWRITE)) {
m_write_vio.op = VIO::NONE;
m_write_vio.buffer.clear();
}
if (ink_atomic_increment((int *)&m_event_count, 1) < 0) {
ink_assert(!"not reached");
}
eventProcessor.schedule_imm(this, ET_NET);
}
void
INKVConnInternal::reenable(VIO * /* vio ATS_UNUSED */)
{
if (ink_atomic_increment((int *)&m_event_count, 1) < 0) {
ink_assert(!"not reached");
}
eventProcessor.schedule_imm(this, ET_NET);
}
void
INKVConnInternal::retry(unsigned int delay)
{
if (ink_atomic_increment((int *)&m_event_count, 1) < 0) {
ink_assert(!"not reached");
}
mutex->thread_holding->schedule_in(this, HRTIME_MSECONDS(delay));
}
bool
INKVConnInternal::get_data(int id, void *data)
{
switch (id) {
case TS_API_DATA_READ_VIO:
*((TSVIO *)data) = reinterpret_cast<TSVIO>(&m_read_vio);
return true;
case TS_API_DATA_WRITE_VIO:
*((TSVIO *)data) = reinterpret_cast<TSVIO>(&m_write_vio);
return true;
case TS_API_DATA_OUTPUT_VC:
*((TSVConn *)data) = reinterpret_cast<TSVConn>(m_output_vc);
return true;
case TS_API_DATA_CLOSED:
*((int *)data) = m_closed;
return true;
default:
return INKContInternal::get_data(id, data);
}
}
bool
INKVConnInternal::set_data(int id, void *data)
{
switch (id) {
case TS_API_DATA_OUTPUT_VC:
m_output_vc = (VConnection *)data;
return true;
default:
return INKContInternal::set_data(id, data);
}
}
////////////////////////////////////////////////////////////////////
//
// APIHook, APIHooks, HttpAPIHooks
//
////////////////////////////////////////////////////////////////////
int
APIHook::invoke(int event, void *edata)
{
if ((event == EVENT_IMMEDIATE) || (event == EVENT_INTERVAL)) {
if (ink_atomic_increment((int *)&m_cont->m_event_count, 1) < 0) {
ink_assert(!"not reached");
}
}
return m_cont->handleEvent(event, edata);
}
APIHook *
APIHook::next() const
{
return m_link.next;
}
void
APIHooks::prepend(INKContInternal *cont)
{
APIHook *api_hook;
api_hook = apiHookAllocator.alloc();
api_hook->m_cont = cont;
m_hooks.push(api_hook);
}
void
APIHooks::append(INKContInternal *cont)
{
APIHook *api_hook;
api_hook = apiHookAllocator.alloc();
api_hook->m_cont = cont;
m_hooks.enqueue(api_hook);
}
APIHook *
APIHooks::get() const
{
return m_hooks.head;
}
void
APIHooks::clear()
{
APIHook *hook;
while (0 != (hook = m_hooks.pop())) {
apiHookAllocator.free(hook);
}
}
////////////////////////////////////////////////////////////////////
//
// ConfigUpdateCbTable
//
////////////////////////////////////////////////////////////////////
ConfigUpdateCbTable::ConfigUpdateCbTable()
{
cb_table = ink_hash_table_create(InkHashTableKeyType_String);
}
ConfigUpdateCbTable::~ConfigUpdateCbTable()
{
ink_assert(cb_table != NULL);
ink_hash_table_destroy(cb_table);
}
void
ConfigUpdateCbTable::insert(INKContInternal *contp, const char *name)
{
ink_assert(cb_table != NULL);
if (contp && name)
ink_hash_table_insert(cb_table, (InkHashTableKey)name, (InkHashTableValue)contp);
}
void
ConfigUpdateCbTable::invoke(const char *name)
{
ink_assert(cb_table != NULL);
InkHashTableIteratorState ht_iter;
InkHashTableEntry *ht_entry;
INKContInternal *contp;
if (name != NULL) {
if (strcmp(name, "*") == 0) {
ht_entry = ink_hash_table_iterator_first(cb_table, &ht_iter);
while (ht_entry != NULL) {
contp = (INKContInternal *)ink_hash_table_entry_value(cb_table, ht_entry);
ink_assert(contp != NULL);
invoke(contp);
ht_entry = ink_hash_table_iterator_next(cb_table, &ht_iter);
}
} else {
ht_entry = ink_hash_table_lookup_entry(cb_table, (InkHashTableKey)name);
if (ht_entry != NULL) {
contp = (INKContInternal *)ink_hash_table_entry_value(cb_table, ht_entry);
ink_assert(contp != NULL);
invoke(contp);
}
}
}
}
void
ConfigUpdateCbTable::invoke(INKContInternal *contp)
{
eventProcessor.schedule_imm(new ConfigUpdateCallback(contp), ET_TASK);
}
////////////////////////////////////////////////////////////////////
//
// api_init
//
////////////////////////////////////////////////////////////////////
void
api_init()
{
// HDR FIX ME
static int init = 1;
if (init) {
init = 0;
/* URL schemes */
TS_URL_SCHEME_FILE = URL_SCHEME_FILE;
TS_URL_SCHEME_FTP = URL_SCHEME_FTP;
TS_URL_SCHEME_GOPHER = URL_SCHEME_GOPHER;
TS_URL_SCHEME_HTTP = URL_SCHEME_HTTP;
TS_URL_SCHEME_HTTPS = URL_SCHEME_HTTPS;
TS_URL_SCHEME_MAILTO = URL_SCHEME_MAILTO;
TS_URL_SCHEME_NEWS = URL_SCHEME_NEWS;
TS_URL_SCHEME_NNTP = URL_SCHEME_NNTP;
TS_URL_SCHEME_PROSPERO = URL_SCHEME_PROSPERO;
TS_URL_SCHEME_TELNET = URL_SCHEME_TELNET;
TS_URL_SCHEME_WAIS = URL_SCHEME_WAIS;
TS_URL_LEN_FILE = URL_LEN_FILE;
TS_URL_LEN_FTP = URL_LEN_FTP;
TS_URL_LEN_GOPHER = URL_LEN_GOPHER;
TS_URL_LEN_HTTP = URL_LEN_HTTP;
TS_URL_LEN_HTTPS = URL_LEN_HTTPS;
TS_URL_LEN_MAILTO = URL_LEN_MAILTO;
TS_URL_LEN_NEWS = URL_LEN_NEWS;
TS_URL_LEN_NNTP = URL_LEN_NNTP;
TS_URL_LEN_PROSPERO = URL_LEN_PROSPERO;
TS_URL_LEN_TELNET = URL_LEN_TELNET;
TS_URL_LEN_WAIS = URL_LEN_WAIS;
/* MIME fields */
TS_MIME_FIELD_ACCEPT = MIME_FIELD_ACCEPT;
TS_MIME_FIELD_ACCEPT_CHARSET = MIME_FIELD_ACCEPT_CHARSET;
TS_MIME_FIELD_ACCEPT_ENCODING = MIME_FIELD_ACCEPT_ENCODING;
TS_MIME_FIELD_ACCEPT_LANGUAGE = MIME_FIELD_ACCEPT_LANGUAGE;
TS_MIME_FIELD_ACCEPT_RANGES = MIME_FIELD_ACCEPT_RANGES;
TS_MIME_FIELD_AGE = MIME_FIELD_AGE;
TS_MIME_FIELD_ALLOW = MIME_FIELD_ALLOW;
TS_MIME_FIELD_APPROVED = MIME_FIELD_APPROVED;
TS_MIME_FIELD_AUTHORIZATION = MIME_FIELD_AUTHORIZATION;
TS_MIME_FIELD_BYTES = MIME_FIELD_BYTES;
TS_MIME_FIELD_CACHE_CONTROL = MIME_FIELD_CACHE_CONTROL;
TS_MIME_FIELD_CLIENT_IP = MIME_FIELD_CLIENT_IP;
TS_MIME_FIELD_CONNECTION = MIME_FIELD_CONNECTION;
TS_MIME_FIELD_CONTENT_BASE = MIME_FIELD_CONTENT_BASE;
TS_MIME_FIELD_CONTENT_ENCODING = MIME_FIELD_CONTENT_ENCODING;
TS_MIME_FIELD_CONTENT_LANGUAGE = MIME_FIELD_CONTENT_LANGUAGE;
TS_MIME_FIELD_CONTENT_LENGTH = MIME_FIELD_CONTENT_LENGTH;
TS_MIME_FIELD_CONTENT_LOCATION = MIME_FIELD_CONTENT_LOCATION;
TS_MIME_FIELD_CONTENT_MD5 = MIME_FIELD_CONTENT_MD5;
TS_MIME_FIELD_CONTENT_RANGE = MIME_FIELD_CONTENT_RANGE;
TS_MIME_FIELD_CONTENT_TYPE = MIME_FIELD_CONTENT_TYPE;
TS_MIME_FIELD_CONTROL = MIME_FIELD_CONTROL;
TS_MIME_FIELD_COOKIE = MIME_FIELD_COOKIE;
TS_MIME_FIELD_DATE = MIME_FIELD_DATE;
TS_MIME_FIELD_DISTRIBUTION = MIME_FIELD_DISTRIBUTION;
TS_MIME_FIELD_ETAG = MIME_FIELD_ETAG;
TS_MIME_FIELD_EXPECT = MIME_FIELD_EXPECT;
TS_MIME_FIELD_EXPIRES = MIME_FIELD_EXPIRES;
TS_MIME_FIELD_FOLLOWUP_TO = MIME_FIELD_FOLLOWUP_TO;
TS_MIME_FIELD_FROM = MIME_FIELD_FROM;
TS_MIME_FIELD_HOST = MIME_FIELD_HOST;
TS_MIME_FIELD_IF_MATCH = MIME_FIELD_IF_MATCH;
TS_MIME_FIELD_IF_MODIFIED_SINCE = MIME_FIELD_IF_MODIFIED_SINCE;
TS_MIME_FIELD_IF_NONE_MATCH = MIME_FIELD_IF_NONE_MATCH;
TS_MIME_FIELD_IF_RANGE = MIME_FIELD_IF_RANGE;
TS_MIME_FIELD_IF_UNMODIFIED_SINCE = MIME_FIELD_IF_UNMODIFIED_SINCE;
TS_MIME_FIELD_KEEP_ALIVE = MIME_FIELD_KEEP_ALIVE;
TS_MIME_FIELD_KEYWORDS = MIME_FIELD_KEYWORDS;
TS_MIME_FIELD_LAST_MODIFIED = MIME_FIELD_LAST_MODIFIED;
TS_MIME_FIELD_LINES = MIME_FIELD_LINES;
TS_MIME_FIELD_LOCATION = MIME_FIELD_LOCATION;
TS_MIME_FIELD_MAX_FORWARDS = MIME_FIELD_MAX_FORWARDS;
TS_MIME_FIELD_MESSAGE_ID = MIME_FIELD_MESSAGE_ID;
TS_MIME_FIELD_NEWSGROUPS = MIME_FIELD_NEWSGROUPS;
TS_MIME_FIELD_ORGANIZATION = MIME_FIELD_ORGANIZATION;
TS_MIME_FIELD_PATH = MIME_FIELD_PATH;
TS_MIME_FIELD_PRAGMA = MIME_FIELD_PRAGMA;
TS_MIME_FIELD_PROXY_AUTHENTICATE = MIME_FIELD_PROXY_AUTHENTICATE;
TS_MIME_FIELD_PROXY_AUTHORIZATION = MIME_FIELD_PROXY_AUTHORIZATION;
TS_MIME_FIELD_PROXY_CONNECTION = MIME_FIELD_PROXY_CONNECTION;
TS_MIME_FIELD_PUBLIC = MIME_FIELD_PUBLIC;
TS_MIME_FIELD_RANGE = MIME_FIELD_RANGE;
TS_MIME_FIELD_REFERENCES = MIME_FIELD_REFERENCES;
TS_MIME_FIELD_REFERER = MIME_FIELD_REFERER;
TS_MIME_FIELD_REPLY_TO = MIME_FIELD_REPLY_TO;
TS_MIME_FIELD_RETRY_AFTER = MIME_FIELD_RETRY_AFTER;
TS_MIME_FIELD_SENDER = MIME_FIELD_SENDER;
TS_MIME_FIELD_SERVER = MIME_FIELD_SERVER;
TS_MIME_FIELD_SET_COOKIE = MIME_FIELD_SET_COOKIE;
TS_MIME_FIELD_STRICT_TRANSPORT_SECURITY = MIME_FIELD_STRICT_TRANSPORT_SECURITY;
TS_MIME_FIELD_SUBJECT = MIME_FIELD_SUBJECT;
TS_MIME_FIELD_SUMMARY = MIME_FIELD_SUMMARY;
TS_MIME_FIELD_TE = MIME_FIELD_TE;
TS_MIME_FIELD_TRANSFER_ENCODING = MIME_FIELD_TRANSFER_ENCODING;
TS_MIME_FIELD_UPGRADE = MIME_FIELD_UPGRADE;
TS_MIME_FIELD_USER_AGENT = MIME_FIELD_USER_AGENT;
TS_MIME_FIELD_VARY = MIME_FIELD_VARY;
TS_MIME_FIELD_VIA = MIME_FIELD_VIA;
TS_MIME_FIELD_WARNING = MIME_FIELD_WARNING;
TS_MIME_FIELD_WWW_AUTHENTICATE = MIME_FIELD_WWW_AUTHENTICATE;
TS_MIME_FIELD_XREF = MIME_FIELD_XREF;
TS_MIME_FIELD_X_FORWARDED_FOR = MIME_FIELD_X_FORWARDED_FOR;
TS_MIME_LEN_ACCEPT = MIME_LEN_ACCEPT;
TS_MIME_LEN_ACCEPT_CHARSET = MIME_LEN_ACCEPT_CHARSET;
TS_MIME_LEN_ACCEPT_ENCODING = MIME_LEN_ACCEPT_ENCODING;
TS_MIME_LEN_ACCEPT_LANGUAGE = MIME_LEN_ACCEPT_LANGUAGE;
TS_MIME_LEN_ACCEPT_RANGES = MIME_LEN_ACCEPT_RANGES;
TS_MIME_LEN_AGE = MIME_LEN_AGE;
TS_MIME_LEN_ALLOW = MIME_LEN_ALLOW;
TS_MIME_LEN_APPROVED = MIME_LEN_APPROVED;
TS_MIME_LEN_AUTHORIZATION = MIME_LEN_AUTHORIZATION;
TS_MIME_LEN_BYTES = MIME_LEN_BYTES;
TS_MIME_LEN_CACHE_CONTROL = MIME_LEN_CACHE_CONTROL;
TS_MIME_LEN_CLIENT_IP = MIME_LEN_CLIENT_IP;
TS_MIME_LEN_CONNECTION = MIME_LEN_CONNECTION;
TS_MIME_LEN_CONTENT_BASE = MIME_LEN_CONTENT_BASE;
TS_MIME_LEN_CONTENT_ENCODING = MIME_LEN_CONTENT_ENCODING;
TS_MIME_LEN_CONTENT_LANGUAGE = MIME_LEN_CONTENT_LANGUAGE;
TS_MIME_LEN_CONTENT_LENGTH = MIME_LEN_CONTENT_LENGTH;
TS_MIME_LEN_CONTENT_LOCATION = MIME_LEN_CONTENT_LOCATION;
TS_MIME_LEN_CONTENT_MD5 = MIME_LEN_CONTENT_MD5;
TS_MIME_LEN_CONTENT_RANGE = MIME_LEN_CONTENT_RANGE;
TS_MIME_LEN_CONTENT_TYPE = MIME_LEN_CONTENT_TYPE;
TS_MIME_LEN_CONTROL = MIME_LEN_CONTROL;
TS_MIME_LEN_COOKIE = MIME_LEN_COOKIE;
TS_MIME_LEN_DATE = MIME_LEN_DATE;
TS_MIME_LEN_DISTRIBUTION = MIME_LEN_DISTRIBUTION;
TS_MIME_LEN_ETAG = MIME_LEN_ETAG;
TS_MIME_LEN_EXPECT = MIME_LEN_EXPECT;
TS_MIME_LEN_EXPIRES = MIME_LEN_EXPIRES;
TS_MIME_LEN_FOLLOWUP_TO = MIME_LEN_FOLLOWUP_TO;
TS_MIME_LEN_FROM = MIME_LEN_FROM;
TS_MIME_LEN_HOST = MIME_LEN_HOST;
TS_MIME_LEN_IF_MATCH = MIME_LEN_IF_MATCH;
TS_MIME_LEN_IF_MODIFIED_SINCE = MIME_LEN_IF_MODIFIED_SINCE;
TS_MIME_LEN_IF_NONE_MATCH = MIME_LEN_IF_NONE_MATCH;
TS_MIME_LEN_IF_RANGE = MIME_LEN_IF_RANGE;
TS_MIME_LEN_IF_UNMODIFIED_SINCE = MIME_LEN_IF_UNMODIFIED_SINCE;
TS_MIME_LEN_KEEP_ALIVE = MIME_LEN_KEEP_ALIVE;
TS_MIME_LEN_KEYWORDS = MIME_LEN_KEYWORDS;
TS_MIME_LEN_LAST_MODIFIED = MIME_LEN_LAST_MODIFIED;
TS_MIME_LEN_LINES = MIME_LEN_LINES;
TS_MIME_LEN_LOCATION = MIME_LEN_LOCATION;
TS_MIME_LEN_MAX_FORWARDS = MIME_LEN_MAX_FORWARDS;
TS_MIME_LEN_MESSAGE_ID = MIME_LEN_MESSAGE_ID;
TS_MIME_LEN_NEWSGROUPS = MIME_LEN_NEWSGROUPS;
TS_MIME_LEN_ORGANIZATION = MIME_LEN_ORGANIZATION;
TS_MIME_LEN_PATH = MIME_LEN_PATH;
TS_MIME_LEN_PRAGMA = MIME_LEN_PRAGMA;
TS_MIME_LEN_PROXY_AUTHENTICATE = MIME_LEN_PROXY_AUTHENTICATE;
TS_MIME_LEN_PROXY_AUTHORIZATION = MIME_LEN_PROXY_AUTHORIZATION;
TS_MIME_LEN_PROXY_CONNECTION = MIME_LEN_PROXY_CONNECTION;
TS_MIME_LEN_PUBLIC = MIME_LEN_PUBLIC;
TS_MIME_LEN_RANGE = MIME_LEN_RANGE;
TS_MIME_LEN_REFERENCES = MIME_LEN_REFERENCES;
TS_MIME_LEN_REFERER = MIME_LEN_REFERER;
TS_MIME_LEN_REPLY_TO = MIME_LEN_REPLY_TO;
TS_MIME_LEN_RETRY_AFTER = MIME_LEN_RETRY_AFTER;
TS_MIME_LEN_SENDER = MIME_LEN_SENDER;
TS_MIME_LEN_SERVER = MIME_LEN_SERVER;
TS_MIME_LEN_SET_COOKIE = MIME_LEN_SET_COOKIE;
TS_MIME_LEN_STRICT_TRANSPORT_SECURITY = MIME_LEN_STRICT_TRANSPORT_SECURITY;
TS_MIME_LEN_SUBJECT = MIME_LEN_SUBJECT;
TS_MIME_LEN_SUMMARY = MIME_LEN_SUMMARY;
TS_MIME_LEN_TE = MIME_LEN_TE;
TS_MIME_LEN_TRANSFER_ENCODING = MIME_LEN_TRANSFER_ENCODING;
TS_MIME_LEN_UPGRADE = MIME_LEN_UPGRADE;
TS_MIME_LEN_USER_AGENT = MIME_LEN_USER_AGENT;
TS_MIME_LEN_VARY = MIME_LEN_VARY;
TS_MIME_LEN_VIA = MIME_LEN_VIA;
TS_MIME_LEN_WARNING = MIME_LEN_WARNING;
TS_MIME_LEN_WWW_AUTHENTICATE = MIME_LEN_WWW_AUTHENTICATE;
TS_MIME_LEN_XREF = MIME_LEN_XREF;
TS_MIME_LEN_X_FORWARDED_FOR = MIME_LEN_X_FORWARDED_FOR;
/* HTTP methods */
TS_HTTP_METHOD_CONNECT = HTTP_METHOD_CONNECT;
TS_HTTP_METHOD_DELETE = HTTP_METHOD_DELETE;
TS_HTTP_METHOD_GET = HTTP_METHOD_GET;
TS_HTTP_METHOD_HEAD = HTTP_METHOD_HEAD;
TS_HTTP_METHOD_ICP_QUERY = HTTP_METHOD_ICP_QUERY;
TS_HTTP_METHOD_OPTIONS = HTTP_METHOD_OPTIONS;
TS_HTTP_METHOD_POST = HTTP_METHOD_POST;
TS_HTTP_METHOD_PURGE = HTTP_METHOD_PURGE;
TS_HTTP_METHOD_PUT = HTTP_METHOD_PUT;
TS_HTTP_METHOD_TRACE = HTTP_METHOD_TRACE;
TS_HTTP_METHOD_PUSH = HTTP_METHOD_PUSH;
TS_HTTP_LEN_CONNECT = HTTP_LEN_CONNECT;
TS_HTTP_LEN_DELETE = HTTP_LEN_DELETE;
TS_HTTP_LEN_GET = HTTP_LEN_GET;
TS_HTTP_LEN_HEAD = HTTP_LEN_HEAD;
TS_HTTP_LEN_ICP_QUERY = HTTP_LEN_ICP_QUERY;
TS_HTTP_LEN_OPTIONS = HTTP_LEN_OPTIONS;
TS_HTTP_LEN_POST = HTTP_LEN_POST;
TS_HTTP_LEN_PURGE = HTTP_LEN_PURGE;
TS_HTTP_LEN_PUT = HTTP_LEN_PUT;
TS_HTTP_LEN_TRACE = HTTP_LEN_TRACE;
TS_HTTP_LEN_PUSH = HTTP_LEN_PUSH;
/* HTTP miscellaneous values */
TS_HTTP_VALUE_BYTES = HTTP_VALUE_BYTES;
TS_HTTP_VALUE_CHUNKED = HTTP_VALUE_CHUNKED;
TS_HTTP_VALUE_CLOSE = HTTP_VALUE_CLOSE;
TS_HTTP_VALUE_COMPRESS = HTTP_VALUE_COMPRESS;
TS_HTTP_VALUE_DEFLATE = HTTP_VALUE_DEFLATE;
TS_HTTP_VALUE_GZIP = HTTP_VALUE_GZIP;
TS_HTTP_VALUE_IDENTITY = HTTP_VALUE_IDENTITY;
TS_HTTP_VALUE_KEEP_ALIVE = HTTP_VALUE_KEEP_ALIVE;
TS_HTTP_VALUE_MAX_AGE = HTTP_VALUE_MAX_AGE;
TS_HTTP_VALUE_MAX_STALE = HTTP_VALUE_MAX_STALE;
TS_HTTP_VALUE_MIN_FRESH = HTTP_VALUE_MIN_FRESH;
TS_HTTP_VALUE_MUST_REVALIDATE = HTTP_VALUE_MUST_REVALIDATE;
TS_HTTP_VALUE_NONE = HTTP_VALUE_NONE;
TS_HTTP_VALUE_NO_CACHE = HTTP_VALUE_NO_CACHE;
TS_HTTP_VALUE_NO_STORE = HTTP_VALUE_NO_STORE;
TS_HTTP_VALUE_NO_TRANSFORM = HTTP_VALUE_NO_TRANSFORM;
TS_HTTP_VALUE_ONLY_IF_CACHED = HTTP_VALUE_ONLY_IF_CACHED;
TS_HTTP_VALUE_PRIVATE = HTTP_VALUE_PRIVATE;
TS_HTTP_VALUE_PROXY_REVALIDATE = HTTP_VALUE_PROXY_REVALIDATE;
TS_HTTP_VALUE_PUBLIC = HTTP_VALUE_PUBLIC;
TS_HTTP_VALUE_S_MAXAGE = HTTP_VALUE_S_MAXAGE;
TS_HTTP_LEN_BYTES = HTTP_LEN_BYTES;
TS_HTTP_LEN_CHUNKED = HTTP_LEN_CHUNKED;
TS_HTTP_LEN_CLOSE = HTTP_LEN_CLOSE;
TS_HTTP_LEN_COMPRESS = HTTP_LEN_COMPRESS;
TS_HTTP_LEN_DEFLATE = HTTP_LEN_DEFLATE;
TS_HTTP_LEN_GZIP = HTTP_LEN_GZIP;
TS_HTTP_LEN_IDENTITY = HTTP_LEN_IDENTITY;
TS_HTTP_LEN_KEEP_ALIVE = HTTP_LEN_KEEP_ALIVE;
TS_HTTP_LEN_MAX_AGE = HTTP_LEN_MAX_AGE;
TS_HTTP_LEN_MAX_STALE = HTTP_LEN_MAX_STALE;
TS_HTTP_LEN_MIN_FRESH = HTTP_LEN_MIN_FRESH;
TS_HTTP_LEN_MUST_REVALIDATE = HTTP_LEN_MUST_REVALIDATE;
TS_HTTP_LEN_NONE = HTTP_LEN_NONE;
TS_HTTP_LEN_NO_CACHE = HTTP_LEN_NO_CACHE;
TS_HTTP_LEN_NO_STORE = HTTP_LEN_NO_STORE;
TS_HTTP_LEN_NO_TRANSFORM = HTTP_LEN_NO_TRANSFORM;
TS_HTTP_LEN_ONLY_IF_CACHED = HTTP_LEN_ONLY_IF_CACHED;
TS_HTTP_LEN_PRIVATE = HTTP_LEN_PRIVATE;
TS_HTTP_LEN_PROXY_REVALIDATE = HTTP_LEN_PROXY_REVALIDATE;
TS_HTTP_LEN_PUBLIC = HTTP_LEN_PUBLIC;
TS_HTTP_LEN_S_MAXAGE = HTTP_LEN_S_MAXAGE;
http_global_hooks = new HttpAPIHooks;
ssl_hooks = new SslAPIHooks;
lifecycle_hooks = new LifecycleAPIHooks;
global_config_cbs = new ConfigUpdateCbTable;
if (TS_MAX_API_STATS > 0) {
api_rsb = RecAllocateRawStatBlock(TS_MAX_API_STATS);
if (NULL == api_rsb) {
Warning("Can't allocate API stats block");
} else {
Debug("sdk", "initialized SDK stats APIs with %d slots", TS_MAX_API_STATS);
}
} else {
api_rsb = NULL;
}
memset(state_arg_table, 0, sizeof(state_arg_table));
// Setup the version string for returning to plugins
ink_strlcpy(traffic_server_version, appVersionInfo.VersionStr, sizeof(traffic_server_version));
// Extract the elements.
// coverity[secure_coding]
if (sscanf(traffic_server_version, "%d.%d.%d", &ts_major_version, &ts_minor_version, &ts_patch_version) != 3) {
Warning("Unable to parse traffic server version string '%s'\n", traffic_server_version);
}
}
}
////////////////////////////////////////////////////////////////////
//
// API memory management
//
////////////////////////////////////////////////////////////////////
void *
_TSmalloc(size_t size, const char * /* path ATS_UNUSED */)
{
return ats_malloc(size);
}
void *
_TSrealloc(void *ptr, size_t size, const char * /* path ATS_UNUSED */)
{
return ats_realloc(ptr, size);
}
// length has to be int64_t and not size_t, since -1 means to call strlen() to get length
char *
_TSstrdup(const char *str, int64_t length, const char *path)
{
return _xstrdup(str, length, path);
}
size_t
_TSstrlcpy(char *dst, const char *str, size_t siz)
{
return ink_strlcpy(dst, str, siz);
}
size_t
_TSstrlcat(char *dst, const char *str, size_t siz)
{
return ink_strlcat(dst, str, siz);
}
void
_TSfree(void *ptr)
{
ats_free(ptr);
}
////////////////////////////////////////////////////////////////////
//
// Encoding utility
//
////////////////////////////////////////////////////////////////////
TSReturnCode
TSBase64Decode(const char *str, size_t str_len, unsigned char *dst, size_t dst_size, size_t *length)
{
sdk_assert(sdk_sanity_check_null_ptr((void *)str) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)dst) == TS_SUCCESS);
return ats_base64_decode(str, str_len, dst, dst_size, length) ? TS_SUCCESS : TS_ERROR;
}
TSReturnCode
TSBase64Encode(const char *str, size_t str_len, char *dst, size_t dst_size, size_t *length)
{
sdk_assert(sdk_sanity_check_null_ptr((void *)str) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)dst) == TS_SUCCESS);
return ats_base64_encode(str, str_len, dst, dst_size, length) ? TS_SUCCESS : TS_ERROR;
}
////////////////////////////////////////////////////////////////////
//
// API utility routines
//
////////////////////////////////////////////////////////////////////
unsigned int
TSrandom()
{
return this_ethread()->generator.random();
}
double
TSdrandom()
{
return this_ethread()->generator.drandom();
}
ink_hrtime
TShrtime()
{
return Thread::get_hrtime();
}
////////////////////////////////////////////////////////////////////
//
// API install and plugin locations
//
////////////////////////////////////////////////////////////////////
const char *
TSInstallDirGet(void)
{
return Layout::get()->prefix;
}
const char *
TSConfigDirGet(void)
{
static char *sysconfdir = NULL;
// This is not great, bit it's no worse than TSPluginDirGet :-/
if (sysconfdir == NULL) {
sysconfdir = RecConfigReadConfigDir();
}
return sysconfdir;
}
const char *
TSTrafficServerVersionGet(void)
{
return traffic_server_version;
}
int
TSTrafficServerVersionGetMajor()
{
return ts_major_version;
}
int
TSTrafficServerVersionGetMinor()
{
return ts_minor_version;
}
int
TSTrafficServerVersionGetPatch()
{
return ts_patch_version;
}
const char *
TSPluginDirGet(void)
{
static char path[PATH_NAME_MAX] = "";
if (*path == '\0') {
char *plugin_dir = RecConfigReadPrefixPath("proxy.config.plugin.plugin_dir");
ink_strlcpy(path, plugin_dir, sizeof(path));
ats_free(plugin_dir);
}
return path;
}
////////////////////////////////////////////////////////////////////
//
// Plugin registration
//
////////////////////////////////////////////////////////////////////
TSReturnCode
TSPluginRegister(TSPluginRegistrationInfo *plugin_info)
{
sdk_assert(sdk_sanity_check_null_ptr((void *)plugin_info) == TS_SUCCESS);
if (!plugin_reg_current) {
return TS_ERROR;
}
plugin_reg_current->plugin_registered = true;
if (plugin_info->plugin_name) {
plugin_reg_current->plugin_name = ats_strdup(plugin_info->plugin_name);
}
if (plugin_info->vendor_name) {
plugin_reg_current->vendor_name = ats_strdup(plugin_info->vendor_name);
}
if (plugin_info->support_email) {
plugin_reg_current->support_email = ats_strdup(plugin_info->support_email);
}
return TS_SUCCESS;
}
////////////////////////////////////////////////////////////////////
//
// API file management
//
////////////////////////////////////////////////////////////////////
TSFile
TSfopen(const char *filename, const char *mode)
{
FileImpl *file;
file = new FileImpl;
if (!file->fopen(filename, mode)) {
delete file;
return NULL;
}
return (TSFile)file;
}
void
TSfclose(TSFile filep)
{
FileImpl *file = (FileImpl *)filep;
file->fclose();
delete file;
}
size_t
TSfread(TSFile filep, void *buf, size_t length)
{
FileImpl *file = (FileImpl *)filep;
return file->fread(buf, length);
}
size_t
TSfwrite(TSFile filep, const void *buf, size_t length)
{
FileImpl *file = (FileImpl *)filep;
return file->fwrite(buf, length);
}
void
TSfflush(TSFile filep)
{
FileImpl *file = (FileImpl *)filep;
file->fflush();
}
char *
TSfgets(TSFile filep, char *buf, size_t length)
{
FileImpl *file = (FileImpl *)filep;
return file->fgets(buf, length);
}
////////////////////////////////////////////////////////////////////
//
// Header component object handles
//
////////////////////////////////////////////////////////////////////
TSReturnCode
TSHandleMLocRelease(TSMBuffer bufp, TSMLoc parent, TSMLoc mloc)
{
MIMEFieldSDKHandle *field_handle;
HdrHeapObjImpl *obj = (HdrHeapObjImpl *)mloc;
if (mloc == TS_NULL_MLOC)
return TS_SUCCESS;
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
switch (obj->m_type) {
case HDR_HEAP_OBJ_URL:
case HDR_HEAP_OBJ_HTTP_HEADER:
case HDR_HEAP_OBJ_MIME_HEADER:
return TS_SUCCESS;
case HDR_HEAP_OBJ_FIELD_SDK_HANDLE:
field_handle = (MIMEFieldSDKHandle *)obj;
if (sdk_sanity_check_field_handle(mloc, parent) != TS_SUCCESS)
return TS_ERROR;
sdk_free_field_handle(bufp, field_handle);
return TS_SUCCESS;
default:
ink_release_assert(!"invalid mloc");
return TS_ERROR;
}
}
////////////////////////////////////////////////////////////////////
//
// HdrHeaps (previously known as "Marshal Buffers")
//
////////////////////////////////////////////////////////////////////
// TSMBuffer: pointers to HdrHeapSDKHandle objects
TSMBuffer
TSMBufferCreate(void)
{
TSMBuffer bufp;
HdrHeapSDKHandle *new_heap = new HdrHeapSDKHandle;
new_heap->m_heap = new_HdrHeap();
bufp = (TSMBuffer)new_heap;
// TODO: Should remove this when memory allocation is guaranteed to fail.
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
return bufp;
}
TSReturnCode
TSMBufferDestroy(TSMBuffer bufp)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR. If allowed, return TS_SUCCESS. Changed the
// return value of function from void to TSReturnCode.
if (!isWriteable(bufp))
return TS_ERROR;
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
HdrHeapSDKHandle *sdk_heap = (HdrHeapSDKHandle *)bufp;
sdk_heap->m_heap->destroy();
delete sdk_heap;
return TS_SUCCESS;
}
////////////////////////////////////////////////////////////////////
//
// URLs
//
////////////////////////////////////////////////////////////////////
// TSMBuffer: pointers to HdrHeapSDKHandle objects
// TSMLoc: pointers to URLImpl objects
TSReturnCode
TSUrlCreate(TSMBuffer bufp, TSMLoc *locp)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr(locp) == TS_SUCCESS);
if (isWriteable(bufp)) {
HdrHeap *heap = ((HdrHeapSDKHandle *)bufp)->m_heap;
*locp = (TSMLoc)url_create(heap);
return TS_SUCCESS;
}
return TS_ERROR;
}
TSReturnCode TSUrlDestroy(TSMBuffer /* bufp ATS_UNUSED */, TSMLoc /* url_loc ATS_UNUSED */)
{
return TS_SUCCESS;
}
TSReturnCode
TSUrlClone(TSMBuffer dest_bufp, TSMBuffer src_bufp, TSMLoc src_url, TSMLoc *locp)
{
sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_url_handle(src_url) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr(locp) == TS_SUCCESS);
if (!isWriteable(dest_bufp))
return TS_ERROR;
HdrHeap *s_heap, *d_heap;
URLImpl *s_url, *d_url;
s_heap = ((HdrHeapSDKHandle *)src_bufp)->m_heap;
d_heap = ((HdrHeapSDKHandle *)dest_bufp)->m_heap;
s_url = (URLImpl *)src_url;
d_url = url_copy(s_url, s_heap, d_heap, (s_heap != d_heap));
*locp = (TSMLoc)d_url;
return TS_SUCCESS;
}
TSReturnCode
TSUrlCopy(TSMBuffer dest_bufp, TSMLoc dest_obj, TSMBuffer src_bufp, TSMLoc src_obj)
{
sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_url_handle(src_obj) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_url_handle(dest_obj) == TS_SUCCESS);
if (!isWriteable(dest_bufp))
return TS_ERROR;
HdrHeap *s_heap, *d_heap;
URLImpl *s_url, *d_url;
s_heap = ((HdrHeapSDKHandle *)src_bufp)->m_heap;
d_heap = ((HdrHeapSDKHandle *)dest_bufp)->m_heap;
s_url = (URLImpl *)src_obj;
d_url = (URLImpl *)dest_obj;
url_copy_onto(s_url, s_heap, d_url, d_heap, (s_heap != d_heap));
return TS_SUCCESS;
}
void
TSUrlPrint(TSMBuffer bufp, TSMLoc obj, TSIOBuffer iobufp)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_iocore_structure(iobufp) == TS_SUCCESS);
MIOBuffer *b = (MIOBuffer *)iobufp;
IOBufferBlock *blk;
int bufindex;
int tmp, dumpoffset;
int done;
URL u;
u.m_heap = ((HdrHeapSDKHandle *)bufp)->m_heap;
u.m_url_impl = (URLImpl *)obj;
dumpoffset = 0;
do {
blk = b->get_current_block();
if (!blk || blk->write_avail() == 0) {
b->add_block();
blk = b->get_current_block();
}
bufindex = 0;
tmp = dumpoffset;
done = u.print(blk->end(), blk->write_avail(), &bufindex, &tmp);
dumpoffset += bufindex;
b->fill(bufindex);
} while (!done);
}
TSParseResult
TSUrlParse(TSMBuffer bufp, TSMLoc obj, const char **start, const char *end)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)start) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)*start) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)end) == TS_SUCCESS);
if (!isWriteable(bufp))
return TS_PARSE_ERROR;
URL u;
u.m_heap = ((HdrHeapSDKHandle *)bufp)->m_heap;
u.m_url_impl = (URLImpl *)obj;
url_clear(u.m_url_impl);
return (TSParseResult)u.parse(start, end);
}
int
TSUrlLengthGet(TSMBuffer bufp, TSMLoc obj)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
URLImpl *url_impl = (URLImpl *)obj;
return url_length_get(url_impl);
}
char *
TSUrlStringGet(TSMBuffer bufp, TSMLoc obj, int *length)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)length) == TS_SUCCESS);
URLImpl *url_impl = (URLImpl *)obj;
return url_string_get(url_impl, NULL, length, NULL);
}
typedef const char *(URL::*URLPartGetF)(int *length);
typedef void (URL::*URLPartSetF)(const char *value, int length);
static const char *
URLPartGet(TSMBuffer bufp, TSMLoc obj, int *length, URLPartGetF url_f)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)length) == TS_SUCCESS);
URL u;
u.m_heap = ((HdrHeapSDKHandle *)bufp)->m_heap;
u.m_url_impl = (URLImpl *)obj;
return (u.*url_f)(length);
}
static TSReturnCode
URLPartSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length, URLPartSetF url_f)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
if (!isWriteable(bufp))
return TS_ERROR;
URL u;
u.m_heap = ((HdrHeapSDKHandle *)bufp)->m_heap;
u.m_url_impl = (URLImpl *)obj;
if (!value)
length = 0;
else if (length < 0)
length = strlen(value);
(u.*url_f)(value, length);
return TS_SUCCESS;
}
const char *
TSUrlSchemeGet(TSMBuffer bufp, TSMLoc obj, int *length)
{
return URLPartGet(bufp, obj, length, &URL::scheme_get);
}
TSReturnCode
TSUrlSchemeSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
{
return URLPartSet(bufp, obj, value, length, &URL::scheme_set);
}
/* Internet specific URLs */
const char *
TSUrlUserGet(TSMBuffer bufp, TSMLoc obj, int *length)
{
return URLPartGet(bufp, obj, length, &URL::user_get);
}
TSReturnCode
TSUrlUserSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
{
return URLPartSet(bufp, obj, value, length, &URL::user_set);
}
const char *
TSUrlPasswordGet(TSMBuffer bufp, TSMLoc obj, int *length)
{
return URLPartGet(bufp, obj, length, &URL::password_get);
}
TSReturnCode
TSUrlPasswordSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
{
return URLPartSet(bufp, obj, value, length, &URL::password_set);
}
const char *
TSUrlHostGet(TSMBuffer bufp, TSMLoc obj, int *length)
{
return URLPartGet(bufp, obj, length, &URL::host_get);
}
TSReturnCode
TSUrlHostSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
{
return URLPartSet(bufp, obj, value, length, &URL::host_set);
}
int
TSUrlPortGet(TSMBuffer bufp, TSMLoc obj)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
URL u;
u.m_heap = ((HdrHeapSDKHandle *)bufp)->m_heap;
u.m_url_impl = (URLImpl *)obj;
return u.port_get();
}
TSReturnCode
TSUrlPortSet(TSMBuffer bufp, TSMLoc obj, int port)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
if (!isWriteable(bufp) || (port < 0))
return TS_ERROR;
URL u;
u.m_heap = ((HdrHeapSDKHandle *)bufp)->m_heap;
u.m_url_impl = (URLImpl *)obj;
u.port_set(port);
return TS_SUCCESS;
}
/* FTP and HTTP specific URLs */
const char *
TSUrlPathGet(TSMBuffer bufp, TSMLoc obj, int *length)
{
return URLPartGet(bufp, obj, length, &URL::path_get);
}
TSReturnCode
TSUrlPathSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
{
return URLPartSet(bufp, obj, value, length, &URL::path_set);
}
/* FTP specific URLs */
int
TSUrlFtpTypeGet(TSMBuffer bufp, TSMLoc obj)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
URL u;
u.m_heap = ((HdrHeapSDKHandle *)bufp)->m_heap;
u.m_url_impl = (URLImpl *)obj;
return u.type_get();
}
TSReturnCode
TSUrlFtpTypeSet(TSMBuffer bufp, TSMLoc obj, int type)
{
// The valid values are : 0, 65('A'), 97('a'),
// 69('E'), 101('e'), 73 ('I') and 105('i').
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
if ((type == 0 || type == 'A' || type == 'E' || type == 'I' || type == 'a' || type == 'i' || type == 'e') && isWriteable(bufp)) {
URL u;
u.m_heap = ((HdrHeapSDKHandle *)bufp)->m_heap;
u.m_url_impl = (URLImpl *)obj;
u.type_set(type);
return TS_SUCCESS;
}
return TS_ERROR;
}
/* HTTP specific URLs */
const char *
TSUrlHttpParamsGet(TSMBuffer bufp, TSMLoc obj, int *length)
{
return URLPartGet(bufp, obj, length, &URL::params_get);
}
TSReturnCode
TSUrlHttpParamsSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
{
return URLPartSet(bufp, obj, value, length, &URL::params_set);
}
const char *
TSUrlHttpQueryGet(TSMBuffer bufp, TSMLoc obj, int *length)
{
return URLPartGet(bufp, obj, length, &URL::query_get);
}
TSReturnCode
TSUrlHttpQuerySet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
{
return URLPartSet(bufp, obj, value, length, &URL::query_set);
}
const char *
TSUrlHttpFragmentGet(TSMBuffer bufp, TSMLoc obj, int *length)
{
return URLPartGet(bufp, obj, length, &URL::fragment_get);
}
TSReturnCode
TSUrlHttpFragmentSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
{
return URLPartSet(bufp, obj, value, length, &URL::fragment_set);
}
// URL percent encoding
TSReturnCode
TSStringPercentEncode(const char *str, int str_len, char *dst, size_t dst_size, size_t *length, const unsigned char *map)
{
sdk_assert(sdk_sanity_check_null_ptr((void *)str) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)dst) == TS_SUCCESS);
int new_len; // Unfortunately, a lot of the core uses "int" for length's internally...
if (str_len < 0)
str_len = strlen(str);
sdk_assert(str_len < static_cast<int>(dst_size));
// TODO: Perhaps we should make escapify_url() deal with const properly...
if (NULL == LogUtils::escapify_url(NULL, const_cast<char *>(str), str_len, &new_len, dst, dst_size, map)) {
if (length)
*length = 0;
return TS_ERROR;
}
if (length)
*length = new_len;
return TS_SUCCESS;
}
TSReturnCode
TSStringPercentDecode(const char *str, size_t str_len, char *dst, size_t dst_size, size_t *length)
{
sdk_assert(sdk_sanity_check_null_ptr((void *)str) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)dst) == TS_SUCCESS);
if (0 == str_len)
str_len = strlen(str);
// return unescapifyStr(str);
char *buffer = dst;
const char *src = str;
int s = 0; // State, which we don't really use
// TODO: We should check for "failures" here?
unescape_str(buffer, buffer + dst_size, src, src + str_len, s);
*buffer = '\0';
if (length)
*length = (buffer - dst);
return TS_SUCCESS;
}
TSReturnCode
TSUrlPercentEncode(TSMBuffer bufp, TSMLoc obj, char *dst, size_t dst_size, size_t *length, const unsigned char *map)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
char *url;
int url_len;
TSReturnCode ret;
URLImpl *url_impl = (URLImpl *)obj;
// TODO: at some point, it might be nice to allow this to write to a pre-allocated buffer
url = url_string_get(url_impl, NULL, &url_len, NULL);
ret = TSStringPercentEncode(url, url_len, dst, dst_size, length, map);
ats_free(url);
return ret;
}
////////////////////////////////////////////////////////////////////
//
// MIME Headers
//
////////////////////////////////////////////////////////////////////
/**************/
/* MimeParser */
/**************/
TSMimeParser
TSMimeParserCreate(void)
{
TSMimeParser parser = reinterpret_cast<TSMimeParser>(ats_malloc(sizeof(MIMEParser)));
mime_parser_init((MIMEParser *)parser);
return parser;
}
void
TSMimeParserClear(TSMimeParser parser)
{
sdk_assert(sdk_sanity_check_mime_parser(parser) == TS_SUCCESS);
mime_parser_clear((MIMEParser *)parser);
}
void
TSMimeParserDestroy(TSMimeParser parser)
{
sdk_assert(sdk_sanity_check_mime_parser(parser) == TS_SUCCESS);
mime_parser_clear((MIMEParser *)parser);
ats_free(parser);
}
/***********/
/* MimeHdr */
/***********/
// TSMBuffer: pointers to HdrHeapSDKHandle objects
// TSMLoc: pointers to MIMEFieldSDKHandle objects
TSReturnCode
TSMimeHdrCreate(TSMBuffer bufp, TSMLoc *locp)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR. If not allowed, return NULL.
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)locp) == TS_SUCCESS);
if (!isWriteable(bufp))
return TS_ERROR;
*locp = reinterpret_cast<TSMLoc>(mime_hdr_create(((HdrHeapSDKHandle *)bufp)->m_heap));
return TS_SUCCESS;
}
TSReturnCode
TSMimeHdrDestroy(TSMBuffer bufp, TSMLoc obj)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR. If allowed, return TS_SUCCESS. Changed the
// return value of function from void to TSReturnCode.
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(obj) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS));
if (!isWriteable(bufp))
return TS_ERROR;
MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(obj);
mime_hdr_destroy(((HdrHeapSDKHandle *)bufp)->m_heap, mh);
return TS_SUCCESS;
}
TSReturnCode
TSMimeHdrClone(TSMBuffer dest_bufp, TSMBuffer src_bufp, TSMLoc src_hdr, TSMLoc *locp)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR. If not allowed, return NULL.
sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_mime_hdr_handle(src_hdr) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_http_hdr_handle(src_hdr) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)locp) == TS_SUCCESS);
if (!isWriteable(dest_bufp))
return TS_ERROR;
HdrHeap *s_heap, *d_heap;
MIMEHdrImpl *s_mh, *d_mh;
s_heap = ((HdrHeapSDKHandle *)src_bufp)->m_heap;
d_heap = ((HdrHeapSDKHandle *)dest_bufp)->m_heap;
s_mh = _hdr_mloc_to_mime_hdr_impl(src_hdr);
d_mh = mime_hdr_clone(s_mh, s_heap, d_heap, (s_heap != d_heap));
*locp = (TSMLoc)d_mh;
return TS_SUCCESS;
}
TSReturnCode
TSMimeHdrCopy(TSMBuffer dest_bufp, TSMLoc dest_obj, TSMBuffer src_bufp, TSMLoc src_obj)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR. If allowed, return TS_SUCCESS. Changed the
// return value of function from void to TSReturnCode.
sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(src_obj) == TS_SUCCESS) ||
(sdk_sanity_check_http_hdr_handle(src_obj) == TS_SUCCESS));
sdk_assert((sdk_sanity_check_mime_hdr_handle(dest_obj) == TS_SUCCESS) ||
(sdk_sanity_check_http_hdr_handle(dest_obj) == TS_SUCCESS));
if (!isWriteable(dest_bufp))
return TS_ERROR;
HdrHeap *s_heap, *d_heap;
MIMEHdrImpl *s_mh, *d_mh;
s_heap = ((HdrHeapSDKHandle *)src_bufp)->m_heap;
d_heap = ((HdrHeapSDKHandle *)dest_bufp)->m_heap;
s_mh = _hdr_mloc_to_mime_hdr_impl(src_obj);
d_mh = _hdr_mloc_to_mime_hdr_impl(dest_obj);
mime_hdr_fields_clear(d_heap, d_mh);
mime_hdr_copy_onto(s_mh, s_heap, d_mh, d_heap, (s_heap != d_heap));
return TS_SUCCESS;
}
void
TSMimeHdrPrint(TSMBuffer bufp, TSMLoc obj, TSIOBuffer iobufp)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(obj) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_iocore_structure(iobufp) == TS_SUCCESS);
HdrHeap *heap = ((HdrHeapSDKHandle *)bufp)->m_heap;
MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(obj);
MIOBuffer *b = (MIOBuffer *)iobufp;
IOBufferBlock *blk;
int bufindex;
int tmp, dumpoffset = 0;
int done;
do {
blk = b->get_current_block();
if (!blk || blk->write_avail() == 0) {
b->add_block();
blk = b->get_current_block();
}
bufindex = 0;
tmp = dumpoffset;
done = mime_hdr_print(heap, mh, blk->end(), blk->write_avail(), &bufindex, &tmp);
dumpoffset += bufindex;
b->fill(bufindex);
} while (!done);
}
TSParseResult
TSMimeHdrParse(TSMimeParser parser, TSMBuffer bufp, TSMLoc obj, const char **start, const char *end)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(obj) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_null_ptr((void *)start) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)*start) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)end) == TS_SUCCESS);
if (!isWriteable(bufp))
return TS_PARSE_ERROR;
MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(obj);
return (TSParseResult)mime_parser_parse((MIMEParser *)parser, ((HdrHeapSDKHandle *)bufp)->m_heap, mh, start, end, false, false);
}
int
TSMimeHdrLengthGet(TSMBuffer bufp, TSMLoc obj)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(obj) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS));
MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(obj);
return mime_hdr_length_get(mh);
}
TSReturnCode
TSMimeHdrFieldsClear(TSMBuffer bufp, TSMLoc obj)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(obj) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS));
if (!isWriteable(bufp))
return TS_ERROR;
MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(obj);
mime_hdr_fields_clear(((HdrHeapSDKHandle *)bufp)->m_heap, mh);
return TS_SUCCESS;
}
int
TSMimeHdrFieldsCount(TSMBuffer bufp, TSMLoc obj)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(obj) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS));
MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(obj);
return mime_hdr_fields_count(mh);
}
// The following three helper functions should not be used in plugins! Since they are not used
// by plugins, there's no need to validate the input.
const char *
TSMimeFieldValueGet(TSMBuffer /* bufp ATS_UNUSED */, TSMLoc field_obj, int idx, int *value_len_ptr)
{
MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *)field_obj;
if (idx >= 0) {
return mime_field_value_get_comma_val(handle->field_ptr, value_len_ptr, idx);
} else {
return mime_field_value_get(handle->field_ptr, value_len_ptr);
}
}
void
TSMimeFieldValueSet(TSMBuffer bufp, TSMLoc field_obj, int idx, const char *value, int length)
{
MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *)field_obj;
HdrHeap *heap = ((HdrHeapSDKHandle *)bufp)->m_heap;
if (length == -1)
length = strlen(value);
if (idx >= 0)
mime_field_value_set_comma_val(heap, handle->mh, handle->field_ptr, idx, value, length);
else
mime_field_value_set(heap, handle->mh, handle->field_ptr, value, length, true);
}
void
TSMimeFieldValueInsert(TSMBuffer bufp, TSMLoc field_obj, const char *value, int length, int idx)
{
MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *)field_obj;
HdrHeap *heap = ((HdrHeapSDKHandle *)bufp)->m_heap;
if (length == -1)
length = strlen(value);
mime_field_value_insert_comma_val(heap, handle->mh, handle->field_ptr, idx, value, length);
}
/****************/
/* MimeHdrField */
/****************/
// TSMBuffer: pointers to HdrHeapSDKHandle objects
// TSMLoc: pointers to MIMEFieldSDKHandle objects
int
TSMimeHdrFieldEqual(TSMBuffer bufp, TSMLoc hdr_obj, TSMLoc field1_obj, TSMLoc field2_obj)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_field_handle(field1_obj, hdr_obj) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_field_handle(field2_obj, hdr_obj) == TS_SUCCESS);
MIMEFieldSDKHandle *field1_handle = (MIMEFieldSDKHandle *)field1_obj;
MIMEFieldSDKHandle *field2_handle = (MIMEFieldSDKHandle *)field2_obj;
if ((field1_handle == NULL) || (field2_handle == NULL))
return (field1_handle == field2_handle);
return (field1_handle->field_ptr == field2_handle->field_ptr);
}
TSMLoc
TSMimeHdrFieldGet(TSMBuffer bufp, TSMLoc hdr_obj, int idx)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr_obj) == TS_SUCCESS) ||
(sdk_sanity_check_http_hdr_handle(hdr_obj) == TS_SUCCESS));
sdk_assert(idx >= 0);
MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(hdr_obj);
MIMEField *f = mime_hdr_field_get(mh, idx);
if (f == NULL)
return TS_NULL_MLOC;
MIMEFieldSDKHandle *h = sdk_alloc_field_handle(bufp, mh);
h->field_ptr = f;
return reinterpret_cast<TSMLoc>(h);
}
TSMLoc
TSMimeHdrFieldFind(TSMBuffer bufp, TSMLoc hdr_obj, const char *name, int length)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr_obj) == TS_SUCCESS) ||
(sdk_sanity_check_http_hdr_handle(hdr_obj) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_null_ptr((void *)name) == TS_SUCCESS);
if (length == -1)
length = strlen(name);
MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(hdr_obj);
MIMEField *f = mime_hdr_field_find(mh, name, length);
if (f == NULL)
return TS_NULL_MLOC;
MIMEFieldSDKHandle *h = sdk_alloc_field_handle(bufp, mh);
h->field_ptr = f;
return reinterpret_cast<TSMLoc>(h);
}
TSReturnCode
TSMimeHdrFieldAppend(TSMBuffer bufp, TSMLoc mh_mloc, TSMLoc field_mloc)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR. If allowed, return TS_SUCCESS. Changed the
// return value of function from void to TSReturnCode.
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(mh_mloc) == TS_SUCCESS) ||
(sdk_sanity_check_http_hdr_handle(mh_mloc) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_field_handle(field_mloc) == TS_SUCCESS);
if (!isWriteable(bufp))
return TS_ERROR;
MIMEField *mh_field;
MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(mh_mloc);
MIMEFieldSDKHandle *field_handle = (MIMEFieldSDKHandle *)field_mloc;
//////////////////////////////////////////////////////////////////////
// The field passed in field_mloc might have been allocated from //
// inside a MIME header (the correct way), or it might have been //
// created in isolation as a "standalone field" (the old way). //
// //
// If it's a standalone field (the associated mime header is NULL), //
// then we need to now allocate a real field inside the header, //
// copy over the data, and convert the standalone field into a //
// forwarding pointer to the real field, in case it's used again //
//////////////////////////////////////////////////////////////////////
if (field_handle->mh == NULL) {
HdrHeap *heap = (HdrHeap *)(((HdrHeapSDKHandle *)bufp)->m_heap);
// allocate a new hdr field and copy any pre-set info
mh_field = mime_field_create(heap, mh);
// FIX: is it safe to copy everything over?
memcpy(mh_field, field_handle->field_ptr, sizeof(MIMEField));
// now set up the forwarding ptr from standalone field to hdr field
field_handle->mh = mh;
field_handle->field_ptr = mh_field;
}
ink_assert(field_handle->mh == mh);
ink_assert(field_handle->field_ptr->m_ptr_name);
mime_hdr_field_attach(mh, field_handle->field_ptr, 1, NULL);
return TS_SUCCESS;
}
TSReturnCode
TSMimeHdrFieldRemove(TSMBuffer bufp, TSMLoc mh_mloc, TSMLoc field_mloc)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR. If allowed, return TS_SUCCESS. Changed the
// return value of function from void to TSReturnCode.
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(mh_mloc) == TS_SUCCESS) ||
(sdk_sanity_check_http_hdr_handle(mh_mloc) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_field_handle(field_mloc, mh_mloc) == TS_SUCCESS);
if (!isWriteable(bufp))
return TS_ERROR;
MIMEFieldSDKHandle *field_handle = (MIMEFieldSDKHandle *)field_mloc;
if (field_handle->mh != NULL) {
MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(mh_mloc);
ink_assert(mh == field_handle->mh);
sdk_sanity_check_field_handle(field_mloc, mh_mloc);
mime_hdr_field_detach(mh, field_handle->field_ptr, false); // only detach this dup
}
return TS_SUCCESS;
}
TSReturnCode
TSMimeHdrFieldDestroy(TSMBuffer bufp, TSMLoc mh_mloc, TSMLoc field_mloc)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR. If allowed, return TS_SUCCESS. Changed the
// return value of function from void to TSReturnCode.
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(mh_mloc) == TS_SUCCESS) ||
(sdk_sanity_check_http_hdr_handle(mh_mloc) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_field_handle(field_mloc, mh_mloc) == TS_SUCCESS);
if (!isWriteable(bufp))
return TS_ERROR;
MIMEFieldSDKHandle *field_handle = (MIMEFieldSDKHandle *)field_mloc;
if (field_handle->mh == NULL) { // NOT SUPPORTED!!
ink_release_assert(!"Failed MH");
} else {
MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(mh_mloc);
HdrHeap *heap = (HdrHeap *)(((HdrHeapSDKHandle *)bufp)->m_heap);
ink_assert(mh == field_handle->mh);
if (sdk_sanity_check_field_handle(field_mloc, mh_mloc) != TS_SUCCESS)
return TS_ERROR;
// detach and delete this field, but not all dups
mime_hdr_field_delete(heap, mh, field_handle->field_ptr, false);
}
// for consistence, the handle will not be released here.
// users will be required to do it.
return TS_SUCCESS;
}
TSReturnCode
TSMimeHdrFieldCreate(TSMBuffer bufp, TSMLoc mh_mloc, TSMLoc *locp)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR. If not allowed, return NULL.
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(mh_mloc) == TS_SUCCESS) ||
(sdk_sanity_check_http_hdr_handle(mh_mloc) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_null_ptr((void *)locp) == TS_SUCCESS);
if (!isWriteable(bufp))
return TS_ERROR;
MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(mh_mloc);
HdrHeap *heap = (HdrHeap *)(((HdrHeapSDKHandle *)bufp)->m_heap);
MIMEFieldSDKHandle *h = sdk_alloc_field_handle(bufp, mh);
h->field_ptr = mime_field_create(heap, mh);
*locp = reinterpret_cast<TSMLoc>(h);
return TS_SUCCESS;
}
TSReturnCode
TSMimeHdrFieldCreateNamed(TSMBuffer bufp, TSMLoc mh_mloc, const char *name, int name_len, TSMLoc *locp)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(mh_mloc) == TS_SUCCESS) ||
(sdk_sanity_check_http_hdr_handle(mh_mloc) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_null_ptr((void *)name) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)locp) == TS_SUCCESS);
if (!isWriteable(bufp))
return TS_ERROR;
if (name_len == -1)
name_len = strlen(name);
MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(mh_mloc);
HdrHeap *heap = (HdrHeap *)(((HdrHeapSDKHandle *)bufp)->m_heap);
MIMEFieldSDKHandle *h = sdk_alloc_field_handle(bufp, mh);
h->field_ptr = mime_field_create_named(heap, mh, name, name_len);
*locp = reinterpret_cast<TSMLoc>(h);
return TS_SUCCESS;
}
TSReturnCode
TSMimeHdrFieldCopy(TSMBuffer dest_bufp, TSMLoc dest_hdr, TSMLoc dest_field, TSMBuffer src_bufp, TSMLoc src_hdr, TSMLoc src_field)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR. If allowed, return TS_SUCCESS. Changed the
// return value of function from void to TSReturnCode.
sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(src_hdr) == TS_SUCCESS) ||
(sdk_sanity_check_http_hdr_handle(src_hdr) == TS_SUCCESS));
sdk_assert((sdk_sanity_check_mime_hdr_handle(dest_hdr) == TS_SUCCESS) ||
(sdk_sanity_check_http_hdr_handle(dest_hdr) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_field_handle(src_field, src_hdr) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_field_handle(dest_field, dest_hdr) == TS_SUCCESS);
if (!isWriteable(dest_bufp))
return TS_ERROR;
bool dest_attached;
MIMEFieldSDKHandle *s_handle = (MIMEFieldSDKHandle *)src_field;
MIMEFieldSDKHandle *d_handle = (MIMEFieldSDKHandle *)dest_field;
HdrHeap *d_heap = ((HdrHeapSDKHandle *)dest_bufp)->m_heap;
// FIX: This tortuous detach/change/attach algorithm is due to the
// fact that we can't change the name of an attached header (assertion)
// TODO: This is never used ... is_live() has no side effects, so this should be ok
// to not call, so commented out
// src_attached = (s_handle->mh && s_handle->field_ptr->is_live());
dest_attached = (d_handle->mh && d_handle->field_ptr->is_live());
if (dest_attached)
mime_hdr_field_detach(d_handle->mh, d_handle->field_ptr, false);
mime_field_name_value_set(d_heap, d_handle->mh, d_handle->field_ptr, s_handle->field_ptr->m_wks_idx,
s_handle->field_ptr->m_ptr_name, s_handle->field_ptr->m_len_name, s_handle->field_ptr->m_ptr_value,
s_handle->field_ptr->m_len_value, 0, 0, true);
if (dest_attached)
mime_hdr_field_attach(d_handle->mh, d_handle->field_ptr, 1, NULL);
return TS_SUCCESS;
}
TSReturnCode
TSMimeHdrFieldClone(TSMBuffer dest_bufp, TSMLoc dest_hdr, TSMBuffer src_bufp, TSMLoc src_hdr, TSMLoc src_field, TSMLoc *locp)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR. If not allowed, return NULL.
sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(dest_hdr) == TS_SUCCESS) ||
(sdk_sanity_check_http_hdr_handle(dest_hdr) == TS_SUCCESS));
sdk_assert((sdk_sanity_check_mime_hdr_handle(src_hdr) == TS_SUCCESS) ||
(sdk_sanity_check_http_hdr_handle(src_hdr) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_field_handle(src_field, src_hdr) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)locp) == TS_SUCCESS);
if (!isWriteable(dest_bufp))
return TS_ERROR;
// This is sort of sub-optimal, since we'll check the args again. TODO.
if (TSMimeHdrFieldCreate(dest_bufp, dest_hdr, locp) == TS_SUCCESS) {
TSMimeHdrFieldCopy(dest_bufp, dest_hdr, *locp, src_bufp, src_hdr, src_field);
return TS_SUCCESS;
}
// TSMimeHdrFieldCreate() failed for some reason.
return TS_ERROR;
}
TSReturnCode
TSMimeHdrFieldCopyValues(TSMBuffer dest_bufp, TSMLoc dest_hdr, TSMLoc dest_field, TSMBuffer src_bufp, TSMLoc src_hdr,
TSMLoc src_field)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR. If allowed, return TS_SUCCESS. Changed the
// return value of function from void to TSReturnCode.
sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(src_hdr) == TS_SUCCESS) ||
(sdk_sanity_check_http_hdr_handle(src_hdr) == TS_SUCCESS));
sdk_assert((sdk_sanity_check_mime_hdr_handle(dest_hdr) == TS_SUCCESS) ||
(sdk_sanity_check_http_hdr_handle(dest_hdr) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_field_handle(src_field, src_hdr) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_field_handle(dest_field, dest_hdr) == TS_SUCCESS);
if (!isWriteable(dest_bufp))
return TS_ERROR;
MIMEFieldSDKHandle *s_handle = (MIMEFieldSDKHandle *)src_field;
MIMEFieldSDKHandle *d_handle = (MIMEFieldSDKHandle *)dest_field;
HdrHeap *d_heap = ((HdrHeapSDKHandle *)dest_bufp)->m_heap;
MIMEField *s_field, *d_field;
s_field = s_handle->field_ptr;
d_field = d_handle->field_ptr;
mime_field_value_set(d_heap, d_handle->mh, d_field, s_field->m_ptr_value, s_field->m_len_value, true);
return TS_SUCCESS;
}
// TODO: This is implemented horribly slowly, but who's using it anyway?
// If we threaded all the MIMEFields, this function could be easier,
// but we'd have to print dups in order and we'd need a flag saying
// end of dup list or dup follows.
TSMLoc
TSMimeHdrFieldNext(TSMBuffer bufp, TSMLoc hdr, TSMLoc field)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *)field;
if (handle->mh == NULL)
return TS_NULL_MLOC;
int slotnum = mime_hdr_field_slotnum(handle->mh, handle->field_ptr);
if (slotnum == -1)
return TS_NULL_MLOC;
while (1) {
++slotnum;
MIMEField *f = mime_hdr_field_get_slotnum(handle->mh, slotnum);
if (f == NULL)
return TS_NULL_MLOC;
if (f->is_live()) {
MIMEFieldSDKHandle *h = sdk_alloc_field_handle(bufp, handle->mh);
h->field_ptr = f;
return reinterpret_cast<TSMLoc>(h);
}
}
return TS_NULL_MLOC; // Shouldn't happen.
}
TSMLoc
TSMimeHdrFieldNextDup(TSMBuffer bufp, TSMLoc hdr, TSMLoc field)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(hdr);
MIMEFieldSDKHandle *field_handle = (MIMEFieldSDKHandle *)field;
MIMEField *next = field_handle->field_ptr->m_next_dup;
if (next == NULL)
return TS_NULL_MLOC;
MIMEFieldSDKHandle *next_handle = sdk_alloc_field_handle(bufp, mh);
next_handle->field_ptr = next;
return (TSMLoc)next_handle;
}
int
TSMimeHdrFieldLengthGet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *)field;
return mime_field_length_get(handle->field_ptr);
}
const char *
TSMimeHdrFieldNameGet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int *length)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)length) == TS_SUCCESS);
MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *)field;
return mime_field_name_get(handle->field_ptr, length);
}
TSReturnCode
TSMimeHdrFieldNameSet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, const char *name, int length)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR. If allowed, return TS_SUCCESS. Changed the
// return value of function from void to TSReturnCode.
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)name) == TS_SUCCESS);
if (!isWriteable(bufp))
return TS_ERROR;
if (length == -1)
length = strlen(name);
MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *)field;
HdrHeap *heap = ((HdrHeapSDKHandle *)bufp)->m_heap;
int attached = (handle->mh && handle->field_ptr->is_live());
if (attached)
mime_hdr_field_detach(handle->mh, handle->field_ptr, false);
handle->field_ptr->name_set(heap, handle->mh, name, length);
if (attached)
mime_hdr_field_attach(handle->mh, handle->field_ptr, 1, NULL);
return TS_SUCCESS;
}
TSReturnCode
TSMimeHdrFieldValuesClear(TSMBuffer bufp, TSMLoc hdr, TSMLoc field)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR. If allowed, return TS_SUCCESS. Changed the
// return value of function from void to TSReturnCode.
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
if (!isWriteable(bufp))
return TS_ERROR;
MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *)field;
HdrHeap *heap = ((HdrHeapSDKHandle *)bufp)->m_heap;
/**
* Modified the string value passed from an empty string ("") to NULL.
* An empty string is also considered to be a token. The correct value of
* the field after this function should be NULL.
*/
mime_field_value_set(heap, handle->mh, handle->field_ptr, NULL, 0, 1);
return TS_SUCCESS;
}
int
TSMimeHdrFieldValuesCount(TSMBuffer bufp, TSMLoc hdr, TSMLoc field)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *)field;
return mime_field_value_get_comma_val_count(handle->field_ptr);
}
const char *
TSMimeHdrFieldValueStringGet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, int *value_len_ptr)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)value_len_ptr) == TS_SUCCESS);
return TSMimeFieldValueGet(bufp, field, idx, value_len_ptr);
}
time_t
TSMimeHdrFieldValueDateGet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
int value_len;
const char *value_str = TSMimeFieldValueGet(bufp, field, -1, &value_len);
if (value_str == NULL)
return (time_t)0;
return mime_parse_date(value_str, value_str + value_len);
}
int
TSMimeHdrFieldValueIntGet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
int value_len;
const char *value_str = TSMimeFieldValueGet(bufp, field, idx, &value_len);
if (value_str == NULL)
return 0;
return mime_parse_int(value_str, value_str + value_len);
}
int64_t
TSMimeHdrFieldValueInt64Get(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
int value_len;
const char *value_str = TSMimeFieldValueGet(bufp, field, idx, &value_len);
if (value_str == NULL)
return 0;
return mime_parse_int64(value_str, value_str + value_len);
}
unsigned int
TSMimeHdrFieldValueUintGet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
int value_len;
const char *value_str = TSMimeFieldValueGet(bufp, field, idx, &value_len);
if (value_str == NULL)
return 0;
return mime_parse_uint(value_str, value_str + value_len);
}
TSReturnCode
TSMimeHdrFieldValueStringSet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, const char *value, int length)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR. If allowed, return TS_SUCCESS. Changed the
// return value of function from void to TSReturnCode.
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)value) == TS_SUCCESS);
if (!isWriteable(bufp))
return TS_ERROR;
if (length == -1)
length = strlen(value);
TSMimeFieldValueSet(bufp, field, idx, value, length);
return TS_SUCCESS;
}
TSReturnCode
TSMimeHdrFieldValueDateSet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, time_t value)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR. If allowed, return TS_SUCCESS. Changed the
// return value of function from void to TSReturnCode.
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
if (!isWriteable(bufp))
return TS_ERROR;
char tmp[33];
int len = mime_format_date(tmp, value);
// idx is ignored and we overwrite all existing values
// TSMimeFieldValueSet(bufp, field_obj, idx, tmp, len);
TSMimeFieldValueSet(bufp, field, -1, tmp, len);
return TS_SUCCESS;
}
TSReturnCode
TSMimeHdrFieldValueIntSet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, int value)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR. If allowed, return TS_SUCCESS. Changed the
// return value of function from void to TSReturnCode.
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
if (!isWriteable(bufp))
return TS_ERROR;
char tmp[16];
int len = mime_format_int(tmp, value, sizeof(tmp));
TSMimeFieldValueSet(bufp, field, idx, tmp, len);
return TS_SUCCESS;
}
TSReturnCode
TSMimeHdrFieldValueInt64Set(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, int64_t value)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR. If allowed, return TS_SUCCESS. Changed the
// return value of function from void to TSReturnCode.
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
if (!isWriteable(bufp))
return TS_ERROR;
char tmp[20];
int len = mime_format_int64(tmp, value, sizeof(tmp));
TSMimeFieldValueSet(bufp, field, idx, tmp, len);
return TS_SUCCESS;
}
TSReturnCode
TSMimeHdrFieldValueUintSet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, unsigned int value)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR. If allowed, return TS_SUCCESS. Changed the
// return value of function from void to TSReturnCode.
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
if (!isWriteable(bufp))
return TS_ERROR;
char tmp[16];
int len = mime_format_uint(tmp, value, sizeof(tmp));
TSMimeFieldValueSet(bufp, field, idx, tmp, len);
return TS_SUCCESS;
}
TSReturnCode
TSMimeHdrFieldValueAppend(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, const char *value, int length)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR. If allowed, return TS_SUCCESS. Changed the
// return value of function from void to TSReturnCode.
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)value) == TS_SUCCESS);
sdk_assert(idx >= 0);
if (!isWriteable(bufp))
return TS_ERROR;
MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *)field;
HdrHeap *heap = ((HdrHeapSDKHandle *)bufp)->m_heap;
if (length == -1)
length = strlen(value);
mime_field_value_extend_comma_val(heap, handle->mh, handle->field_ptr, idx, value, length);
return TS_SUCCESS;
}
TSReturnCode
TSMimeHdrFieldValueStringInsert(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, const char *value, int length)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR, else return TS_SUCCESS.
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)value) == TS_SUCCESS);
if (!isWriteable(bufp))
return TS_ERROR;
if (length == -1)
length = strlen(value);
TSMimeFieldValueInsert(bufp, field, value, length, idx);
return TS_SUCCESS;
}
TSReturnCode
TSMimeHdrFieldValueIntInsert(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, int value)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR, else return TS_SUCCESS.
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
if (!isWriteable(bufp))
return TS_ERROR;
char tmp[16];
int len = mime_format_int(tmp, value, sizeof(tmp));
TSMimeFieldValueInsert(bufp, field, tmp, len, idx);
return TS_SUCCESS;
}
TSReturnCode
TSMimeHdrFieldValueUintInsert(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, unsigned int value)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR, else return TS_SUCCESS.
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
if (!isWriteable(bufp))
return TS_ERROR;
char tmp[16];
int len = mime_format_uint(tmp, value, sizeof(tmp));
TSMimeFieldValueInsert(bufp, field, tmp, len, idx);
return TS_SUCCESS;
}
TSReturnCode
TSMimeHdrFieldValueDateInsert(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, time_t value)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR, else return TS_SUCCESS
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
if (!isWriteable(bufp))
return TS_ERROR;
if (TSMimeHdrFieldValuesClear(bufp, hdr, field) == TS_ERROR)
return TS_ERROR;
char tmp[33];
int len = mime_format_date(tmp, value);
// idx ignored, overwrite all exisiting values
// (void)TSMimeFieldValueInsert(bufp, field_obj, tmp, len, idx);
(void)TSMimeFieldValueSet(bufp, field, -1, tmp, len);
return TS_SUCCESS;
}
TSReturnCode
TSMimeHdrFieldValueDelete(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR. If allowed, return TS_SUCCESS. Changed the
// return value of function from void to TSReturnCode.
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
sdk_assert(idx >= 0);
if (!isWriteable(bufp))
return TS_ERROR;
MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *)field;
HdrHeap *heap = ((HdrHeapSDKHandle *)bufp)->m_heap;
mime_field_value_delete_comma_val(heap, handle->mh, handle->field_ptr, idx);
return TS_SUCCESS;
}
/**************/
/* HttpParser */
/**************/
TSHttpParser
TSHttpParserCreate(void)
{
TSHttpParser parser = reinterpret_cast<TSHttpParser>(ats_malloc(sizeof(HTTPParser)));
http_parser_init((HTTPParser *)parser);
return parser;
}
void
TSHttpParserClear(TSHttpParser parser)
{
sdk_assert(sdk_sanity_check_http_parser(parser) == TS_SUCCESS);
http_parser_clear((HTTPParser *)parser);
}
void
TSHttpParserDestroy(TSHttpParser parser)
{
sdk_assert(sdk_sanity_check_http_parser(parser) == TS_SUCCESS);
http_parser_clear((HTTPParser *)parser);
ats_free(parser);
}
/***********/
/* HttpHdr */
/***********/
TSMLoc
TSHttpHdrCreate(TSMBuffer bufp)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
HTTPHdr h;
h.m_heap = ((HdrHeapSDKHandle *)bufp)->m_heap;
h.create(HTTP_TYPE_UNKNOWN);
return (TSMLoc)(h.m_http);
}
void
TSHttpHdrDestroy(TSMBuffer bufp, TSMLoc obj)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
// No more objects counts in heap or deallocation
// so do nothing!
// HDR FIX ME - Did this free the MBuffer in Pete's old system
}
TSReturnCode
TSHttpHdrClone(TSMBuffer dest_bufp, TSMBuffer src_bufp, TSMLoc src_hdr, TSMLoc *locp)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR. If not allowed, return NULL.
sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_http_hdr_handle(src_hdr) == TS_SUCCESS);
if (!isWriteable(dest_bufp))
return TS_ERROR;
HdrHeap *s_heap, *d_heap;
HTTPHdrImpl *s_hh, *d_hh;
s_heap = ((HdrHeapSDKHandle *)src_bufp)->m_heap;
d_heap = ((HdrHeapSDKHandle *)dest_bufp)->m_heap;
s_hh = (HTTPHdrImpl *)src_hdr;
if (s_hh->m_type != HDR_HEAP_OBJ_HTTP_HEADER)
return TS_ERROR;
// TODO: This is never used
// inherit_strs = (s_heap != d_heap ? true : false);
d_hh = http_hdr_clone(s_hh, s_heap, d_heap);
*locp = (TSMLoc)d_hh;
return TS_SUCCESS;
}
TSReturnCode
TSHttpHdrCopy(TSMBuffer dest_bufp, TSMLoc dest_obj, TSMBuffer src_bufp, TSMLoc src_obj)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR. If allowed, return TS_SUCCESS. Changed the
// return value of function from void to TSReturnCode.
sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_http_hdr_handle(dest_obj) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_http_hdr_handle(src_obj) == TS_SUCCESS);
if (!isWriteable(dest_bufp))
return TS_ERROR;
bool inherit_strs;
HdrHeap *s_heap, *d_heap;
HTTPHdrImpl *s_hh, *d_hh;
s_heap = ((HdrHeapSDKHandle *)src_bufp)->m_heap;
d_heap = ((HdrHeapSDKHandle *)dest_bufp)->m_heap;
s_hh = (HTTPHdrImpl *)src_obj;
d_hh = (HTTPHdrImpl *)dest_obj;
if ((s_hh->m_type != HDR_HEAP_OBJ_HTTP_HEADER) || (d_hh->m_type != HDR_HEAP_OBJ_HTTP_HEADER))
return TS_ERROR;
inherit_strs = (s_heap != d_heap ? true : false);
TSHttpHdrTypeSet(dest_bufp, dest_obj, (TSHttpType)(s_hh->m_polarity));
http_hdr_copy_onto(s_hh, s_heap, d_hh, d_heap, inherit_strs);
return TS_SUCCESS;
}
void
TSHttpHdrPrint(TSMBuffer bufp, TSMLoc obj, TSIOBuffer iobufp)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_iocore_structure(iobufp) == TS_SUCCESS);
MIOBuffer *b = (MIOBuffer *)iobufp;
IOBufferBlock *blk;
HTTPHdr h;
int bufindex;
int tmp, dumpoffset;
int done;
SET_HTTP_HDR(h, bufp, obj);
ink_assert(h.m_http->m_type == HDR_HEAP_OBJ_HTTP_HEADER);
dumpoffset = 0;
do {
blk = b->get_current_block();
if (!blk || blk->write_avail() == 0) {
b->add_block();
blk = b->get_current_block();
}
bufindex = 0;
tmp = dumpoffset;
done = h.print(blk->end(), blk->write_avail(), &bufindex, &tmp);
dumpoffset += bufindex;
b->fill(bufindex);
} while (!done);
}
TSParseResult
TSHttpHdrParseReq(TSHttpParser parser, TSMBuffer bufp, TSMLoc obj, const char **start, const char *end)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)start) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)*start) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)end) == TS_SUCCESS);
if (!isWriteable(bufp))
return TS_PARSE_ERROR;
HTTPHdr h;
SET_HTTP_HDR(h, bufp, obj);
ink_assert(h.m_http->m_type == HDR_HEAP_OBJ_HTTP_HEADER);
TSHttpHdrTypeSet(bufp, obj, TS_HTTP_TYPE_REQUEST);
return (TSParseResult)h.parse_req((HTTPParser *)parser, start, end, false);
}
TSParseResult
TSHttpHdrParseResp(TSHttpParser parser, TSMBuffer bufp, TSMLoc obj, const char **start, const char *end)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)start) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)*start) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)end) == TS_SUCCESS);
if (!isWriteable(bufp))
return TS_PARSE_ERROR;
HTTPHdr h;
SET_HTTP_HDR(h, bufp, obj);
ink_assert(h.m_http->m_type == HDR_HEAP_OBJ_HTTP_HEADER);
TSHttpHdrTypeSet(bufp, obj, TS_HTTP_TYPE_RESPONSE);
return (TSParseResult)h.parse_resp((HTTPParser *)parser, start, end, false);
}
int
TSHttpHdrLengthGet(TSMBuffer bufp, TSMLoc obj)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
HTTPHdr h;
SET_HTTP_HDR(h, bufp, obj);
ink_assert(h.m_http->m_type == HDR_HEAP_OBJ_HTTP_HEADER);
return h.length_get();
}
TSHttpType
TSHttpHdrTypeGet(TSMBuffer bufp, TSMLoc obj)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
HTTPHdr h;
SET_HTTP_HDR(h, bufp, obj);
/* Don't need the assert as the check is done in sdk_sanity_check_http_hdr_handle
ink_assert(h.m_http->m_type == HDR_HEAP_OBJ_HTTP_HEADER);
*/
return (TSHttpType)h.type_get();
}
TSReturnCode
TSHttpHdrTypeSet(TSMBuffer bufp, TSMLoc obj, TSHttpType type)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR. If allowed, return TS_SUCCESS. Changed the
// return value of function from void to TSReturnCode.
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
sdk_assert((type >= TS_HTTP_TYPE_UNKNOWN) && (type <= TS_HTTP_TYPE_RESPONSE));
if (!isWriteable(bufp))
return TS_ERROR;
HTTPHdr h;
SET_HTTP_HDR(h, bufp, obj);
ink_assert(h.m_http->m_type == HDR_HEAP_OBJ_HTTP_HEADER);
// FIX: why are we using an HTTPHdr here? why can't we
// just manipulate the impls directly?
// In Pete's MBuffer system you can change the type
// at will. Not so anymore. We need to try to
// fake the difference. We not going to let
// people change the types of a header. If they
// try, too bad.
if (h.m_http->m_polarity == HTTP_TYPE_UNKNOWN) {
if (type == (TSHttpType)HTTP_TYPE_REQUEST) {
h.m_http->u.req.m_url_impl = url_create(h.m_heap);
h.m_http->m_polarity = (HTTPType)type;
} else if (type == (TSHttpType)HTTP_TYPE_RESPONSE) {
h.m_http->m_polarity = (HTTPType)type;
}
}
return TS_SUCCESS;
}
int
TSHttpHdrVersionGet(TSMBuffer bufp, TSMLoc obj)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
HTTPHdr h;
SET_HTTP_HDR(h, bufp, obj);
HTTPVersion ver = h.version_get();
return ver.m_version;
}
TSReturnCode
TSHttpHdrVersionSet(TSMBuffer bufp, TSMLoc obj, int ver)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR. If allowed, return TS_SUCCESS. Changed the
// return value of function from void to TSReturnCode.
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
if (!isWriteable(bufp))
return TS_ERROR;
HTTPHdr h;
HTTPVersion version(ver);
SET_HTTP_HDR(h, bufp, obj);
ink_assert(h.m_http->m_type == HDR_HEAP_OBJ_HTTP_HEADER);
h.version_set(version);
return TS_SUCCESS;
}
const char *
TSHttpHdrMethodGet(TSMBuffer bufp, TSMLoc obj, int *length)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)length) == TS_SUCCESS);
HTTPHdr h;
SET_HTTP_HDR(h, bufp, obj);
return h.method_get(length);
}
TSReturnCode
TSHttpHdrMethodSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR. If allowed, return TS_SUCCESS. Changed the
// return value of function from void to TSReturnCode.
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)value) == TS_SUCCESS);
if (!isWriteable(bufp))
return TS_ERROR;
HTTPHdr h;
SET_HTTP_HDR(h, bufp, obj);
if (length < 0)
length = strlen(value);
h.method_set(value, length);
return TS_SUCCESS;
}
const char *
TSHttpHdrHostGet(TSMBuffer bufp, TSMLoc obj, int *length)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)length) == TS_SUCCESS);
HTTPHdr h;
SET_HTTP_HDR(h, bufp, obj);
return h.host_get(length);
}
TSReturnCode
TSHttpHdrUrlGet(TSMBuffer bufp, TSMLoc obj, TSMLoc *locp)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
HTTPHdrImpl *hh = (HTTPHdrImpl *)obj;
if (hh->m_polarity != HTTP_TYPE_REQUEST)
return TS_ERROR;
*locp = ((TSMLoc)hh->u.req.m_url_impl);
return TS_SUCCESS;
}
TSReturnCode
TSHttpHdrUrlSet(TSMBuffer bufp, TSMLoc obj, TSMLoc url)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR. If allowed, return TS_SUCCESS. Changed the
// return value of function from void to TSReturnCode.
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_url_handle(url) == TS_SUCCESS);
if (!isWriteable(bufp))
return TS_ERROR;
HdrHeap *heap = ((HdrHeapSDKHandle *)bufp)->m_heap;
HTTPHdrImpl *hh = (HTTPHdrImpl *)obj;
if (hh->m_type != HDR_HEAP_OBJ_HTTP_HEADER)
return TS_ERROR;
URLImpl *url_impl = (URLImpl *)url;
http_hdr_url_set(heap, hh, url_impl);
return TS_SUCCESS;
}
TSHttpStatus
TSHttpHdrStatusGet(TSMBuffer bufp, TSMLoc obj)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
HTTPHdr h;
SET_HTTP_HDR(h, bufp, obj);
return (TSHttpStatus)h.status_get();
}
TSReturnCode
TSHttpHdrStatusSet(TSMBuffer bufp, TSMLoc obj, TSHttpStatus status)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR. If allowed, return TS_SUCCESS. Changed the
// return value of function from void to TSReturnCode.
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
if (!isWriteable(bufp))
return TS_ERROR;
HTTPHdr h;
SET_HTTP_HDR(h, bufp, obj);
ink_assert(h.m_http->m_type == HDR_HEAP_OBJ_HTTP_HEADER);
h.status_set((HTTPStatus)status);
return TS_SUCCESS;
}
const char *
TSHttpHdrReasonGet(TSMBuffer bufp, TSMLoc obj, int *length)
{
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)length) == TS_SUCCESS);
HTTPHdr h;
SET_HTTP_HDR(h, bufp, obj);
return h.reason_get(length);
}
TSReturnCode
TSHttpHdrReasonSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
{
// Allow to modify the buffer only
// if bufp is modifiable. If bufp is not modifiable return
// TS_ERROR. If allowed, return TS_SUCCESS. Changed the
// return value of function from void to TSReturnCode.
sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)value) == TS_SUCCESS);
if (!isWriteable(bufp))
return TS_ERROR;
HTTPHdr h;
SET_HTTP_HDR(h, bufp, obj);
/* Don't need the assert as the check is done in sdk_sanity_check_http_hdr_handle
ink_assert(h.m_http->m_type == HDR_HEAP_OBJ_HTTP_HEADER);
*/
if (length < 0)
length = strlen(value);
h.reason_set(value, length);
return TS_SUCCESS;
}
const char *
TSHttpHdrReasonLookup(TSHttpStatus status)
{
return http_hdr_reason_lookup((HTTPStatus)status);
}
////////////////////////////////////////////////////////////////////
//
// Cache
//
////////////////////////////////////////////////////////////////////
inline TSReturnCode
sdk_sanity_check_cachekey(TSCacheKey key)
{
if (NULL == key)
return TS_ERROR;
return TS_SUCCESS;
}
TSCacheKey
TSCacheKeyCreate(void)
{
TSCacheKey key = (TSCacheKey) new CacheInfo();
// TODO: Probably remove this when we can be use "NEW" can't fail.
sdk_assert(sdk_sanity_check_cachekey(key) == TS_SUCCESS);
return key;
}
TSReturnCode
TSCacheKeyDigestSet(TSCacheKey key, const char *input, int length)
{
sdk_assert(sdk_sanity_check_cachekey(key) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_iocore_structure((void *)input) == TS_SUCCESS);
sdk_assert(length > 0);
CacheInfo *ci = reinterpret_cast<CacheInfo *>(key);
if (ci->magic != CACHE_INFO_MAGIC_ALIVE)
return TS_ERROR;
MD5Context().hash_immediate(ci->cache_key, input, length);
return TS_SUCCESS;
}
TSReturnCode
TSCacheKeyDigestFromUrlSet(TSCacheKey key, TSMLoc url)
{
sdk_assert(sdk_sanity_check_cachekey(key) == TS_SUCCESS);
if (((CacheInfo *)key)->magic != CACHE_INFO_MAGIC_ALIVE)
return TS_ERROR;
url_MD5_get((URLImpl *)url, &((CacheInfo *)key)->cache_key);
return TS_SUCCESS;
}
TSReturnCode
TSCacheKeyDataTypeSet(TSCacheKey key, TSCacheDataType type)
{
sdk_assert(sdk_sanity_check_cachekey(key) == TS_SUCCESS);
if (((CacheInfo *)key)->magic != CACHE_INFO_MAGIC_ALIVE)
return TS_ERROR;
switch (type) {
case TS_CACHE_DATA_TYPE_NONE:
((CacheInfo *)key)->frag_type = CACHE_FRAG_TYPE_NONE;
break;
case TS_CACHE_DATA_TYPE_OTHER: /* other maps to http */
case TS_CACHE_DATA_TYPE_HTTP:
((CacheInfo *)key)->frag_type = CACHE_FRAG_TYPE_HTTP;
break;
default:
return TS_ERROR;
}
return TS_SUCCESS;
}
TSReturnCode
TSCacheKeyHostNameSet(TSCacheKey key, const char *hostname, int host_len)
{
sdk_assert(sdk_sanity_check_cachekey(key) == TS_SUCCESS);
sdk_assert(sdk_sanity_check_null_ptr((void *)hostname) == TS_SUCCESS);
sdk_assert(host_len > 0);
if (((CacheInfo *)key)->magic != CACHE_INFO_MAGIC_ALIVE)
return TS_ERROR;
CacheInfo *i = (CacheInfo *)key;
/* need to make a copy of the hostname. The caller
might deallocate it anytime in the future */
i->hostname = (char *)ats_malloc(host_len);
memcpy(i->hostname, hostname, host_len);
i->len = host_len;
return TS_SUCCESS;
}
TSReturnCode
TSCacheKeyPinnedSet(TSCacheKey key, time_t pin_in_cache)
{
sdk_assert(sdk_sanity_check_cachekey(key) == TS_SUCCESS);
if (((CacheInfo *)key)->magic != CACHE_INFO_MAGIC_ALIVE)
return TS_ERROR;
CacheInfo *i = (CacheInfo *)key;
i->pin_in_cache = pin_in_cache;
return TS_SUCCESS;
}
TSReturnCode
TSCacheKeyDestroy(TSCacheKey key)
{
sdk_assert(sdk_sanity_check_cachekey(key) == TS_SUCCESS);
if (((CacheInfo *)key)->magic != CACHE_INFO_MAGIC_ALIVE)
return TS_ERROR;
CacheInfo *i = (CacheInfo *)key;
ats_free(i->hostname);
i->magic = CACHE_INFO_MAGIC_DEAD;
delete i;
return TS_SUCCESS;
}
TSCacheHttpInfo
TSCacheHttpInfoCopy(TSCacheHttpInfo infop)
{
CacheHTTPInfo *new_info = new CacheHTTPInfo;
new_info->copy((CacheHTTPInfo *)infop);
return reinterpret_cast<TSCacheHttpInfo>(new_info);
}
void
TSCacheHttpInfoReqGet(TSCacheHttpInfo infop, TSMBuffer *bufp, TSMLoc *obj)
{
CacheHTTPInfo *info = (CacheHTTPInfo *)infop;
*(reinterpret_cast<HTTPHdr **>(bufp)) = info->request_get();
*obj = reinterpret_cast<TSMLoc>(info->request_get()->m_http);
sdk_sanity_check_mbuffer(*bufp);
}
void
TSCacheHttpInfoRespGet(TSCacheHttpInfo infop, TSMBuffer *bufp, TSMLoc *obj)
{
CacheHTTPInfo *info = (CacheHTTPInfo *)infop;
*(reinterpret_cast<HTTPHdr **>(bufp)) = info->response_get();
*obj = reinterpret_cast<TSMLoc>(info->response_get()->m_http);
sdk_sanity_check_mbuffer(*bufp);
}
time_t
TSCacheHttpInfoReqSentTimeGet(TSCacheHttpInfo infop)
{
CacheHTTPInfo *info = (CacheHTTPInfo *)infop;
return info->request_sent_time_get();
}
time_t
TSCacheHttpInfoRespReceivedTimeGet(TSCacheHttpInfo infop)
{
CacheHTTPInfo *info = (CacheHTTPInfo *)infop;
return info->response_received_time_get();
}
int64_t
TSCacheHttpInfoSizeGet(TSCacheHttpInfo infop)
{
CacheHTTPInfo *info = (CacheHTTPInfo *)infop;
return info->object_size_get();
}
void
TSCacheHttpInfoReqSet(TSCacheHttpInfo infop, TSMBuffer bufp, TSMLoc obj)
{
HTTPHdr h;
SET_HTTP_HDR(h, bufp, obj);
CacheHTTPInfo *info = (CacheHTTPInfo *)infop;
info->request_set(&h);
}
void
TSCacheHttpInfoRespSet(TSCacheHttpInfo infop, TSMBuffer bufp, TSMLoc obj)
{
HTTPHdr h;
SET_HTTP_HDR(h, bufp, obj);
CacheHTTPInfo *info = (CacheHTTPInfo *)infop;
info->response_set(&h);
}
int
TSCacheHttpInfoVector(TSCacheHttpInfo infop, void *data, int length)
{
CacheHTTPInfo *info = (CacheHTTPInfo *)infop;
CacheHTTPInfoVector vector;
vector.insert(info);
int size = vector.marshal_length();
if (size > length)
// error
return 0;
return vector.marshal((char *)data, length);
}
void
TSCacheHttpInfoDestroy(TSCacheHttpInfo infop)
{
((CacheHTTPInfo *)infop)->destroy();
}
TSCacheHttpInfo
TSCacheHttpInfoCreate(void)