• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

InkAPI.cc

Go to the documentation of this file.
00001 /** @file
00002 
00003   Implements callin functions for TSAPI plugins.
00004 
00005   @section license License
00006 
00007   Licensed to the Apache Software Foundation (ASF) under one
00008   or more contributor license agreements.  See the NOTICE file
00009   distributed with this work for additional information
00010   regarding copyright ownership.  The ASF licenses this file
00011   to you under the Apache License, Version 2.0 (the
00012   "License"); you may not use this file except in compliance
00013   with the License.  You may obtain a copy of the License at
00014 
00015       http://www.apache.org/licenses/LICENSE-2.0
00016 
00017   Unless required by applicable law or agreed to in writing, software
00018   distributed under the License is distributed on an "AS IS" BASIS,
00019   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020   See the License for the specific language governing permissions and
00021   limitations under the License.
00022  */
00023 
00024 #include <stdio.h>
00025 
00026 #include "libts.h"
00027 #include "I_Layout.h"
00028 
00029 #include "ts.h"
00030 #include "InkAPIInternal.h"
00031 #include "Log.h"
00032 #include "URL.h"
00033 #include "MIME.h"
00034 #include "HTTP.h"
00035 #include "HttpClientSession.h"
00036 #include "HttpServerSession.h"
00037 #include "HttpSM.h"
00038 #include "HttpConfig.h"
00039 #include "P_Net.h"
00040 #include "P_UDPNet.h"
00041 #include "P_HostDB.h"
00042 #include "StatSystem.h"
00043 #include "P_Cache.h"
00044 #include "I_RecCore.h"
00045 #include "I_RecSignals.h"
00046 #include "ProxyConfig.h"
00047 #include "Plugin.h"
00048 #include "LogObject.h"
00049 #include "LogConfig.h"
00050 //#include "UserNameCache.h"
00051 #include "PluginVC.h"
00052 #include "api/ts/experimental.h"
00053 #include "ICP.h"
00054 #include "HttpSessionAccept.h"
00055 #include "PluginVC.h"
00056 #include "FetchSM.h"
00057 #include "HttpDebugNames.h"
00058 #include "I_AIO.h"
00059 #include "I_Tasks.h"
00060 
00061 #include "I_RecDefs.h"
00062 #include "I_RecCore.h"
00063 #include "HttpProxyServerMain.h"
00064 
00065 
00066 /****************************************************************
00067  *  IMPORTANT - READ ME
00068  * Any plugin using the IO Core must enter
00069  *   with a held mutex.  SDK 1.0, 1.1 & 2.0 did not
00070  *   have this restriction so we need to add a mutex
00071  *   to Plugin's Continuation if it trys to use the IOCore
00072  * Not only does the plugin have to have a mutex
00073  *   before entering the IO Core.  The mutex needs to be held.
00074  *   We now take out the mutex on each call to ensure it is
00075  *   held for the entire duration of the IOCore call
00076  ***************************************************************/
00077 
00078 // helper macro for setting HTTPHdr data
00079 #define SET_HTTP_HDR(_HDR, _BUF_PTR, _OBJ_PTR) \
00080     _HDR.m_heap = ((HdrHeapSDKHandle*) _BUF_PTR)->m_heap; \
00081     _HDR.m_http = (HTTPHdrImpl*) _OBJ_PTR; \
00082     _HDR.m_mime = _HDR.m_http->m_fields_impl;
00083 
00084 // Globals for new librecords stats
00085 static volatile int api_rsb_index = 0;
00086 static RecRawStatBlock * api_rsb;
00087 
00088 // Library init functions needed for API.
00089 extern void ts_session_protocol_well_known_name_indices_init();
00090 
00091 // Globals for the Sessions/Transaction index registry
00092 static volatile int next_argv_index = 0;
00093 
00094 struct _STATE_ARG_TABLE {
00095   char* name;
00096   size_t name_len;
00097   char* description;
00098 } state_arg_table[HTTP_SSN_TXN_MAX_USER_ARG];
00099 
00100 
00101 /* URL schemes */
00102 tsapi const char *TS_URL_SCHEME_FILE;
00103 tsapi const char *TS_URL_SCHEME_FTP;
00104 tsapi const char *TS_URL_SCHEME_GOPHER;
00105 tsapi const char *TS_URL_SCHEME_HTTP;
00106 tsapi const char *TS_URL_SCHEME_HTTPS;
00107 tsapi const char *TS_URL_SCHEME_MAILTO;
00108 tsapi const char *TS_URL_SCHEME_NEWS;
00109 tsapi const char *TS_URL_SCHEME_NNTP;
00110 tsapi const char *TS_URL_SCHEME_PROSPERO;
00111 tsapi const char *TS_URL_SCHEME_TELNET;
00112 tsapi const char *TS_URL_SCHEME_TUNNEL;
00113 tsapi const char *TS_URL_SCHEME_WAIS;
00114 tsapi const char *TS_URL_SCHEME_PNM;
00115 tsapi const char *TS_URL_SCHEME_RTSP;
00116 tsapi const char *TS_URL_SCHEME_RTSPU;
00117 tsapi const char *TS_URL_SCHEME_MMS;
00118 tsapi const char *TS_URL_SCHEME_MMSU;
00119 tsapi const char *TS_URL_SCHEME_MMST;
00120 
00121 /* URL schemes string lengths */
00122 tsapi int TS_URL_LEN_FILE;
00123 tsapi int TS_URL_LEN_FTP;
00124 tsapi int TS_URL_LEN_GOPHER;
00125 tsapi int TS_URL_LEN_HTTP;
00126 tsapi int TS_URL_LEN_HTTPS;
00127 tsapi int TS_URL_LEN_MAILTO;
00128 tsapi int TS_URL_LEN_NEWS;
00129 tsapi int TS_URL_LEN_NNTP;
00130 tsapi int TS_URL_LEN_PROSPERO;
00131 tsapi int TS_URL_LEN_TELNET;
00132 tsapi int TS_URL_LEN_TUNNEL;
00133 tsapi int TS_URL_LEN_WAIS;
00134 tsapi int TS_URL_LEN_PNM;
00135 tsapi int TS_URL_LEN_RTSP;
00136 tsapi int TS_URL_LEN_RTSPU;
00137 tsapi int TS_URL_LEN_MMS;
00138 tsapi int TS_URL_LEN_MMSU;
00139 tsapi int TS_URL_LEN_MMST;
00140 
00141 /* MIME fields */
00142 tsapi const char *TS_MIME_FIELD_ACCEPT;
00143 tsapi const char *TS_MIME_FIELD_ACCEPT_CHARSET;
00144 tsapi const char *TS_MIME_FIELD_ACCEPT_ENCODING;
00145 tsapi const char *TS_MIME_FIELD_ACCEPT_LANGUAGE;
00146 tsapi const char *TS_MIME_FIELD_ACCEPT_RANGES;
00147 tsapi const char *TS_MIME_FIELD_AGE;
00148 tsapi const char *TS_MIME_FIELD_ALLOW;
00149 tsapi const char *TS_MIME_FIELD_APPROVED;
00150 tsapi const char *TS_MIME_FIELD_AUTHORIZATION;
00151 tsapi const char *TS_MIME_FIELD_BYTES;
00152 tsapi const char *TS_MIME_FIELD_CACHE_CONTROL;
00153 tsapi const char *TS_MIME_FIELD_CLIENT_IP;
00154 tsapi const char *TS_MIME_FIELD_CONNECTION;
00155 tsapi const char *TS_MIME_FIELD_CONTENT_BASE;
00156 tsapi const char *TS_MIME_FIELD_CONTENT_ENCODING;
00157 tsapi const char *TS_MIME_FIELD_CONTENT_LANGUAGE;
00158 tsapi const char *TS_MIME_FIELD_CONTENT_LENGTH;
00159 tsapi const char *TS_MIME_FIELD_CONTENT_LOCATION;
00160 tsapi const char *TS_MIME_FIELD_CONTENT_MD5;
00161 tsapi const char *TS_MIME_FIELD_CONTENT_RANGE;
00162 tsapi const char *TS_MIME_FIELD_CONTENT_TYPE;
00163 tsapi const char *TS_MIME_FIELD_CONTROL;
00164 tsapi const char *TS_MIME_FIELD_COOKIE;
00165 tsapi const char *TS_MIME_FIELD_DATE;
00166 tsapi const char *TS_MIME_FIELD_DISTRIBUTION;
00167 tsapi const char *TS_MIME_FIELD_ETAG;
00168 tsapi const char *TS_MIME_FIELD_EXPECT;
00169 tsapi const char *TS_MIME_FIELD_EXPIRES;
00170 tsapi const char *TS_MIME_FIELD_FOLLOWUP_TO;
00171 tsapi const char *TS_MIME_FIELD_FROM;
00172 tsapi const char *TS_MIME_FIELD_HOST;
00173 tsapi const char *TS_MIME_FIELD_IF_MATCH;
00174 tsapi const char *TS_MIME_FIELD_IF_MODIFIED_SINCE;
00175 tsapi const char *TS_MIME_FIELD_IF_NONE_MATCH;
00176 tsapi const char *TS_MIME_FIELD_IF_RANGE;
00177 tsapi const char *TS_MIME_FIELD_IF_UNMODIFIED_SINCE;
00178 tsapi const char *TS_MIME_FIELD_KEEP_ALIVE;
00179 tsapi const char *TS_MIME_FIELD_KEYWORDS;
00180 tsapi const char *TS_MIME_FIELD_LAST_MODIFIED;
00181 tsapi const char *TS_MIME_FIELD_LINES;
00182 tsapi const char *TS_MIME_FIELD_LOCATION;
00183 tsapi const char *TS_MIME_FIELD_MAX_FORWARDS;
00184 tsapi const char *TS_MIME_FIELD_MESSAGE_ID;
00185 tsapi const char *TS_MIME_FIELD_NEWSGROUPS;
00186 tsapi const char *TS_MIME_FIELD_ORGANIZATION;
00187 tsapi const char *TS_MIME_FIELD_PATH;
00188 tsapi const char *TS_MIME_FIELD_PRAGMA;
00189 tsapi const char *TS_MIME_FIELD_PROXY_AUTHENTICATE;
00190 tsapi const char *TS_MIME_FIELD_PROXY_AUTHORIZATION;
00191 tsapi const char *TS_MIME_FIELD_PROXY_CONNECTION;
00192 tsapi const char *TS_MIME_FIELD_PUBLIC;
00193 tsapi const char *TS_MIME_FIELD_RANGE;
00194 tsapi const char *TS_MIME_FIELD_REFERENCES;
00195 tsapi const char *TS_MIME_FIELD_REFERER;
00196 tsapi const char *TS_MIME_FIELD_REPLY_TO;
00197 tsapi const char *TS_MIME_FIELD_RETRY_AFTER;
00198 tsapi const char *TS_MIME_FIELD_SENDER;
00199 tsapi const char *TS_MIME_FIELD_SERVER;
00200 tsapi const char *TS_MIME_FIELD_SET_COOKIE;
00201 tsapi const char *TS_MIME_FIELD_STRICT_TRANSPORT_SECURITY;
00202 tsapi const char *TS_MIME_FIELD_SUBJECT;
00203 tsapi const char *TS_MIME_FIELD_SUMMARY;
00204 tsapi const char *TS_MIME_FIELD_TE;
00205 tsapi const char *TS_MIME_FIELD_TRANSFER_ENCODING;
00206 tsapi const char *TS_MIME_FIELD_UPGRADE;
00207 tsapi const char *TS_MIME_FIELD_USER_AGENT;
00208 tsapi const char *TS_MIME_FIELD_VARY;
00209 tsapi const char *TS_MIME_FIELD_VIA;
00210 tsapi const char *TS_MIME_FIELD_WARNING;
00211 tsapi const char *TS_MIME_FIELD_WWW_AUTHENTICATE;
00212 tsapi const char *TS_MIME_FIELD_XREF;
00213 tsapi const char *TS_MIME_FIELD_X_FORWARDED_FOR;
00214 
00215 /* MIME fields string lengths */
00216 tsapi int TS_MIME_LEN_ACCEPT;
00217 tsapi int TS_MIME_LEN_ACCEPT_CHARSET;
00218 tsapi int TS_MIME_LEN_ACCEPT_ENCODING;
00219 tsapi int TS_MIME_LEN_ACCEPT_LANGUAGE;
00220 tsapi int TS_MIME_LEN_ACCEPT_RANGES;
00221 tsapi int TS_MIME_LEN_AGE;
00222 tsapi int TS_MIME_LEN_ALLOW;
00223 tsapi int TS_MIME_LEN_APPROVED;
00224 tsapi int TS_MIME_LEN_AUTHORIZATION;
00225 tsapi int TS_MIME_LEN_BYTES;
00226 tsapi int TS_MIME_LEN_CACHE_CONTROL;
00227 tsapi int TS_MIME_LEN_CLIENT_IP;
00228 tsapi int TS_MIME_LEN_CONNECTION;
00229 tsapi int TS_MIME_LEN_CONTENT_BASE;
00230 tsapi int TS_MIME_LEN_CONTENT_ENCODING;
00231 tsapi int TS_MIME_LEN_CONTENT_LANGUAGE;
00232 tsapi int TS_MIME_LEN_CONTENT_LENGTH;
00233 tsapi int TS_MIME_LEN_CONTENT_LOCATION;
00234 tsapi int TS_MIME_LEN_CONTENT_MD5;
00235 tsapi int TS_MIME_LEN_CONTENT_RANGE;
00236 tsapi int TS_MIME_LEN_CONTENT_TYPE;
00237 tsapi int TS_MIME_LEN_CONTROL;
00238 tsapi int TS_MIME_LEN_COOKIE;
00239 tsapi int TS_MIME_LEN_DATE;
00240 tsapi int TS_MIME_LEN_DISTRIBUTION;
00241 tsapi int TS_MIME_LEN_ETAG;
00242 tsapi int TS_MIME_LEN_EXPECT;
00243 tsapi int TS_MIME_LEN_EXPIRES;
00244 tsapi int TS_MIME_LEN_FOLLOWUP_TO;
00245 tsapi int TS_MIME_LEN_FROM;
00246 tsapi int TS_MIME_LEN_HOST;
00247 tsapi int TS_MIME_LEN_IF_MATCH;
00248 tsapi int TS_MIME_LEN_IF_MODIFIED_SINCE;
00249 tsapi int TS_MIME_LEN_IF_NONE_MATCH;
00250 tsapi int TS_MIME_LEN_IF_RANGE;
00251 tsapi int TS_MIME_LEN_IF_UNMODIFIED_SINCE;
00252 tsapi int TS_MIME_LEN_KEEP_ALIVE;
00253 tsapi int TS_MIME_LEN_KEYWORDS;
00254 tsapi int TS_MIME_LEN_LAST_MODIFIED;
00255 tsapi int TS_MIME_LEN_LINES;
00256 tsapi int TS_MIME_LEN_LOCATION;
00257 tsapi int TS_MIME_LEN_MAX_FORWARDS;
00258 tsapi int TS_MIME_LEN_MESSAGE_ID;
00259 tsapi int TS_MIME_LEN_NEWSGROUPS;
00260 tsapi int TS_MIME_LEN_ORGANIZATION;
00261 tsapi int TS_MIME_LEN_PATH;
00262 tsapi int TS_MIME_LEN_PRAGMA;
00263 tsapi int TS_MIME_LEN_PROXY_AUTHENTICATE;
00264 tsapi int TS_MIME_LEN_PROXY_AUTHORIZATION;
00265 tsapi int TS_MIME_LEN_PROXY_CONNECTION;
00266 tsapi int TS_MIME_LEN_PUBLIC;
00267 tsapi int TS_MIME_LEN_RANGE;
00268 tsapi int TS_MIME_LEN_REFERENCES;
00269 tsapi int TS_MIME_LEN_REFERER;
00270 tsapi int TS_MIME_LEN_REPLY_TO;
00271 tsapi int TS_MIME_LEN_RETRY_AFTER;
00272 tsapi int TS_MIME_LEN_SENDER;
00273 tsapi int TS_MIME_LEN_SERVER;
00274 tsapi int TS_MIME_LEN_SET_COOKIE;
00275 tsapi int TS_MIME_LEN_STRICT_TRANSPORT_SECURITY;
00276 tsapi int TS_MIME_LEN_SUBJECT;
00277 tsapi int TS_MIME_LEN_SUMMARY;
00278 tsapi int TS_MIME_LEN_TE;
00279 tsapi int TS_MIME_LEN_TRANSFER_ENCODING;
00280 tsapi int TS_MIME_LEN_UPGRADE;
00281 tsapi int TS_MIME_LEN_USER_AGENT;
00282 tsapi int TS_MIME_LEN_VARY;
00283 tsapi int TS_MIME_LEN_VIA;
00284 tsapi int TS_MIME_LEN_WARNING;
00285 tsapi int TS_MIME_LEN_WWW_AUTHENTICATE;
00286 tsapi int TS_MIME_LEN_XREF;
00287 tsapi int TS_MIME_LEN_X_FORWARDED_FOR;
00288 
00289 
00290 /* HTTP miscellaneous values */
00291 tsapi const char *TS_HTTP_VALUE_BYTES;
00292 tsapi const char *TS_HTTP_VALUE_CHUNKED;
00293 tsapi const char *TS_HTTP_VALUE_CLOSE;
00294 tsapi const char *TS_HTTP_VALUE_COMPRESS;
00295 tsapi const char *TS_HTTP_VALUE_DEFLATE;
00296 tsapi const char *TS_HTTP_VALUE_GZIP;
00297 tsapi const char *TS_HTTP_VALUE_IDENTITY;
00298 tsapi const char *TS_HTTP_VALUE_KEEP_ALIVE;
00299 tsapi const char *TS_HTTP_VALUE_MAX_AGE;
00300 tsapi const char *TS_HTTP_VALUE_MAX_STALE;
00301 tsapi const char *TS_HTTP_VALUE_MIN_FRESH;
00302 tsapi const char *TS_HTTP_VALUE_MUST_REVALIDATE;
00303 tsapi const char *TS_HTTP_VALUE_NONE;
00304 tsapi const char *TS_HTTP_VALUE_NO_CACHE;
00305 tsapi const char *TS_HTTP_VALUE_NO_STORE;
00306 tsapi const char *TS_HTTP_VALUE_NO_TRANSFORM;
00307 tsapi const char *TS_HTTP_VALUE_ONLY_IF_CACHED;
00308 tsapi const char *TS_HTTP_VALUE_PRIVATE;
00309 tsapi const char *TS_HTTP_VALUE_PROXY_REVALIDATE;
00310 tsapi const char *TS_HTTP_VALUE_PUBLIC;
00311 tsapi const char *TS_HTTP_VALUE_S_MAXAGE;
00312 
00313 /* HTTP miscellaneous values string lengths */
00314 tsapi int TS_HTTP_LEN_BYTES;
00315 tsapi int TS_HTTP_LEN_CHUNKED;
00316 tsapi int TS_HTTP_LEN_CLOSE;
00317 tsapi int TS_HTTP_LEN_COMPRESS;
00318 tsapi int TS_HTTP_LEN_DEFLATE;
00319 tsapi int TS_HTTP_LEN_GZIP;
00320 tsapi int TS_HTTP_LEN_IDENTITY;
00321 tsapi int TS_HTTP_LEN_KEEP_ALIVE;
00322 tsapi int TS_HTTP_LEN_MAX_AGE;
00323 tsapi int TS_HTTP_LEN_MAX_STALE;
00324 tsapi int TS_HTTP_LEN_MIN_FRESH;
00325 tsapi int TS_HTTP_LEN_MUST_REVALIDATE;
00326 tsapi int TS_HTTP_LEN_NONE;
00327 tsapi int TS_HTTP_LEN_NO_CACHE;
00328 tsapi int TS_HTTP_LEN_NO_STORE;
00329 tsapi int TS_HTTP_LEN_NO_TRANSFORM;
00330 tsapi int TS_HTTP_LEN_ONLY_IF_CACHED;
00331 tsapi int TS_HTTP_LEN_PRIVATE;
00332 tsapi int TS_HTTP_LEN_PROXY_REVALIDATE;
00333 tsapi int TS_HTTP_LEN_PUBLIC;
00334 tsapi int TS_HTTP_LEN_S_MAXAGE;
00335 
00336 /* HTTP methods */
00337 tsapi const char *TS_HTTP_METHOD_CONNECT;
00338 tsapi const char *TS_HTTP_METHOD_DELETE;
00339 tsapi const char *TS_HTTP_METHOD_GET;
00340 tsapi const char *TS_HTTP_METHOD_HEAD;
00341 tsapi const char *TS_HTTP_METHOD_ICP_QUERY;
00342 tsapi const char *TS_HTTP_METHOD_OPTIONS;
00343 tsapi const char *TS_HTTP_METHOD_POST;
00344 tsapi const char *TS_HTTP_METHOD_PURGE;
00345 tsapi const char *TS_HTTP_METHOD_PUT;
00346 tsapi const char *TS_HTTP_METHOD_TRACE;
00347 tsapi const char *TS_HTTP_METHOD_PUSH;
00348 
00349 /* HTTP methods string lengths */
00350 tsapi int TS_HTTP_LEN_CONNECT;
00351 tsapi int TS_HTTP_LEN_DELETE;
00352 tsapi int TS_HTTP_LEN_GET;
00353 tsapi int TS_HTTP_LEN_HEAD;
00354 tsapi int TS_HTTP_LEN_ICP_QUERY;
00355 tsapi int TS_HTTP_LEN_OPTIONS;
00356 tsapi int TS_HTTP_LEN_POST;
00357 tsapi int TS_HTTP_LEN_PURGE;
00358 tsapi int TS_HTTP_LEN_PUT;
00359 tsapi int TS_HTTP_LEN_TRACE;
00360 tsapi int TS_HTTP_LEN_PUSH;
00361 
00362 /* MLoc Constants */
00363 tsapi const TSMLoc TS_NULL_MLOC = (TSMLoc)NULL;
00364 
00365 HttpAPIHooks *http_global_hooks = NULL;
00366 LifecycleAPIHooks* lifecycle_hooks = NULL;
00367 ConfigUpdateCbTable *global_config_cbs = NULL;
00368 
00369 static char traffic_server_version[128] = "";
00370 static int ts_major_version = 0;
00371 static int ts_minor_version = 0;
00372 static int ts_patch_version = 0;
00373 
00374 static ClassAllocator<APIHook> apiHookAllocator("apiHookAllocator");
00375 static ClassAllocator<INKContInternal> INKContAllocator("INKContAllocator");
00376 static ClassAllocator<INKVConnInternal> INKVConnAllocator("INKVConnAllocator");
00377 static ClassAllocator<MIMEFieldSDKHandle> mHandleAllocator("MIMEFieldSDKHandle");
00378 
00379 
00380 ////////////////////////////////////////////////////////////////////
00381 //
00382 // API error logging
00383 //
00384 ////////////////////////////////////////////////////////////////////
00385 void
00386 TSError(const char *fmt, ...)
00387 {
00388   va_list args;
00389 
00390   if (is_action_tag_set("deft") || is_action_tag_set("sdk_vbos_errors")) {
00391     va_start(args, fmt);
00392     diags->print_va(NULL, DL_Error, NULL, fmt, args);
00393     va_end(args);
00394   }
00395   va_start(args, fmt);
00396   Log::va_error((char *) fmt, args);
00397   va_end(args);
00398 }
00399 
00400 // Assert in debug AND optim
00401 void
00402 _TSReleaseAssert(const char *text, const char *file, int line)
00403 {
00404   _ink_assert(text, file, line);
00405 }
00406 
00407 // Assert only in debug
00408 int
00409 #ifdef DEBUG
00410 _TSAssert(const char *text, const char *file, int line)
00411 {
00412   _ink_assert(text, file, line);
00413   return 0;
00414 }
00415 #else
00416 _TSAssert(const char *, const char *, int)
00417 {
00418   return 0;
00419 }
00420 #endif
00421 
00422 // This assert is for internal API use only.
00423 #if TS_USE_FAST_SDK
00424 #define sdk_assert(EX) (void)(EX)
00425 #else
00426 #define sdk_assert(EX)                                          \
00427   ( (void)((EX) ? (void)0 : _TSReleaseAssert(#EX, __FILE__, __LINE__)) )
00428 #endif
00429 
00430 ////////////////////////////////////////////////////////////////////
00431 //
00432 // SDK Interoperability Support
00433 //
00434 // ----------------------------------------------------------------
00435 //
00436 // Standalone Fields (SDK Version-Interoperability Hack)
00437 //
00438 //
00439 // A "standalone" field is an ugly hack for portability with old
00440 // versions of the SDK that mirrored the old header system.  In
00441 // the old system, you could create arbitrary tiny little field
00442 // objects, distinct from MIME header objects, and link them
00443 // together.  In the new header system, all fields are internal
00444 // constituents of the MIME header.  To preserve the semantics of
00445 // the old SDK, we need to maintain the concept of fields that
00446 // are created outside of a MIME header.  Whenever a field is
00447 // "attached" to a MIME header, it is copied into the MIME header
00448 // field's slot, and the handle to the field is updated to refer
00449 // to the new field.
00450 //
00451 // Hopefully, we can eliminate this old compatibility interface and
00452 // migrate users to the newer semantics quickly.
00453 //
00454 // ----------------------------------------------------------------
00455 //
00456 // MIMEField SDK Handles (SDK Version-Interoperability Hack)
00457 //
00458 // MIMEField "handles" are used by the SDK as an indirect reference
00459 // to the MIMEField.  Because versions 1 & 2 of the SDK allowed
00460 // standalone fields that existed without associated MIME headers,
00461 // and because the version 3 SDK requires an associated MIME header
00462 // for all field mutation operations (for presence bits, etc.) we
00463 // need a data structure that:
00464 //
00465 //   * identifies standalone fields and stores field name/value
00466 //     information for fields that are not yet in a header
00467 //   * redirects the field to a real header field when the field
00468 //     is inserted into a header
00469 //   * maintains the associated MIMEHdrImpl when returning field
00470 //     slots from lookup and create functions
00471 //
00472 // If the MIMEHdrImpl pointer is NULL, then the handle points
00473 // to a standalone field, otherwise the handle points to a field
00474 // within the MIME header.
00475 //
00476 ////////////////////////////////////////////////////////////////////
00477 
00478 
00479 /*****************************************************************/
00480 /* Handles to headers are impls, but need to handle MIME or HTTP */
00481 /*****************************************************************/
00482 
00483 inline MIMEHdrImpl *
00484 _hdr_obj_to_mime_hdr_impl(HdrHeapObjImpl * obj)
00485 {
00486   MIMEHdrImpl *impl;
00487   if (obj->m_type == HDR_HEAP_OBJ_HTTP_HEADER)
00488     impl = ((HTTPHdrImpl *) obj)->m_fields_impl;
00489   else if (obj->m_type == HDR_HEAP_OBJ_MIME_HEADER)
00490     impl = (MIMEHdrImpl *) obj;
00491   else {
00492     ink_release_assert(!"mloc not a header type");
00493     impl = NULL;                /* gcc does not know about 'ink_release_assert' - make it happy */
00494   }
00495   return impl;
00496 }
00497 
00498 inline MIMEHdrImpl *
00499 _hdr_mloc_to_mime_hdr_impl(TSMLoc mloc)
00500 {
00501   return _hdr_obj_to_mime_hdr_impl((HdrHeapObjImpl *) mloc);
00502 }
00503 
00504 TSReturnCode
00505 sdk_sanity_check_field_handle(TSMLoc field, TSMLoc parent_hdr = NULL)
00506 {
00507   if (field == TS_NULL_MLOC)
00508     return TS_ERROR;
00509 
00510   MIMEFieldSDKHandle *field_handle = (MIMEFieldSDKHandle *) field;
00511   if (field_handle->m_type != HDR_HEAP_OBJ_FIELD_SDK_HANDLE)
00512     return TS_ERROR;
00513 
00514   if (parent_hdr != NULL) {
00515     MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(parent_hdr);
00516     if (field_handle->mh != mh)
00517       return TS_ERROR;
00518   }
00519   return TS_SUCCESS;
00520 }
00521 
00522 TSReturnCode
00523 sdk_sanity_check_mbuffer(TSMBuffer bufp)
00524 {
00525   HdrHeapSDKHandle *handle = (HdrHeapSDKHandle *) bufp;
00526   if ((handle == NULL) || (handle->m_heap == NULL) || (handle->m_heap->m_magic != HDR_BUF_MAGIC_ALIVE))
00527     return TS_ERROR;
00528 
00529   return TS_SUCCESS;
00530 }
00531 
00532 TSReturnCode
00533 sdk_sanity_check_mime_hdr_handle(TSMLoc field)
00534 {
00535   if (field == TS_NULL_MLOC)
00536     return TS_ERROR;
00537 
00538   MIMEFieldSDKHandle *field_handle = (MIMEFieldSDKHandle *) field;
00539   if (field_handle->m_type != HDR_HEAP_OBJ_MIME_HEADER)
00540     return TS_ERROR;
00541 
00542   return TS_SUCCESS;
00543 }
00544 
00545 TSReturnCode
00546 sdk_sanity_check_url_handle(TSMLoc field)
00547 {
00548   if (field == TS_NULL_MLOC)
00549     return TS_ERROR;
00550 
00551   MIMEFieldSDKHandle *field_handle = (MIMEFieldSDKHandle *) field;
00552   if (field_handle->m_type != HDR_HEAP_OBJ_URL)
00553     return TS_ERROR;
00554 
00555   return TS_SUCCESS;
00556 }
00557 
00558 TSReturnCode
00559 sdk_sanity_check_http_hdr_handle(TSMLoc field)
00560 {
00561   if (field == TS_NULL_MLOC)
00562     return TS_ERROR;
00563 
00564   HTTPHdrImpl *field_handle = (HTTPHdrImpl *) field;
00565   if (field_handle->m_type != HDR_HEAP_OBJ_HTTP_HEADER)
00566     return TS_ERROR;
00567 
00568   return TS_SUCCESS;
00569 }
00570 
00571 TSReturnCode
00572 sdk_sanity_check_continuation(TSCont cont)
00573 {
00574   if ((cont == NULL) || (((INKContInternal *) cont)->m_free_magic == INKCONT_INTERN_MAGIC_DEAD))
00575     return TS_ERROR;
00576 
00577   return TS_SUCCESS;
00578 }
00579 
00580 TSReturnCode
00581 sdk_sanity_check_fetch_sm(TSFetchSM fetch_sm)
00582 {
00583   if (fetch_sm == NULL)
00584     return TS_ERROR;
00585 
00586   return TS_SUCCESS;
00587 }
00588 
00589 TSReturnCode
00590 sdk_sanity_check_http_ssn(TSHttpSsn ssnp)
00591 {
00592   if (ssnp == NULL)
00593     return TS_ERROR;
00594 
00595   return TS_SUCCESS;
00596 }
00597 
00598 TSReturnCode
00599 sdk_sanity_check_txn(TSHttpTxn txnp)
00600 {
00601   if ((txnp != NULL) && (((HttpSM *) txnp)->magic == HTTP_SM_MAGIC_ALIVE))
00602     return TS_SUCCESS;
00603   return TS_ERROR;
00604 }
00605 
00606 TSReturnCode
00607 sdk_sanity_check_mime_parser(TSMimeParser parser)
00608 {
00609   if (parser == NULL)
00610     return TS_ERROR;
00611   return TS_SUCCESS;
00612 }
00613 
00614 TSReturnCode
00615 sdk_sanity_check_http_parser(TSHttpParser parser)
00616 {
00617   if (parser == NULL)
00618     return TS_ERROR;
00619   return TS_SUCCESS;
00620 }
00621 
00622 TSReturnCode
00623 sdk_sanity_check_alt_info(TSHttpAltInfo info)
00624 {
00625   if (info == NULL)
00626     return TS_ERROR;
00627   return TS_SUCCESS;
00628 }
00629 
00630 TSReturnCode
00631 sdk_sanity_check_hook_id(TSHttpHookID id)
00632 {
00633   if (id<TS_HTTP_READ_REQUEST_HDR_HOOK || id> TS_HTTP_LAST_HOOK)
00634     return TS_ERROR;
00635   return TS_SUCCESS;
00636 }
00637 
00638 TSReturnCode
00639 sdk_sanity_check_lifecycle_hook_id(TSLifecycleHookID id)
00640 {
00641   if (id<TS_LIFECYCLE_PORTS_INITIALIZED_HOOK || id> TS_LIFECYCLE_LAST_HOOK)
00642     return TS_ERROR;
00643   return TS_SUCCESS;
00644 }
00645 
00646 TSReturnCode
00647 sdk_sanity_check_null_ptr(void *ptr)
00648 {
00649   if (ptr == NULL)
00650     return TS_ERROR;
00651   return TS_SUCCESS;
00652 }
00653 
00654 /**
00655   The function checks if the buffer is Modifiable and returns true if
00656   it is modifiable, else returns false.
00657 
00658 */
00659 bool
00660 isWriteable(TSMBuffer bufp)
00661 {
00662   if (bufp != NULL) {
00663     return ((HdrHeapSDKHandle *) bufp)->m_heap->m_writeable;
00664   }
00665   return false;
00666 }
00667 
00668 
00669 /******************************************************/
00670 /* Allocators for field handles and standalone fields */
00671 /******************************************************/
00672 static MIMEFieldSDKHandle *
00673 sdk_alloc_field_handle(TSMBuffer /* bufp ATS_UNUSED */, MIMEHdrImpl *mh)
00674 {
00675   MIMEFieldSDKHandle *handle = mHandleAllocator.alloc();
00676 
00677   // TODO: Should remove this when memory allocation can't fail.
00678   sdk_assert(sdk_sanity_check_null_ptr((void*)handle) == TS_SUCCESS);
00679 
00680   obj_init_header(handle, HDR_HEAP_OBJ_FIELD_SDK_HANDLE, sizeof(MIMEFieldSDKHandle), 0);
00681   handle->mh = mh;
00682 
00683   return handle;
00684 }
00685 
00686 static void
00687 sdk_free_field_handle(TSMBuffer bufp, MIMEFieldSDKHandle *field_handle)
00688 {
00689   if (sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS) {
00690     mHandleAllocator.free(field_handle);
00691   }
00692 }
00693 
00694 
00695 ////////////////////////////////////////////////////////////////////
00696 //
00697 // FileImpl
00698 //
00699 ////////////////////////////////////////////////////////////////////
00700 FileImpl::FileImpl()
00701   : m_fd(-1), m_mode(CLOSED), m_buf(NULL), m_bufsize(0), m_bufpos(0)
00702 { }
00703 
00704 FileImpl::~FileImpl()
00705 {
00706   fclose();
00707 }
00708 
00709 int
00710 FileImpl::fopen(const char *filename, const char *mode)
00711 {
00712   if (mode[0] == '\0') {
00713     return 0;
00714   } else if (mode[0] == 'r') {
00715     if (mode[1] != '\0') {
00716       return 0;
00717     }
00718     m_mode = READ;
00719     m_fd = open(filename, O_RDONLY | _O_ATTRIB_NORMAL);
00720   } else if (mode[0] == 'w') {
00721     if (mode[1] != '\0') {
00722       return 0;
00723     }
00724     m_mode = WRITE;
00725     m_fd = open(filename, O_WRONLY | O_CREAT | _O_ATTRIB_NORMAL, 0644);
00726   } else if (mode[0] == 'a') {
00727     if (mode[1] != '\0') {
00728       return 0;
00729     }
00730     m_mode = WRITE;
00731     m_fd = open(filename, O_WRONLY | O_CREAT | O_APPEND | _O_ATTRIB_NORMAL, 0644);
00732   }
00733 
00734   if (m_fd < 0) {
00735     m_mode = CLOSED;
00736     return 0;
00737   } else {
00738     return 1;
00739   }
00740 }
00741 
00742 void
00743 FileImpl::fclose()
00744 {
00745   if (m_fd != -1) {
00746     fflush();
00747 
00748     close(m_fd);
00749     m_fd = -1;
00750     m_mode = CLOSED;
00751   }
00752 
00753   if (m_buf) {
00754     ats_free(m_buf);
00755     m_buf = NULL;
00756     m_bufsize = 0;
00757     m_bufpos = 0;
00758   }
00759 }
00760 
00761 int
00762 FileImpl::fread(void *buf, int length)
00763 {
00764   int64_t amount;
00765   int64_t err;
00766 
00767   if ((m_mode != READ) || (m_fd == -1)) {
00768     return -1;
00769   }
00770 
00771   if (!m_buf) {
00772     m_bufpos = 0;
00773     m_bufsize = 1024;
00774     m_buf = (char *)ats_malloc(m_bufsize);
00775   }
00776 
00777   if (m_bufpos < length) {
00778     amount = length;
00779     if (amount < 1024) {
00780       amount = 1024;
00781     }
00782     if (amount > (m_bufsize - m_bufpos)) {
00783       while (amount > (m_bufsize - m_bufpos)) {
00784         m_bufsize *= 2;
00785       }
00786       m_buf = (char *)ats_realloc(m_buf, m_bufsize);
00787     }
00788 
00789     do {
00790       err = read(m_fd, &m_buf[m_bufpos], amount);
00791     } while ((err < 0) && (errno == EINTR));
00792 
00793     if (err < 0) {
00794       return -1;
00795     }
00796 
00797     m_bufpos += err;
00798   }
00799 
00800   if (buf) {
00801     amount = length;
00802     if (amount > m_bufpos) {
00803       amount = m_bufpos;
00804     }
00805     memcpy(buf, m_buf, amount);
00806     memmove(m_buf, &m_buf[amount], m_bufpos - amount);
00807     m_bufpos -= amount;
00808     return amount;
00809   } else {
00810     return m_bufpos;
00811   }
00812 }
00813 
00814 int
00815 FileImpl::fwrite(const void *buf, int length)
00816 {
00817   const char *p, *e;
00818   int64_t avail;
00819 
00820   if ((m_mode != WRITE) || (m_fd == -1)) {
00821     return -1;
00822   }
00823 
00824   if (!m_buf) {
00825     m_bufpos = 0;
00826     m_bufsize = 1024;
00827     m_buf = (char *)ats_malloc(m_bufsize);
00828   }
00829 
00830   p = (const char *) buf;
00831   e = p + length;
00832 
00833   while (p != e) {
00834     avail = m_bufsize - m_bufpos;
00835     if (avail > length) {
00836       avail = length;
00837     }
00838     memcpy(&m_buf[m_bufpos], p, avail);
00839 
00840     m_bufpos += avail;
00841     p += avail;
00842     length -= avail;
00843 
00844     if ((length > 0) && (m_bufpos > 0)) {
00845       if (fflush() <= 0) {
00846         break;
00847       }
00848     }
00849   }
00850 
00851   return (p - (const char *) buf);
00852 }
00853 
00854 int
00855 FileImpl::fflush()
00856 {
00857   char *p, *e;
00858   int err = 0;
00859 
00860   if ((m_mode != WRITE) || (m_fd == -1)) {
00861     return -1;
00862   }
00863 
00864   if (m_buf) {
00865     p = m_buf;
00866     e = &m_buf[m_bufpos];
00867 
00868     while (p != e) {
00869       do {
00870         err = write(m_fd, p, e - p);
00871       } while ((err < 0) && (errno == EINTR));
00872 
00873       if (err < 0) {
00874         break;
00875       }
00876 
00877       p += err;
00878     }
00879 
00880     err = p - m_buf;
00881     memmove(m_buf, &m_buf[err], m_bufpos - err);
00882     m_bufpos -= err;
00883   }
00884 
00885   return err;
00886 }
00887 
00888 char *
00889 FileImpl::fgets(char *buf, int length)
00890 {
00891   char *e;
00892   int pos;
00893 
00894   if (length == 0) {
00895     return NULL;
00896   }
00897 
00898   if (!m_buf || (m_bufpos < (length - 1))) {
00899     pos = m_bufpos;
00900 
00901     fread(NULL, length - 1);
00902 
00903     if (!m_bufpos && (pos == m_bufpos)) {
00904       return NULL;
00905     }
00906   }
00907 
00908   e = (char *) memchr(m_buf, '\n', m_bufpos);
00909   if (e) {
00910     e += 1;
00911     if (length > (e - m_buf + 1)) {
00912       length = e - m_buf + 1;
00913     }
00914   }
00915 
00916   pos = fread(buf, length - 1);
00917   buf[pos] = '\0';
00918 
00919   return buf;
00920 }
00921 
00922 ////////////////////////////////////////////////////////////////////
00923 //
00924 // INKContInternal
00925 //
00926 ////////////////////////////////////////////////////////////////////
00927 
00928 INKContInternal::INKContInternal()
00929   : DummyVConnection(NULL), mdata(NULL), m_event_func(NULL), m_event_count(0), m_closed(1), m_deletable(0),
00930     m_deleted(0), m_free_magic(INKCONT_INTERN_MAGIC_ALIVE)
00931 { }
00932 
00933 INKContInternal::INKContInternal(TSEventFunc funcp, TSMutex mutexp)
00934   : DummyVConnection((ProxyMutex *) mutexp),
00935     mdata(NULL), m_event_func(funcp), m_event_count(0), m_closed(1), m_deletable(0), m_deleted(0),
00936     m_free_magic(INKCONT_INTERN_MAGIC_ALIVE)
00937 {
00938   SET_HANDLER(&INKContInternal::handle_event);
00939 }
00940 
00941 void
00942 INKContInternal::init(TSEventFunc funcp, TSMutex mutexp)
00943 {
00944   SET_HANDLER(&INKContInternal::handle_event);
00945 
00946   mutex = (ProxyMutex *) mutexp;
00947   m_event_func = funcp;
00948 }
00949 
00950 void
00951 INKContInternal::destroy()
00952 {
00953   if (m_free_magic == INKCONT_INTERN_MAGIC_DEAD) {
00954     ink_release_assert(!"Plugin tries to use a continuation which is deleted");
00955   }
00956   m_deleted = 1;
00957   if (m_deletable) {
00958     this->mutex = NULL;
00959     m_free_magic = INKCONT_INTERN_MAGIC_DEAD;
00960     INKContAllocator.free(this);
00961   } else {
00962     // TODO: Should this schedule on some other "thread" ?
00963     // TODO: we don't care about the return action?
00964     TSContSchedule((TSCont)this, 0, TS_THREAD_POOL_DEFAULT);
00965   }
00966 }
00967 
00968 void
00969 INKContInternal::handle_event_count(int event)
00970 {
00971   if ((event == EVENT_IMMEDIATE) || (event == EVENT_INTERVAL)) {
00972     int val;
00973 
00974     m_deletable = (m_closed != 0);
00975 
00976     val = ink_atomic_increment((int *) &m_event_count, -1);
00977     if (val <= 0) {
00978       ink_assert(!"not reached");
00979     }
00980 
00981     m_deletable = m_deletable && (val == 1);
00982   }
00983 }
00984 
00985 int
00986 INKContInternal::handle_event(int event, void *edata)
00987 {
00988   if (m_free_magic == INKCONT_INTERN_MAGIC_DEAD) {
00989     ink_release_assert(!"Plugin tries to use a continuation which is deleted");
00990   }
00991   handle_event_count(event);
00992   if (m_deleted) {
00993     if (m_deletable) {
00994       this->mutex = NULL;
00995       m_free_magic = INKCONT_INTERN_MAGIC_DEAD;
00996       INKContAllocator.free(this);
00997     }
00998   } else {
00999     return m_event_func((TSCont) this, (TSEvent) event, edata);
01000   }
01001   return EVENT_DONE;
01002 }
01003 
01004 
01005 ////////////////////////////////////////////////////////////////////
01006 //
01007 // INKVConnInternal
01008 //
01009 ////////////////////////////////////////////////////////////////////
01010 
01011 INKVConnInternal::INKVConnInternal()
01012 :INKContInternal(), m_read_vio(), m_write_vio(), m_output_vc(NULL)
01013 {
01014   m_closed = 0;
01015 }
01016 
01017 INKVConnInternal::INKVConnInternal(TSEventFunc funcp, TSMutex mutexp)
01018 :INKContInternal(funcp, mutexp), m_read_vio(), m_write_vio(), m_output_vc(NULL)
01019 {
01020   m_closed = 0;
01021   SET_HANDLER(&INKVConnInternal::handle_event);
01022 }
01023 
01024 void
01025 INKVConnInternal::init(TSEventFunc funcp, TSMutex mutexp)
01026 {
01027   INKContInternal::init(funcp, mutexp);
01028   SET_HANDLER(&INKVConnInternal::handle_event);
01029 }
01030 
01031 void
01032 INKVConnInternal::destroy()
01033 {
01034   m_deleted = 1;
01035   if (m_deletable) {
01036     this->mutex = NULL;
01037     m_read_vio.set_continuation(NULL);
01038     m_write_vio.set_continuation(NULL);
01039     INKVConnAllocator.free(this);
01040   }
01041 }
01042 
01043 int
01044 INKVConnInternal::handle_event(int event, void *edata)
01045 {
01046   handle_event_count(event);
01047   if (m_deleted) {
01048     if (m_deletable) {
01049       this->mutex = NULL;
01050       m_read_vio.set_continuation(NULL);
01051       m_write_vio.set_continuation(NULL);
01052       INKVConnAllocator.free(this);
01053     }
01054   } else {
01055     return m_event_func((TSCont) this, (TSEvent) event, edata);
01056   }
01057   return EVENT_DONE;
01058 }
01059 
01060 VIO *
01061 INKVConnInternal::do_io_read(Continuation *c, int64_t nbytes, MIOBuffer *buf)
01062 {
01063   m_read_vio.buffer.writer_for(buf);
01064   m_read_vio.op = VIO::READ;
01065   m_read_vio.set_continuation(c);
01066   m_read_vio.nbytes = nbytes;
01067   m_read_vio.ndone = 0;
01068   m_read_vio.vc_server = this;
01069 
01070   if (ink_atomic_increment((int *) &m_event_count, 1) < 0) {
01071     ink_assert(!"not reached");
01072   }
01073   eventProcessor.schedule_imm(this, ET_NET);
01074 
01075   return &m_read_vio;
01076 }
01077 
01078 VIO *
01079 INKVConnInternal::do_io_write(Continuation *c, int64_t nbytes, IOBufferReader *buf, bool owner)
01080 {
01081   ink_assert(!owner);
01082   m_write_vio.buffer.reader_for(buf);
01083   m_write_vio.op = VIO::WRITE;
01084   m_write_vio.set_continuation(c);
01085   m_write_vio.nbytes = nbytes;
01086   m_write_vio.ndone = 0;
01087   m_write_vio.vc_server = this;
01088 
01089   if (m_write_vio.buffer.reader()->read_avail() > 0) {
01090     if (ink_atomic_increment((int *) &m_event_count, 1) < 0) {
01091       ink_assert(!"not reached");
01092     }
01093     eventProcessor.schedule_imm(this, ET_NET);
01094   }
01095 
01096   return &m_write_vio;
01097 }
01098 
01099 void
01100 INKVConnInternal::do_io_transform(VConnection *vc)
01101 {
01102   m_output_vc = vc;
01103 }
01104 
01105 void
01106 INKVConnInternal::do_io_close(int error)
01107 {
01108   if (ink_atomic_increment((int *) &m_event_count, 1) < 0) {
01109     ink_assert(!"not reached");
01110   }
01111 
01112   INK_WRITE_MEMORY_BARRIER;
01113 
01114   if (error != -1) {
01115     lerrno = error;
01116     m_closed = TS_VC_CLOSE_ABORT;
01117   } else {
01118     m_closed = TS_VC_CLOSE_NORMAL;
01119   }
01120 
01121   m_read_vio.op = VIO::NONE;
01122   m_read_vio.buffer.clear();
01123 
01124   m_write_vio.op = VIO::NONE;
01125   m_write_vio.buffer.clear();
01126 
01127   if (m_output_vc) {
01128     m_output_vc->do_io_close(error);
01129   }
01130 
01131   eventProcessor.schedule_imm(this, ET_NET);
01132 }
01133 
01134 void
01135 INKVConnInternal::do_io_shutdown(ShutdownHowTo_t howto)
01136 {
01137   if ((howto == IO_SHUTDOWN_READ) || (howto == IO_SHUTDOWN_READWRITE)) {
01138     m_read_vio.op = VIO::NONE;
01139     m_read_vio.buffer.clear();
01140   }
01141 
01142   if ((howto == IO_SHUTDOWN_WRITE) || (howto == IO_SHUTDOWN_READWRITE)) {
01143     m_write_vio.op = VIO::NONE;
01144     m_write_vio.buffer.clear();
01145   }
01146 
01147   if (ink_atomic_increment((int *) &m_event_count, 1) < 0) {
01148     ink_assert(!"not reached");
01149   }
01150   eventProcessor.schedule_imm(this, ET_NET);
01151 }
01152 
01153 void
01154 INKVConnInternal::reenable(VIO */* vio ATS_UNUSED */)
01155 {
01156   if (ink_atomic_increment((int *) &m_event_count, 1) < 0) {
01157     ink_assert(!"not reached");
01158   }
01159   eventProcessor.schedule_imm(this, ET_NET);
01160 }
01161 
01162 void
01163 INKVConnInternal::retry(unsigned int delay)
01164 {
01165   if (ink_atomic_increment((int *) &m_event_count, 1) < 0) {
01166     ink_assert(!"not reached");
01167   }
01168   mutex->thread_holding->schedule_in(this, HRTIME_MSECONDS(delay));
01169 }
01170 
01171 bool
01172 INKVConnInternal::get_data(int id, void *data)
01173 {
01174   switch (id) {
01175   case TS_API_DATA_READ_VIO:
01176     *((TSVIO *) data) = reinterpret_cast<TSVIO>(&m_read_vio);
01177     return true;
01178   case TS_API_DATA_WRITE_VIO:
01179     *((TSVIO *) data) = reinterpret_cast<TSVIO>(&m_write_vio);
01180     return true;
01181   case TS_API_DATA_OUTPUT_VC:
01182     *((TSVConn *) data) = reinterpret_cast<TSVConn>(m_output_vc);
01183     return true;
01184   case TS_API_DATA_CLOSED:
01185     *((int *) data) = m_closed;
01186     return true;
01187   default:
01188     return INKContInternal::get_data(id, data);
01189   }
01190 }
01191 
01192 bool
01193 INKVConnInternal::set_data(int id, void *data)
01194 {
01195   switch (id) {
01196   case TS_API_DATA_OUTPUT_VC:
01197     m_output_vc = (VConnection *) data;
01198     return true;
01199   default:
01200     return INKContInternal::set_data(id, data);
01201   }
01202 }
01203 
01204 ////////////////////////////////////////////////////////////////////
01205 //
01206 // APIHook, APIHooks, HttpAPIHooks
01207 //
01208 ////////////////////////////////////////////////////////////////////
01209 
01210 int
01211 APIHook::invoke(int event, void *edata)
01212 {
01213   if ((event == EVENT_IMMEDIATE) || (event == EVENT_INTERVAL)) {
01214     if (ink_atomic_increment((int *) &m_cont->m_event_count, 1) < 0) {
01215       ink_assert(!"not reached");
01216     }
01217   }
01218   return m_cont->handleEvent(event, edata);
01219 }
01220 
01221 APIHook *
01222 APIHook::next() const
01223 {
01224   return m_link.next;
01225 }
01226 
01227 
01228 void
01229 APIHooks::prepend(INKContInternal *cont)
01230 {
01231   APIHook *api_hook;
01232 
01233   api_hook = apiHookAllocator.alloc();
01234   api_hook->m_cont = cont;
01235 
01236   m_hooks.push(api_hook);
01237 }
01238 
01239 void
01240 APIHooks::append(INKContInternal *cont)
01241 {
01242   APIHook *api_hook;
01243 
01244   api_hook = apiHookAllocator.alloc();
01245   api_hook->m_cont = cont;
01246 
01247   m_hooks.enqueue(api_hook);
01248 }
01249 
01250 APIHook *
01251 APIHooks::get() const
01252 {
01253   return m_hooks.head;
01254 }
01255 
01256 void
01257 APIHooks::clear()
01258 {
01259   APIHook* hook;
01260   while (0 != (hook = m_hooks.pop())) {
01261     apiHookAllocator.free(hook);
01262   }
01263 }
01264 
01265 ////////////////////////////////////////////////////////////////////
01266 //
01267 // ConfigUpdateCbTable
01268 //
01269 ////////////////////////////////////////////////////////////////////
01270 
01271 ConfigUpdateCbTable::ConfigUpdateCbTable()
01272 {
01273   cb_table = ink_hash_table_create(InkHashTableKeyType_String);
01274 }
01275 
01276 ConfigUpdateCbTable::~ConfigUpdateCbTable()
01277 {
01278   ink_assert(cb_table != NULL);
01279 
01280   ink_hash_table_destroy(cb_table);
01281 }
01282 
01283 void
01284 ConfigUpdateCbTable::insert(INKContInternal *contp, const char *name)
01285 {
01286   ink_assert(cb_table != NULL);
01287 
01288   if (contp && name)
01289     ink_hash_table_insert(cb_table, (InkHashTableKey) name, (InkHashTableValue) contp);
01290 }
01291 
01292 void
01293 ConfigUpdateCbTable::invoke(const char *name)
01294 {
01295   ink_assert(cb_table != NULL);
01296 
01297   InkHashTableIteratorState ht_iter;
01298   InkHashTableEntry *ht_entry;
01299   INKContInternal *contp;
01300 
01301   if (name != NULL) {
01302     if (strcmp(name, "*") == 0) {
01303       ht_entry = ink_hash_table_iterator_first(cb_table, &ht_iter);
01304       while (ht_entry != NULL) {
01305         contp = (INKContInternal *)ink_hash_table_entry_value(cb_table, ht_entry);
01306         ink_assert(contp != NULL);
01307         invoke(contp);
01308         ht_entry = ink_hash_table_iterator_next(cb_table, &ht_iter);
01309       }
01310     } else {
01311       ht_entry = ink_hash_table_lookup_entry(cb_table, (InkHashTableKey) name);
01312       if (ht_entry != NULL) {
01313         contp = (INKContInternal *) ink_hash_table_entry_value(cb_table, ht_entry);
01314         ink_assert(contp != NULL);
01315         invoke(contp);
01316       }
01317     }
01318   }
01319 }
01320 
01321 void
01322 ConfigUpdateCbTable::invoke(INKContInternal *contp)
01323 {
01324   eventProcessor.schedule_imm(new ConfigUpdateCallback(contp), ET_TASK);
01325 }
01326 
01327 ////////////////////////////////////////////////////////////////////
01328 //
01329 // api_init
01330 //
01331 ////////////////////////////////////////////////////////////////////
01332 
01333 void
01334 api_init()
01335 {
01336   // HDR FIX ME
01337 
01338   static int init = 1;
01339 
01340   if (init) {
01341     init = 0;
01342 
01343 #ifndef UNSAFE_FORCE_MUTEX
01344     ink_mutex_init(&big_mux, "APIMongoMutex");
01345 #endif
01346 
01347     /* URL schemes */
01348     TS_URL_SCHEME_FILE = URL_SCHEME_FILE;
01349     TS_URL_SCHEME_FTP = URL_SCHEME_FTP;
01350     TS_URL_SCHEME_GOPHER = URL_SCHEME_GOPHER;
01351     TS_URL_SCHEME_HTTP = URL_SCHEME_HTTP;
01352     TS_URL_SCHEME_HTTPS = URL_SCHEME_HTTPS;
01353     TS_URL_SCHEME_MAILTO = URL_SCHEME_MAILTO;
01354     TS_URL_SCHEME_NEWS = URL_SCHEME_NEWS;
01355     TS_URL_SCHEME_NNTP = URL_SCHEME_NNTP;
01356     TS_URL_SCHEME_PROSPERO = URL_SCHEME_PROSPERO;
01357     TS_URL_SCHEME_TELNET = URL_SCHEME_TELNET;
01358     TS_URL_SCHEME_WAIS = URL_SCHEME_WAIS;
01359 
01360     TS_URL_LEN_FILE = URL_LEN_FILE;
01361     TS_URL_LEN_FTP = URL_LEN_FTP;
01362     TS_URL_LEN_GOPHER = URL_LEN_GOPHER;
01363     TS_URL_LEN_HTTP = URL_LEN_HTTP;
01364     TS_URL_LEN_HTTPS = URL_LEN_HTTPS;
01365     TS_URL_LEN_MAILTO = URL_LEN_MAILTO;
01366     TS_URL_LEN_NEWS = URL_LEN_NEWS;
01367     TS_URL_LEN_NNTP = URL_LEN_NNTP;
01368     TS_URL_LEN_PROSPERO = URL_LEN_PROSPERO;
01369     TS_URL_LEN_TELNET = URL_LEN_TELNET;
01370     TS_URL_LEN_WAIS = URL_LEN_WAIS;
01371 
01372     /* MIME fields */
01373     TS_MIME_FIELD_ACCEPT = MIME_FIELD_ACCEPT;
01374     TS_MIME_FIELD_ACCEPT_CHARSET = MIME_FIELD_ACCEPT_CHARSET;
01375     TS_MIME_FIELD_ACCEPT_ENCODING = MIME_FIELD_ACCEPT_ENCODING;
01376     TS_MIME_FIELD_ACCEPT_LANGUAGE = MIME_FIELD_ACCEPT_LANGUAGE;
01377     TS_MIME_FIELD_ACCEPT_RANGES = MIME_FIELD_ACCEPT_RANGES;
01378     TS_MIME_FIELD_AGE = MIME_FIELD_AGE;
01379     TS_MIME_FIELD_ALLOW = MIME_FIELD_ALLOW;
01380     TS_MIME_FIELD_APPROVED = MIME_FIELD_APPROVED;
01381     TS_MIME_FIELD_AUTHORIZATION = MIME_FIELD_AUTHORIZATION;
01382     TS_MIME_FIELD_BYTES = MIME_FIELD_BYTES;
01383     TS_MIME_FIELD_CACHE_CONTROL = MIME_FIELD_CACHE_CONTROL;
01384     TS_MIME_FIELD_CLIENT_IP = MIME_FIELD_CLIENT_IP;
01385     TS_MIME_FIELD_CONNECTION = MIME_FIELD_CONNECTION;
01386     TS_MIME_FIELD_CONTENT_BASE = MIME_FIELD_CONTENT_BASE;
01387     TS_MIME_FIELD_CONTENT_ENCODING = MIME_FIELD_CONTENT_ENCODING;
01388     TS_MIME_FIELD_CONTENT_LANGUAGE = MIME_FIELD_CONTENT_LANGUAGE;
01389     TS_MIME_FIELD_CONTENT_LENGTH = MIME_FIELD_CONTENT_LENGTH;
01390     TS_MIME_FIELD_CONTENT_LOCATION = MIME_FIELD_CONTENT_LOCATION;
01391     TS_MIME_FIELD_CONTENT_MD5 = MIME_FIELD_CONTENT_MD5;
01392     TS_MIME_FIELD_CONTENT_RANGE = MIME_FIELD_CONTENT_RANGE;
01393     TS_MIME_FIELD_CONTENT_TYPE = MIME_FIELD_CONTENT_TYPE;
01394     TS_MIME_FIELD_CONTROL = MIME_FIELD_CONTROL;
01395     TS_MIME_FIELD_COOKIE = MIME_FIELD_COOKIE;
01396     TS_MIME_FIELD_DATE = MIME_FIELD_DATE;
01397     TS_MIME_FIELD_DISTRIBUTION = MIME_FIELD_DISTRIBUTION;
01398     TS_MIME_FIELD_ETAG = MIME_FIELD_ETAG;
01399     TS_MIME_FIELD_EXPECT = MIME_FIELD_EXPECT;
01400     TS_MIME_FIELD_EXPIRES = MIME_FIELD_EXPIRES;
01401     TS_MIME_FIELD_FOLLOWUP_TO = MIME_FIELD_FOLLOWUP_TO;
01402     TS_MIME_FIELD_FROM = MIME_FIELD_FROM;
01403     TS_MIME_FIELD_HOST = MIME_FIELD_HOST;
01404     TS_MIME_FIELD_IF_MATCH = MIME_FIELD_IF_MATCH;
01405     TS_MIME_FIELD_IF_MODIFIED_SINCE = MIME_FIELD_IF_MODIFIED_SINCE;
01406     TS_MIME_FIELD_IF_NONE_MATCH = MIME_FIELD_IF_NONE_MATCH;
01407     TS_MIME_FIELD_IF_RANGE = MIME_FIELD_IF_RANGE;
01408     TS_MIME_FIELD_IF_UNMODIFIED_SINCE = MIME_FIELD_IF_UNMODIFIED_SINCE;
01409     TS_MIME_FIELD_KEEP_ALIVE = MIME_FIELD_KEEP_ALIVE;
01410     TS_MIME_FIELD_KEYWORDS = MIME_FIELD_KEYWORDS;
01411     TS_MIME_FIELD_LAST_MODIFIED = MIME_FIELD_LAST_MODIFIED;
01412     TS_MIME_FIELD_LINES = MIME_FIELD_LINES;
01413     TS_MIME_FIELD_LOCATION = MIME_FIELD_LOCATION;
01414     TS_MIME_FIELD_MAX_FORWARDS = MIME_FIELD_MAX_FORWARDS;
01415     TS_MIME_FIELD_MESSAGE_ID = MIME_FIELD_MESSAGE_ID;
01416     TS_MIME_FIELD_NEWSGROUPS = MIME_FIELD_NEWSGROUPS;
01417     TS_MIME_FIELD_ORGANIZATION = MIME_FIELD_ORGANIZATION;
01418     TS_MIME_FIELD_PATH = MIME_FIELD_PATH;
01419     TS_MIME_FIELD_PRAGMA = MIME_FIELD_PRAGMA;
01420     TS_MIME_FIELD_PROXY_AUTHENTICATE = MIME_FIELD_PROXY_AUTHENTICATE;
01421     TS_MIME_FIELD_PROXY_AUTHORIZATION = MIME_FIELD_PROXY_AUTHORIZATION;
01422     TS_MIME_FIELD_PROXY_CONNECTION = MIME_FIELD_PROXY_CONNECTION;
01423     TS_MIME_FIELD_PUBLIC = MIME_FIELD_PUBLIC;
01424     TS_MIME_FIELD_RANGE = MIME_FIELD_RANGE;
01425     TS_MIME_FIELD_REFERENCES = MIME_FIELD_REFERENCES;
01426     TS_MIME_FIELD_REFERER = MIME_FIELD_REFERER;
01427     TS_MIME_FIELD_REPLY_TO = MIME_FIELD_REPLY_TO;
01428     TS_MIME_FIELD_RETRY_AFTER = MIME_FIELD_RETRY_AFTER;
01429     TS_MIME_FIELD_SENDER = MIME_FIELD_SENDER;
01430     TS_MIME_FIELD_SERVER = MIME_FIELD_SERVER;
01431     TS_MIME_FIELD_SET_COOKIE = MIME_FIELD_SET_COOKIE;
01432     TS_MIME_FIELD_STRICT_TRANSPORT_SECURITY = MIME_FIELD_STRICT_TRANSPORT_SECURITY;
01433     TS_MIME_FIELD_SUBJECT = MIME_FIELD_SUBJECT;
01434     TS_MIME_FIELD_SUMMARY = MIME_FIELD_SUMMARY;
01435     TS_MIME_FIELD_TE = MIME_FIELD_TE;
01436     TS_MIME_FIELD_TRANSFER_ENCODING = MIME_FIELD_TRANSFER_ENCODING;
01437     TS_MIME_FIELD_UPGRADE = MIME_FIELD_UPGRADE;
01438     TS_MIME_FIELD_USER_AGENT = MIME_FIELD_USER_AGENT;
01439     TS_MIME_FIELD_VARY = MIME_FIELD_VARY;
01440     TS_MIME_FIELD_VIA = MIME_FIELD_VIA;
01441     TS_MIME_FIELD_WARNING = MIME_FIELD_WARNING;
01442     TS_MIME_FIELD_WWW_AUTHENTICATE = MIME_FIELD_WWW_AUTHENTICATE;
01443     TS_MIME_FIELD_XREF = MIME_FIELD_XREF;
01444     TS_MIME_FIELD_X_FORWARDED_FOR = MIME_FIELD_X_FORWARDED_FOR;
01445 
01446 
01447     TS_MIME_LEN_ACCEPT = MIME_LEN_ACCEPT;
01448     TS_MIME_LEN_ACCEPT_CHARSET = MIME_LEN_ACCEPT_CHARSET;
01449     TS_MIME_LEN_ACCEPT_ENCODING = MIME_LEN_ACCEPT_ENCODING;
01450     TS_MIME_LEN_ACCEPT_LANGUAGE = MIME_LEN_ACCEPT_LANGUAGE;
01451     TS_MIME_LEN_ACCEPT_RANGES = MIME_LEN_ACCEPT_RANGES;
01452     TS_MIME_LEN_AGE = MIME_LEN_AGE;
01453     TS_MIME_LEN_ALLOW = MIME_LEN_ALLOW;
01454     TS_MIME_LEN_APPROVED = MIME_LEN_APPROVED;
01455     TS_MIME_LEN_AUTHORIZATION = MIME_LEN_AUTHORIZATION;
01456     TS_MIME_LEN_BYTES = MIME_LEN_BYTES;
01457     TS_MIME_LEN_CACHE_CONTROL = MIME_LEN_CACHE_CONTROL;
01458     TS_MIME_LEN_CLIENT_IP = MIME_LEN_CLIENT_IP;
01459     TS_MIME_LEN_CONNECTION = MIME_LEN_CONNECTION;
01460     TS_MIME_LEN_CONTENT_BASE = MIME_LEN_CONTENT_BASE;
01461     TS_MIME_LEN_CONTENT_ENCODING = MIME_LEN_CONTENT_ENCODING;
01462     TS_MIME_LEN_CONTENT_LANGUAGE = MIME_LEN_CONTENT_LANGUAGE;
01463     TS_MIME_LEN_CONTENT_LENGTH = MIME_LEN_CONTENT_LENGTH;
01464     TS_MIME_LEN_CONTENT_LOCATION = MIME_LEN_CONTENT_LOCATION;
01465     TS_MIME_LEN_CONTENT_MD5 = MIME_LEN_CONTENT_MD5;
01466     TS_MIME_LEN_CONTENT_RANGE = MIME_LEN_CONTENT_RANGE;
01467     TS_MIME_LEN_CONTENT_TYPE = MIME_LEN_CONTENT_TYPE;
01468     TS_MIME_LEN_CONTROL = MIME_LEN_CONTROL;
01469     TS_MIME_LEN_COOKIE = MIME_LEN_COOKIE;
01470     TS_MIME_LEN_DATE = MIME_LEN_DATE;
01471     TS_MIME_LEN_DISTRIBUTION = MIME_LEN_DISTRIBUTION;
01472     TS_MIME_LEN_ETAG = MIME_LEN_ETAG;
01473     TS_MIME_LEN_EXPECT = MIME_LEN_EXPECT;
01474     TS_MIME_LEN_EXPIRES = MIME_LEN_EXPIRES;
01475     TS_MIME_LEN_FOLLOWUP_TO = MIME_LEN_FOLLOWUP_TO;
01476     TS_MIME_LEN_FROM = MIME_LEN_FROM;
01477     TS_MIME_LEN_HOST = MIME_LEN_HOST;
01478     TS_MIME_LEN_IF_MATCH = MIME_LEN_IF_MATCH;
01479     TS_MIME_LEN_IF_MODIFIED_SINCE = MIME_LEN_IF_MODIFIED_SINCE;
01480     TS_MIME_LEN_IF_NONE_MATCH = MIME_LEN_IF_NONE_MATCH;
01481     TS_MIME_LEN_IF_RANGE = MIME_LEN_IF_RANGE;
01482     TS_MIME_LEN_IF_UNMODIFIED_SINCE = MIME_LEN_IF_UNMODIFIED_SINCE;
01483     TS_MIME_LEN_KEEP_ALIVE = MIME_LEN_KEEP_ALIVE;
01484     TS_MIME_LEN_KEYWORDS = MIME_LEN_KEYWORDS;
01485     TS_MIME_LEN_LAST_MODIFIED = MIME_LEN_LAST_MODIFIED;
01486     TS_MIME_LEN_LINES = MIME_LEN_LINES;
01487     TS_MIME_LEN_LOCATION = MIME_LEN_LOCATION;
01488     TS_MIME_LEN_MAX_FORWARDS = MIME_LEN_MAX_FORWARDS;
01489     TS_MIME_LEN_MESSAGE_ID = MIME_LEN_MESSAGE_ID;
01490     TS_MIME_LEN_NEWSGROUPS = MIME_LEN_NEWSGROUPS;
01491     TS_MIME_LEN_ORGANIZATION = MIME_LEN_ORGANIZATION;
01492     TS_MIME_LEN_PATH = MIME_LEN_PATH;
01493     TS_MIME_LEN_PRAGMA = MIME_LEN_PRAGMA;
01494     TS_MIME_LEN_PROXY_AUTHENTICATE = MIME_LEN_PROXY_AUTHENTICATE;
01495     TS_MIME_LEN_PROXY_AUTHORIZATION = MIME_LEN_PROXY_AUTHORIZATION;
01496     TS_MIME_LEN_PROXY_CONNECTION = MIME_LEN_PROXY_CONNECTION;
01497     TS_MIME_LEN_PUBLIC = MIME_LEN_PUBLIC;
01498     TS_MIME_LEN_RANGE = MIME_LEN_RANGE;
01499     TS_MIME_LEN_REFERENCES = MIME_LEN_REFERENCES;
01500     TS_MIME_LEN_REFERER = MIME_LEN_REFERER;
01501     TS_MIME_LEN_REPLY_TO = MIME_LEN_REPLY_TO;
01502     TS_MIME_LEN_RETRY_AFTER = MIME_LEN_RETRY_AFTER;
01503     TS_MIME_LEN_SENDER = MIME_LEN_SENDER;
01504     TS_MIME_LEN_SERVER = MIME_LEN_SERVER;
01505     TS_MIME_LEN_SET_COOKIE = MIME_LEN_SET_COOKIE;
01506     TS_MIME_LEN_STRICT_TRANSPORT_SECURITY = MIME_LEN_STRICT_TRANSPORT_SECURITY;
01507     TS_MIME_LEN_SUBJECT = MIME_LEN_SUBJECT;
01508     TS_MIME_LEN_SUMMARY = MIME_LEN_SUMMARY;
01509     TS_MIME_LEN_TE = MIME_LEN_TE;
01510     TS_MIME_LEN_TRANSFER_ENCODING = MIME_LEN_TRANSFER_ENCODING;
01511     TS_MIME_LEN_UPGRADE = MIME_LEN_UPGRADE;
01512     TS_MIME_LEN_USER_AGENT = MIME_LEN_USER_AGENT;
01513     TS_MIME_LEN_VARY = MIME_LEN_VARY;
01514     TS_MIME_LEN_VIA = MIME_LEN_VIA;
01515     TS_MIME_LEN_WARNING = MIME_LEN_WARNING;
01516     TS_MIME_LEN_WWW_AUTHENTICATE = MIME_LEN_WWW_AUTHENTICATE;
01517     TS_MIME_LEN_XREF = MIME_LEN_XREF;
01518     TS_MIME_LEN_X_FORWARDED_FOR = MIME_LEN_X_FORWARDED_FOR;
01519 
01520 
01521     /* HTTP methods */
01522     TS_HTTP_METHOD_CONNECT = HTTP_METHOD_CONNECT;
01523     TS_HTTP_METHOD_DELETE = HTTP_METHOD_DELETE;
01524     TS_HTTP_METHOD_GET = HTTP_METHOD_GET;
01525     TS_HTTP_METHOD_HEAD = HTTP_METHOD_HEAD;
01526     TS_HTTP_METHOD_ICP_QUERY = HTTP_METHOD_ICP_QUERY;
01527     TS_HTTP_METHOD_OPTIONS = HTTP_METHOD_OPTIONS;
01528     TS_HTTP_METHOD_POST = HTTP_METHOD_POST;
01529     TS_HTTP_METHOD_PURGE = HTTP_METHOD_PURGE;
01530     TS_HTTP_METHOD_PUT = HTTP_METHOD_PUT;
01531     TS_HTTP_METHOD_TRACE = HTTP_METHOD_TRACE;
01532     TS_HTTP_METHOD_PUSH = HTTP_METHOD_PUSH;
01533 
01534     TS_HTTP_LEN_CONNECT = HTTP_LEN_CONNECT;
01535     TS_HTTP_LEN_DELETE = HTTP_LEN_DELETE;
01536     TS_HTTP_LEN_GET = HTTP_LEN_GET;
01537     TS_HTTP_LEN_HEAD = HTTP_LEN_HEAD;
01538     TS_HTTP_LEN_ICP_QUERY = HTTP_LEN_ICP_QUERY;
01539     TS_HTTP_LEN_OPTIONS = HTTP_LEN_OPTIONS;
01540     TS_HTTP_LEN_POST = HTTP_LEN_POST;
01541     TS_HTTP_LEN_PURGE = HTTP_LEN_PURGE;
01542     TS_HTTP_LEN_PUT = HTTP_LEN_PUT;
01543     TS_HTTP_LEN_TRACE = HTTP_LEN_TRACE;
01544     TS_HTTP_LEN_PUSH = HTTP_LEN_PUSH;
01545 
01546     /* HTTP miscellaneous values */
01547     TS_HTTP_VALUE_BYTES = HTTP_VALUE_BYTES;
01548     TS_HTTP_VALUE_CHUNKED = HTTP_VALUE_CHUNKED;
01549     TS_HTTP_VALUE_CLOSE = HTTP_VALUE_CLOSE;
01550     TS_HTTP_VALUE_COMPRESS = HTTP_VALUE_COMPRESS;
01551     TS_HTTP_VALUE_DEFLATE = HTTP_VALUE_DEFLATE;
01552     TS_HTTP_VALUE_GZIP = HTTP_VALUE_GZIP;
01553     TS_HTTP_VALUE_IDENTITY = HTTP_VALUE_IDENTITY;
01554     TS_HTTP_VALUE_KEEP_ALIVE = HTTP_VALUE_KEEP_ALIVE;
01555     TS_HTTP_VALUE_MAX_AGE = HTTP_VALUE_MAX_AGE;
01556     TS_HTTP_VALUE_MAX_STALE = HTTP_VALUE_MAX_STALE;
01557     TS_HTTP_VALUE_MIN_FRESH = HTTP_VALUE_MIN_FRESH;
01558     TS_HTTP_VALUE_MUST_REVALIDATE = HTTP_VALUE_MUST_REVALIDATE;
01559     TS_HTTP_VALUE_NONE = HTTP_VALUE_NONE;
01560     TS_HTTP_VALUE_NO_CACHE = HTTP_VALUE_NO_CACHE;
01561     TS_HTTP_VALUE_NO_STORE = HTTP_VALUE_NO_STORE;
01562     TS_HTTP_VALUE_NO_TRANSFORM = HTTP_VALUE_NO_TRANSFORM;
01563     TS_HTTP_VALUE_ONLY_IF_CACHED = HTTP_VALUE_ONLY_IF_CACHED;
01564     TS_HTTP_VALUE_PRIVATE = HTTP_VALUE_PRIVATE;
01565     TS_HTTP_VALUE_PROXY_REVALIDATE = HTTP_VALUE_PROXY_REVALIDATE;
01566     TS_HTTP_VALUE_PUBLIC = HTTP_VALUE_PUBLIC;
01567     TS_HTTP_VALUE_S_MAXAGE = HTTP_VALUE_S_MAXAGE;
01568 
01569     TS_HTTP_LEN_BYTES = HTTP_LEN_BYTES;
01570     TS_HTTP_LEN_CHUNKED = HTTP_LEN_CHUNKED;
01571     TS_HTTP_LEN_CLOSE = HTTP_LEN_CLOSE;
01572     TS_HTTP_LEN_COMPRESS = HTTP_LEN_COMPRESS;
01573     TS_HTTP_LEN_DEFLATE = HTTP_LEN_DEFLATE;
01574     TS_HTTP_LEN_GZIP = HTTP_LEN_GZIP;
01575     TS_HTTP_LEN_IDENTITY = HTTP_LEN_IDENTITY;
01576     TS_HTTP_LEN_KEEP_ALIVE = HTTP_LEN_KEEP_ALIVE;
01577     TS_HTTP_LEN_MAX_AGE = HTTP_LEN_MAX_AGE;
01578     TS_HTTP_LEN_MAX_STALE = HTTP_LEN_MAX_STALE;
01579     TS_HTTP_LEN_MIN_FRESH = HTTP_LEN_MIN_FRESH;
01580     TS_HTTP_LEN_MUST_REVALIDATE = HTTP_LEN_MUST_REVALIDATE;
01581     TS_HTTP_LEN_NONE = HTTP_LEN_NONE;
01582     TS_HTTP_LEN_NO_CACHE = HTTP_LEN_NO_CACHE;
01583     TS_HTTP_LEN_NO_STORE = HTTP_LEN_NO_STORE;
01584     TS_HTTP_LEN_NO_TRANSFORM = HTTP_LEN_NO_TRANSFORM;
01585     TS_HTTP_LEN_ONLY_IF_CACHED = HTTP_LEN_ONLY_IF_CACHED;
01586     TS_HTTP_LEN_PRIVATE = HTTP_LEN_PRIVATE;
01587     TS_HTTP_LEN_PROXY_REVALIDATE = HTTP_LEN_PROXY_REVALIDATE;
01588     TS_HTTP_LEN_PUBLIC = HTTP_LEN_PUBLIC;
01589     TS_HTTP_LEN_S_MAXAGE = HTTP_LEN_S_MAXAGE;
01590 
01591     http_global_hooks = new HttpAPIHooks;
01592     lifecycle_hooks = new LifecycleAPIHooks;
01593     global_config_cbs = new ConfigUpdateCbTable;
01594 
01595     if (TS_MAX_API_STATS > 0) {
01596       api_rsb = RecAllocateRawStatBlock(TS_MAX_API_STATS);
01597       if (NULL == api_rsb) {
01598         Warning("Can't allocate API stats block");
01599       } else {
01600         Debug("sdk", "initialized SDK stats APIs with %d slots", TS_MAX_API_STATS);
01601       }
01602     } else {
01603       api_rsb = NULL;
01604     }
01605 
01606     memset(state_arg_table, 0, sizeof(state_arg_table));
01607 
01608     // Setup the version string for returning to plugins
01609     ink_strlcpy(traffic_server_version, appVersionInfo.VersionStr, sizeof(traffic_server_version));
01610     // Extract the elements.
01611     // coverity[secure_coding]
01612     if (sscanf(traffic_server_version, "%d.%d.%d", &ts_major_version, &ts_minor_version, &ts_patch_version) != 3) {
01613       Warning("Unable to parse traffic server version string '%s'\n", traffic_server_version);
01614     }
01615   }
01616 }
01617 
01618 ////////////////////////////////////////////////////////////////////
01619 //
01620 // API memory management
01621 //
01622 ////////////////////////////////////////////////////////////////////
01623 
01624 void *
01625 _TSmalloc(size_t size, const char */* path ATS_UNUSED */)
01626 {
01627   return ats_malloc(size);
01628 }
01629 
01630 void *
01631 _TSrealloc(void *ptr, size_t size, const char */* path ATS_UNUSED */)
01632 {
01633   return ats_realloc(ptr, size);
01634 }
01635 
01636 // length has to be int64_t and not size_t, since -1 means to call strlen() to get length
01637 char *
01638 _TSstrdup(const char *str, int64_t length, const char *path)
01639 {
01640   return _xstrdup(str, length, path);
01641 }
01642 
01643 size_t
01644 _TSstrlcpy(char *dst, const char *str, size_t siz)
01645 {
01646   return ink_strlcpy(dst, str, siz);
01647 }
01648 
01649 size_t
01650 _TSstrlcat(char *dst, const char *str, size_t siz)
01651 {
01652   return ink_strlcat(dst, str, siz);
01653 }
01654 
01655 void
01656 _TSfree(void *ptr)
01657 {
01658   ats_free(ptr);
01659 }
01660 
01661 ////////////////////////////////////////////////////////////////////
01662 //
01663 // Encoding utility
01664 //
01665 ////////////////////////////////////////////////////////////////////
01666 TSReturnCode
01667 TSBase64Decode(const char *str, size_t str_len, unsigned char *dst, size_t dst_size, size_t *length)
01668 {
01669   sdk_assert(sdk_sanity_check_null_ptr((void*)str) == TS_SUCCESS);
01670   sdk_assert(sdk_sanity_check_null_ptr((void*)dst) == TS_SUCCESS);
01671 
01672   return ats_base64_decode(str, str_len, dst, dst_size, length) ? TS_SUCCESS : TS_ERROR;
01673 }
01674 
01675 TSReturnCode
01676 TSBase64Encode(const char *str, size_t str_len, char *dst, size_t dst_size, size_t *length)
01677 {
01678   sdk_assert(sdk_sanity_check_null_ptr((void*)str) == TS_SUCCESS);
01679   sdk_assert(sdk_sanity_check_null_ptr((void*)dst) == TS_SUCCESS);
01680 
01681   return ats_base64_encode(str, str_len, dst, dst_size, length) ? TS_SUCCESS : TS_ERROR;
01682 }
01683 
01684 ////////////////////////////////////////////////////////////////////
01685 //
01686 // API utility routines
01687 //
01688 ////////////////////////////////////////////////////////////////////
01689 
01690 unsigned int
01691 TSrandom()
01692 {
01693   return this_ethread()->generator.random();
01694 }
01695 
01696 double
01697 TSdrandom()
01698 {
01699   return this_ethread()->generator.drandom();
01700 }
01701 
01702 ink_hrtime
01703 TShrtime()
01704 {
01705   return ink_get_based_hrtime();
01706 }
01707 
01708 ////////////////////////////////////////////////////////////////////
01709 //
01710 // API install and plugin locations
01711 //
01712 ////////////////////////////////////////////////////////////////////
01713 
01714 const char *
01715 TSInstallDirGet(void)
01716 {
01717   return Layout::get()->prefix;
01718 }
01719 
01720 const char *
01721 TSConfigDirGet(void)
01722 {
01723   return Layout::get()->sysconfdir;
01724 }
01725 
01726 const char *
01727 TSTrafficServerVersionGet(void)
01728 {
01729   return traffic_server_version;
01730 }
01731 
01732 int TSTrafficServerVersionGetMajor() { return ts_major_version; }
01733 int TSTrafficServerVersionGetMinor() { return ts_minor_version; }
01734 int TSTrafficServerVersionGetPatch() { return ts_patch_version; }
01735 
01736 const char *
01737 TSPluginDirGet(void)
01738 {
01739   static char path[PATH_NAME_MAX + 1] = "";
01740 
01741   if (*path == '\0') {
01742     char * plugin_dir = RecConfigReadPrefixPath("proxy.config.plugin.plugin_dir");
01743     ink_strlcpy(path, plugin_dir, sizeof(path));
01744     ats_free(plugin_dir);
01745   }
01746 
01747   return path;
01748 }
01749 
01750 ////////////////////////////////////////////////////////////////////
01751 //
01752 // Plugin registration
01753 //
01754 ////////////////////////////////////////////////////////////////////
01755 
01756 TSReturnCode
01757 TSPluginRegister(TSSDKVersion sdk_version, TSPluginRegistrationInfo *plugin_info)
01758 {
01759   PluginSDKVersion version = (PluginSDKVersion)sdk_version;
01760 
01761   if (!plugin_reg_current)
01762     return TS_ERROR;
01763 
01764   sdk_assert(sdk_sanity_check_null_ptr((void*) plugin_info) == TS_SUCCESS);
01765 
01766   plugin_reg_current->plugin_registered = true;
01767 
01768   // We're compatible only within the 3.x release
01769   if (version >= PLUGIN_SDK_VERSION_3_0 && version < PLUGIN_SDK_VERSION_4_0) {
01770     plugin_reg_current->sdk_version = version;
01771   } else {
01772     plugin_reg_current->sdk_version = PLUGIN_SDK_VERSION_UNKNOWN;
01773   }
01774 
01775   if (plugin_info->plugin_name) {
01776     plugin_reg_current->plugin_name = ats_strdup(plugin_info->plugin_name);
01777   }
01778 
01779   if (plugin_info->vendor_name) {
01780     plugin_reg_current->vendor_name = ats_strdup(plugin_info->vendor_name);
01781   }
01782 
01783   if (plugin_info->support_email) {
01784     plugin_reg_current->support_email = ats_strdup(plugin_info->support_email);
01785   }
01786 
01787   return TS_SUCCESS;
01788 }
01789 
01790 ////////////////////////////////////////////////////////////////////
01791 //
01792 // API file management
01793 //
01794 ////////////////////////////////////////////////////////////////////
01795 
01796 TSFile
01797 TSfopen(const char *filename, const char *mode)
01798 {
01799   FileImpl *file;
01800 
01801   file = new FileImpl;
01802   if (!file->fopen(filename, mode)) {
01803     delete file;
01804     return NULL;
01805   }
01806 
01807   return (TSFile)file;
01808 }
01809 
01810 void
01811 TSfclose(TSFile filep)
01812 {
01813   FileImpl *file = (FileImpl *) filep;
01814   file->fclose();
01815   delete file;
01816 }
01817 
01818 size_t
01819 TSfread(TSFile filep, void *buf, size_t length)
01820 {
01821   FileImpl *file = (FileImpl *) filep;
01822   return file->fread(buf, length);
01823 }
01824 
01825 size_t
01826 TSfwrite(TSFile filep, const void *buf, size_t length)
01827 {
01828   FileImpl *file = (FileImpl *) filep;
01829   return file->fwrite(buf, length);
01830 }
01831 
01832 void
01833 TSfflush(TSFile filep)
01834 {
01835   FileImpl *file = (FileImpl *) filep;
01836   file->fflush();
01837 }
01838 
01839 char *
01840 TSfgets(TSFile filep, char *buf, size_t length)
01841 {
01842   FileImpl *file = (FileImpl *) filep;
01843   return file->fgets(buf, length);
01844 }
01845 
01846 ////////////////////////////////////////////////////////////////////
01847 //
01848 // Header component object handles
01849 //
01850 ////////////////////////////////////////////////////////////////////
01851 
01852 TSReturnCode
01853 TSHandleMLocRelease(TSMBuffer bufp, TSMLoc parent, TSMLoc mloc)
01854 {
01855   MIMEFieldSDKHandle *field_handle;
01856   HdrHeapObjImpl *obj = (HdrHeapObjImpl *) mloc;
01857 
01858   if (mloc == TS_NULL_MLOC)
01859     return TS_SUCCESS;
01860 
01861   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
01862 
01863   switch (obj->m_type) {
01864   case HDR_HEAP_OBJ_URL:
01865   case HDR_HEAP_OBJ_HTTP_HEADER:
01866   case HDR_HEAP_OBJ_MIME_HEADER:
01867     return TS_SUCCESS;
01868 
01869   case HDR_HEAP_OBJ_FIELD_SDK_HANDLE:
01870     field_handle = (MIMEFieldSDKHandle *) obj;
01871     if (sdk_sanity_check_field_handle(mloc, parent) != TS_SUCCESS)
01872       return TS_ERROR;
01873 
01874     sdk_free_field_handle(bufp, field_handle);
01875     return TS_SUCCESS;
01876 
01877   default:
01878     ink_release_assert(!"invalid mloc");
01879     return TS_ERROR;
01880   }
01881 }
01882 
01883 
01884 ////////////////////////////////////////////////////////////////////
01885 //
01886 // HdrHeaps (previously known as "Marshal Buffers")
01887 //
01888 ////////////////////////////////////////////////////////////////////
01889 
01890 // TSMBuffer: pointers to HdrHeapSDKHandle objects
01891 
01892 TSMBuffer
01893 TSMBufferCreate(void)
01894 {
01895   TSMBuffer bufp;
01896   HdrHeapSDKHandle *new_heap = new HdrHeapSDKHandle;
01897 
01898   new_heap->m_heap = new_HdrHeap();
01899   bufp = (TSMBuffer)new_heap;
01900   // TODO: Should remove this when memory allocation is guaranteed to fail.
01901   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
01902   return bufp;
01903 }
01904 
01905 TSReturnCode
01906 TSMBufferDestroy(TSMBuffer bufp)
01907 {
01908   // Allow to modify the buffer only
01909   // if bufp is modifiable. If bufp is not modifiable return
01910   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
01911   // return value of function from void to TSReturnCode.
01912   if (!isWriteable(bufp))
01913     return TS_ERROR;
01914 
01915   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
01916   HdrHeapSDKHandle *sdk_heap = (HdrHeapSDKHandle *)bufp;
01917   sdk_heap->m_heap->destroy();
01918   delete sdk_heap;
01919   return TS_SUCCESS;
01920 }
01921 
01922 ////////////////////////////////////////////////////////////////////
01923 //
01924 // URLs
01925 //
01926 ////////////////////////////////////////////////////////////////////
01927 
01928 // TSMBuffer: pointers to HdrHeapSDKHandle objects
01929 // TSMLoc:    pointers to URLImpl objects
01930 TSReturnCode
01931 TSUrlCreate(TSMBuffer bufp, TSMLoc *locp)
01932 {
01933   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
01934   sdk_assert(sdk_sanity_check_null_ptr(locp) == TS_SUCCESS);
01935 
01936   if (isWriteable(bufp)) {
01937     HdrHeap *heap = ((HdrHeapSDKHandle *) bufp)->m_heap;
01938     *locp = (TSMLoc)url_create(heap);
01939     return TS_SUCCESS;
01940   }
01941   return TS_ERROR;
01942 }
01943 
01944 TSReturnCode
01945 TSUrlDestroy(TSMBuffer /* bufp ATS_UNUSED */, TSMLoc /* url_loc ATS_UNUSED */)
01946 {
01947   return TS_SUCCESS;
01948 }
01949 
01950 TSReturnCode
01951 TSUrlClone(TSMBuffer dest_bufp, TSMBuffer src_bufp, TSMLoc src_url, TSMLoc *locp)
01952 {
01953   sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
01954   sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
01955   sdk_assert(sdk_sanity_check_url_handle(src_url) == TS_SUCCESS);
01956   sdk_assert(sdk_sanity_check_null_ptr(locp) == TS_SUCCESS);
01957 
01958   if (!isWriteable(dest_bufp))
01959     return TS_ERROR;
01960 
01961   HdrHeap *s_heap, *d_heap;
01962   URLImpl *s_url, *d_url;
01963 
01964   s_heap = ((HdrHeapSDKHandle *) src_bufp)->m_heap;
01965   d_heap = ((HdrHeapSDKHandle *) dest_bufp)->m_heap;
01966   s_url = (URLImpl *) src_url;
01967 
01968   d_url = url_copy(s_url, s_heap, d_heap, (s_heap != d_heap));
01969   *locp = (TSMLoc)d_url;
01970   return TS_SUCCESS;
01971 }
01972 
01973 TSReturnCode
01974 TSUrlCopy(TSMBuffer dest_bufp, TSMLoc dest_obj, TSMBuffer src_bufp, TSMLoc src_obj)
01975 {
01976   sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
01977   sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
01978   sdk_assert(sdk_sanity_check_url_handle(src_obj) == TS_SUCCESS);
01979   sdk_assert(sdk_sanity_check_url_handle(dest_obj) == TS_SUCCESS);
01980 
01981   if (!isWriteable(dest_bufp))
01982     return TS_ERROR;
01983 
01984   HdrHeap *s_heap, *d_heap;
01985   URLImpl *s_url, *d_url;
01986 
01987   s_heap = ((HdrHeapSDKHandle *) src_bufp)->m_heap;
01988   d_heap = ((HdrHeapSDKHandle *) dest_bufp)->m_heap;
01989   s_url = (URLImpl *) src_obj;
01990   d_url = (URLImpl *) dest_obj;
01991 
01992   url_copy_onto(s_url, s_heap, d_url, d_heap, (s_heap != d_heap));
01993   return TS_SUCCESS;
01994 }
01995 
01996 void
01997 TSUrlPrint(TSMBuffer bufp, TSMLoc obj, TSIOBuffer iobufp)
01998 {
01999   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
02000   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
02001   sdk_assert(sdk_sanity_check_iocore_structure(iobufp) == TS_SUCCESS);
02002 
02003   MIOBuffer *b = (MIOBuffer *) iobufp;
02004   IOBufferBlock *blk;
02005   int bufindex;
02006   int tmp, dumpoffset;
02007   int done;
02008   URL u;
02009 
02010   u.m_heap = ((HdrHeapSDKHandle *) bufp)->m_heap;
02011   u.m_url_impl = (URLImpl *) obj;
02012   dumpoffset = 0;
02013 
02014   do {
02015     blk = b->get_current_block();
02016     if (!blk || blk->write_avail() == 0) {
02017       b->add_block();
02018       blk = b->get_current_block();
02019     }
02020 
02021     bufindex = 0;
02022     tmp = dumpoffset;
02023 
02024     done = u.print(blk->end(), blk->write_avail(), &bufindex, &tmp);
02025 
02026     dumpoffset += bufindex;
02027     b->fill(bufindex);
02028   } while (!done);
02029 }
02030 
02031 TSParseResult
02032 TSUrlParse(TSMBuffer bufp, TSMLoc obj, const char **start, const char *end)
02033 {
02034   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
02035   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
02036   sdk_assert(sdk_sanity_check_null_ptr((void*)start) == TS_SUCCESS);
02037   sdk_assert(sdk_sanity_check_null_ptr((void*)*start) == TS_SUCCESS);
02038   sdk_assert(sdk_sanity_check_null_ptr((void*)end) == TS_SUCCESS);
02039 
02040   if (!isWriteable(bufp))
02041     return TS_PARSE_ERROR;
02042 
02043   URL u;
02044   u.m_heap = ((HdrHeapSDKHandle *) bufp)->m_heap;
02045   u.m_url_impl = (URLImpl *) obj;
02046   url_clear(u.m_url_impl);
02047   return (TSParseResult)u.parse(start, end);
02048 }
02049 
02050 int
02051 TSUrlLengthGet(TSMBuffer bufp, TSMLoc obj)
02052 {
02053   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
02054   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
02055 
02056   URLImpl *url_impl = (URLImpl *) obj;
02057   return url_length_get(url_impl);
02058 }
02059 
02060 char *
02061 TSUrlStringGet(TSMBuffer bufp, TSMLoc obj, int *length)
02062 {
02063   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
02064   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
02065   sdk_assert(sdk_sanity_check_null_ptr((void*)length) == TS_SUCCESS);
02066 
02067   URLImpl *url_impl = (URLImpl *) obj;
02068   return url_string_get(url_impl, NULL, length, NULL);
02069 }
02070 
02071 typedef const char *(URL::*URLPartGetF) (int *length);
02072 typedef void (URL::*URLPartSetF) (const char *value, int length);
02073 
02074 static const char *
02075 URLPartGet(TSMBuffer bufp, TSMLoc obj, int *length, URLPartGetF url_f)
02076 {
02077   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
02078   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
02079   sdk_assert(sdk_sanity_check_null_ptr((void*)length) == TS_SUCCESS);
02080 
02081   URL u;
02082 
02083   u.m_heap = ((HdrHeapSDKHandle *) bufp)->m_heap;
02084   u.m_url_impl = (URLImpl *) obj;
02085 
02086   return (u.*url_f)(length);
02087 }
02088 
02089 static TSReturnCode
02090 URLPartSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length, URLPartSetF url_f)
02091 {
02092   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
02093   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
02094 
02095   if (!isWriteable(bufp))
02096     return TS_ERROR;
02097 
02098   URL u;
02099   u.m_heap = ((HdrHeapSDKHandle *) bufp)->m_heap;
02100   u.m_url_impl = (URLImpl *) obj;
02101 
02102   if (!value)
02103     length = 0;
02104   else if (length < 0)
02105     length = strlen(value);
02106   (u.*url_f)(value, length);
02107 
02108   return TS_SUCCESS;
02109 }
02110 
02111 const char *
02112 TSUrlSchemeGet(TSMBuffer bufp, TSMLoc obj, int *length)
02113 {
02114   return URLPartGet(bufp, obj, length, &URL::scheme_get);
02115 }
02116 
02117 TSReturnCode
02118 TSUrlSchemeSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
02119 {
02120   return URLPartSet(bufp, obj, value, length, &URL::scheme_set);
02121 }
02122 
02123 /* Internet specific URLs */
02124 
02125 const char *
02126 TSUrlUserGet(TSMBuffer bufp, TSMLoc obj, int *length)
02127 {
02128   return URLPartGet(bufp, obj, length, &URL::user_get);
02129 }
02130 
02131 TSReturnCode
02132 TSUrlUserSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
02133 {
02134   return URLPartSet(bufp, obj, value, length, &URL::user_set);
02135 }
02136 
02137 const char *
02138 TSUrlPasswordGet(TSMBuffer bufp, TSMLoc obj, int *length)
02139 {
02140   return URLPartGet(bufp, obj, length, &URL::password_get);
02141 }
02142 
02143 TSReturnCode
02144 TSUrlPasswordSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
02145 {
02146   return URLPartSet(bufp, obj, value, length, &URL::password_set);
02147 }
02148 
02149 const char *
02150 TSUrlHostGet(TSMBuffer bufp, TSMLoc obj, int *length)
02151 {
02152   return URLPartGet(bufp, obj, length, &URL::host_get);
02153 }
02154 
02155 TSReturnCode
02156 TSUrlHostSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
02157 {
02158   return URLPartSet(bufp, obj, value, length, &URL::host_set);
02159 }
02160 
02161 int
02162 TSUrlPortGet(TSMBuffer bufp, TSMLoc obj)
02163 {
02164   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
02165   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
02166 
02167   URL u;
02168   u.m_heap = ((HdrHeapSDKHandle *) bufp)->m_heap;
02169   u.m_url_impl = (URLImpl *) obj;
02170 
02171   return u.port_get();
02172 }
02173 
02174 TSReturnCode
02175 TSUrlPortSet(TSMBuffer bufp, TSMLoc obj, int port)
02176 {
02177   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
02178   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
02179 
02180   if (!isWriteable(bufp) || (port < 0))
02181     return TS_ERROR;
02182 
02183   URL u;
02184 
02185   u.m_heap = ((HdrHeapSDKHandle *) bufp)->m_heap;
02186   u.m_url_impl = (URLImpl *) obj;
02187   u.port_set(port);
02188   return TS_SUCCESS;
02189 }
02190 
02191 /* FTP and HTTP specific URLs  */
02192 
02193 const char *
02194 TSUrlPathGet(TSMBuffer bufp, TSMLoc obj, int *length)
02195 {
02196   return URLPartGet(bufp, obj, length, &URL::path_get);
02197 }
02198 
02199 TSReturnCode
02200 TSUrlPathSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
02201 {
02202   return URLPartSet(bufp, obj, value, length, &URL::path_set);
02203 }
02204 
02205 /* FTP specific URLs */
02206 
02207 int
02208 TSUrlFtpTypeGet(TSMBuffer bufp, TSMLoc obj)
02209 {
02210   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
02211   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
02212 
02213   URL u;
02214   u.m_heap = ((HdrHeapSDKHandle *) bufp)->m_heap;
02215   u.m_url_impl = (URLImpl *) obj;
02216   return u.type_get();
02217 }
02218 
02219 TSReturnCode
02220 TSUrlFtpTypeSet(TSMBuffer bufp, TSMLoc obj, int type)
02221 {
02222   //The valid values are : 0, 65('A'), 97('a'),
02223   //69('E'), 101('e'), 73 ('I') and 105('i').
02224   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
02225   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
02226 
02227 
02228   if ((type == 0 || type=='A' || type=='E' || type=='I' || type=='a' || type=='i' || type=='e') && isWriteable(bufp)) {
02229     URL u;
02230 
02231     u.m_heap = ((HdrHeapSDKHandle *) bufp)->m_heap;
02232     u.m_url_impl = (URLImpl *) obj;
02233     u.type_set(type);
02234     return TS_SUCCESS;
02235   }
02236 
02237   return TS_ERROR;
02238 }
02239 
02240 /* HTTP specific URLs */
02241 
02242 const char *
02243 TSUrlHttpParamsGet(TSMBuffer bufp, TSMLoc obj, int *length)
02244 {
02245   return URLPartGet(bufp, obj, length, &URL::params_get);
02246 }
02247 
02248 TSReturnCode
02249 TSUrlHttpParamsSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
02250 {
02251   return URLPartSet(bufp, obj, value, length, &URL::params_set);
02252 }
02253 
02254 const char *
02255 TSUrlHttpQueryGet(TSMBuffer bufp, TSMLoc obj, int *length)
02256 {
02257   return URLPartGet(bufp, obj, length, &URL::query_get);
02258 }
02259 
02260 TSReturnCode
02261 TSUrlHttpQuerySet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
02262 {
02263   return URLPartSet(bufp, obj, value, length, &URL::query_set);
02264 }
02265 
02266 const char *
02267 TSUrlHttpFragmentGet(TSMBuffer bufp, TSMLoc obj, int *length)
02268 {
02269   return URLPartGet(bufp, obj, length, &URL::fragment_get);
02270 }
02271 
02272 TSReturnCode
02273 TSUrlHttpFragmentSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
02274 {
02275   return URLPartSet(bufp, obj, value, length, &URL::fragment_set);
02276 }
02277 
02278 // URL percent encoding
02279 TSReturnCode
02280 TSStringPercentEncode(const char* str, int str_len, char *dst, size_t dst_size, size_t *length, const unsigned char *map)
02281 {
02282   sdk_assert(sdk_sanity_check_null_ptr((void*)str) == TS_SUCCESS);
02283   sdk_assert(sdk_sanity_check_null_ptr((void*)dst) == TS_SUCCESS);
02284 
02285   int new_len; // Unfortunately, a lot of the core uses "int" for length's internally...
02286 
02287   if (str_len < 0)
02288     str_len = strlen(str);
02289 
02290   sdk_assert(str_len < static_cast<int>(dst_size));
02291 
02292   // TODO: Perhaps we should make escapify_url() deal with const properly...
02293   if (NULL == LogUtils::escapify_url(NULL, const_cast<char*>(str), str_len, &new_len, dst, dst_size, map)) {
02294     if (length)
02295       *length = 0;
02296     return TS_ERROR;
02297   }
02298 
02299   if (length)
02300     *length = new_len;
02301 
02302   return TS_SUCCESS;
02303 }
02304 
02305 TSReturnCode
02306 TSStringPercentDecode(const char *str, size_t str_len, char* dst, size_t dst_size, size_t *length)
02307 {
02308   sdk_assert(sdk_sanity_check_null_ptr((void*)str) == TS_SUCCESS);
02309   sdk_assert(sdk_sanity_check_null_ptr((void*)dst) == TS_SUCCESS);
02310 
02311   if (0 == str_len)
02312     str_len = strlen(str);
02313 
02314   // return unescapifyStr(str);
02315   char *buffer = dst;
02316   const char *src =  str;
02317   int s = 0; // State, which we don't really use
02318 
02319   // TODO: We should check for "failures" here?
02320   unescape_str(buffer, buffer+dst_size, src, src+str_len, s);
02321   *buffer = '\0';
02322   if (length)
02323     *length = (buffer - dst);
02324 
02325   return TS_SUCCESS;
02326 }
02327 
02328 TSReturnCode
02329 TSUrlPercentEncode(TSMBuffer bufp, TSMLoc obj, char *dst, size_t dst_size, size_t *length, const unsigned char *map)
02330 {
02331   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
02332   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
02333 
02334   char *url;
02335   int url_len;
02336   TSReturnCode ret;
02337   URLImpl *url_impl = (URLImpl *)obj;
02338 
02339   // TODO: at some point, it might be nice to allow this to write to a pre-allocated buffer
02340   url = url_string_get(url_impl, NULL, &url_len, NULL);
02341   ret = TSStringPercentEncode(url, url_len, dst, dst_size, length, map);
02342   ats_free(url);
02343 
02344   return ret;
02345 }
02346 
02347 
02348 ////////////////////////////////////////////////////////////////////
02349 //
02350 // MIME Headers
02351 //
02352 ////////////////////////////////////////////////////////////////////
02353 
02354 /**************/
02355 /* MimeParser */
02356 /**************/
02357 
02358 TSMimeParser
02359 TSMimeParserCreate(void)
02360 {
02361   TSMimeParser parser = reinterpret_cast<TSMimeParser>(ats_malloc(sizeof(MIMEParser)));
02362 
02363   mime_parser_init((MIMEParser *) parser);
02364   return parser;
02365 }
02366 
02367 void
02368 TSMimeParserClear(TSMimeParser parser)
02369 {
02370   sdk_assert(sdk_sanity_check_mime_parser(parser) == TS_SUCCESS);
02371 
02372   mime_parser_clear((MIMEParser *) parser);
02373 }
02374 
02375 void
02376 TSMimeParserDestroy(TSMimeParser parser)
02377 {
02378   sdk_assert(sdk_sanity_check_mime_parser(parser) == TS_SUCCESS);
02379 
02380   mime_parser_clear((MIMEParser *) parser);
02381   ats_free(parser);
02382 }
02383 
02384 /***********/
02385 /* MimeHdr */
02386 /***********/
02387 
02388 // TSMBuffer: pointers to HdrHeapSDKHandle objects
02389 // TSMLoc:    pointers to MIMEFieldSDKHandle objects
02390 
02391 TSReturnCode
02392 TSMimeHdrCreate(TSMBuffer bufp, TSMLoc *locp)
02393 {
02394   // Allow to modify the buffer only
02395   // if bufp is modifiable. If bufp is not modifiable return
02396   // TS_ERROR. If not allowed, return NULL.
02397   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
02398   sdk_assert(sdk_sanity_check_null_ptr((void*)locp) == TS_SUCCESS);
02399 
02400   if (!isWriteable(bufp))
02401     return TS_ERROR;
02402 
02403   *locp = reinterpret_cast<TSMLoc>(mime_hdr_create(((HdrHeapSDKHandle *) bufp)->m_heap));
02404   return TS_SUCCESS;
02405 }
02406 
02407 TSReturnCode
02408 TSMimeHdrDestroy(TSMBuffer bufp, TSMLoc obj)
02409 {
02410   // Allow to modify the buffer only
02411   // if bufp is modifiable. If bufp is not modifiable return
02412   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
02413   // return value of function from void to TSReturnCode.
02414   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
02415   sdk_assert((sdk_sanity_check_mime_hdr_handle(obj) == TS_SUCCESS) ||
02416              (sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS));
02417 
02418   if (!isWriteable(bufp))
02419     return TS_ERROR;
02420 
02421   MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(obj);
02422 
02423   mime_hdr_destroy(((HdrHeapSDKHandle *) bufp)->m_heap, mh);
02424   return TS_SUCCESS;
02425 }
02426 
02427 TSReturnCode
02428 TSMimeHdrClone(TSMBuffer dest_bufp, TSMBuffer src_bufp, TSMLoc src_hdr, TSMLoc *locp)
02429 {
02430   // Allow to modify the buffer only
02431   // if bufp is modifiable. If bufp is not modifiable return
02432   // TS_ERROR. If not allowed, return NULL.
02433   sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
02434   sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
02435   sdk_assert(sdk_sanity_check_mime_hdr_handle(src_hdr) == TS_SUCCESS);
02436   sdk_assert(sdk_sanity_check_http_hdr_handle(src_hdr) == TS_SUCCESS);
02437   sdk_assert(sdk_sanity_check_null_ptr((void*)locp) == TS_SUCCESS);
02438 
02439   if (!isWriteable(dest_bufp))
02440     return TS_ERROR;
02441 
02442   HdrHeap *s_heap, *d_heap;
02443   MIMEHdrImpl *s_mh, *d_mh;
02444 
02445   s_heap = ((HdrHeapSDKHandle *) src_bufp)->m_heap;
02446   d_heap = ((HdrHeapSDKHandle *) dest_bufp)->m_heap;
02447   s_mh = _hdr_mloc_to_mime_hdr_impl(src_hdr);
02448 
02449   d_mh = mime_hdr_clone(s_mh, s_heap, d_heap, (s_heap != d_heap));
02450   *locp = (TSMLoc)d_mh;
02451 
02452   return TS_SUCCESS;
02453 }
02454 
02455 TSReturnCode
02456 TSMimeHdrCopy(TSMBuffer dest_bufp, TSMLoc dest_obj, TSMBuffer src_bufp, TSMLoc src_obj)
02457 {
02458   // Allow to modify the buffer only
02459   // if bufp is modifiable. If bufp is not modifiable return
02460   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
02461   // return value of function from void to TSReturnCode.
02462   sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
02463   sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
02464   sdk_assert((sdk_sanity_check_mime_hdr_handle(src_obj) == TS_SUCCESS) ||
02465              (sdk_sanity_check_http_hdr_handle(src_obj) == TS_SUCCESS));
02466   sdk_assert((sdk_sanity_check_mime_hdr_handle(dest_obj) == TS_SUCCESS) ||
02467              (sdk_sanity_check_http_hdr_handle(dest_obj) == TS_SUCCESS));
02468 
02469   if (!isWriteable(dest_bufp))
02470     return TS_ERROR;
02471 
02472   HdrHeap *s_heap, *d_heap;
02473   MIMEHdrImpl *s_mh, *d_mh;
02474 
02475   s_heap = ((HdrHeapSDKHandle *) src_bufp)->m_heap;
02476   d_heap = ((HdrHeapSDKHandle *) dest_bufp)->m_heap;
02477   s_mh = _hdr_mloc_to_mime_hdr_impl(src_obj);
02478   d_mh = _hdr_mloc_to_mime_hdr_impl(dest_obj);
02479 
02480   mime_hdr_fields_clear(d_heap, d_mh);
02481   mime_hdr_copy_onto(s_mh, s_heap, d_mh, d_heap, (s_heap != d_heap));
02482   return TS_SUCCESS;
02483 }
02484 
02485 void
02486 TSMimeHdrPrint(TSMBuffer bufp, TSMLoc obj, TSIOBuffer iobufp)
02487 {
02488   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
02489   sdk_assert((sdk_sanity_check_mime_hdr_handle(obj) == TS_SUCCESS) ||
02490              (sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS));
02491   sdk_assert(sdk_sanity_check_iocore_structure(iobufp) == TS_SUCCESS);
02492 
02493   HdrHeap *heap = ((HdrHeapSDKHandle *) bufp)->m_heap;
02494   MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(obj);
02495   MIOBuffer *b = (MIOBuffer *) iobufp;
02496   IOBufferBlock *blk;
02497   int bufindex;
02498   int tmp, dumpoffset = 0;
02499   int done;
02500 
02501   do {
02502     blk = b->get_current_block();
02503     if (!blk || blk->write_avail() == 0) {
02504       b->add_block();
02505       blk = b->get_current_block();
02506     }
02507 
02508     bufindex = 0;
02509     tmp = dumpoffset;
02510     done = mime_hdr_print(heap, mh, blk->end(), blk->write_avail(), &bufindex, &tmp);
02511 
02512     dumpoffset += bufindex;
02513     b->fill(bufindex);
02514   } while (!done);
02515 }
02516 
02517 TSParseResult
02518 TSMimeHdrParse(TSMimeParser parser, TSMBuffer bufp, TSMLoc obj, const char **start, const char *end)
02519 {
02520   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
02521   sdk_assert((sdk_sanity_check_mime_hdr_handle(obj) == TS_SUCCESS) ||
02522              (sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS));
02523   sdk_assert(sdk_sanity_check_null_ptr((void*)start) == TS_SUCCESS);
02524   sdk_assert(sdk_sanity_check_null_ptr((void*)*start) == TS_SUCCESS);
02525   sdk_assert(sdk_sanity_check_null_ptr((void*)end) == TS_SUCCESS);
02526 
02527   if (!isWriteable(bufp))
02528     return TS_PARSE_ERROR;
02529 
02530   MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(obj);
02531 
02532   return (TSParseResult)mime_parser_parse((MIMEParser *) parser, ((HdrHeapSDKHandle *) bufp)->m_heap, mh,
02533                                           start, end, false, false);
02534 }
02535 
02536 int
02537 TSMimeHdrLengthGet(TSMBuffer bufp, TSMLoc obj)
02538 {
02539   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
02540   sdk_assert((sdk_sanity_check_mime_hdr_handle(obj) == TS_SUCCESS) ||
02541              (sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS));
02542 
02543   MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(obj);
02544   return mime_hdr_length_get(mh);
02545 }
02546 
02547 TSReturnCode
02548 TSMimeHdrFieldsClear(TSMBuffer bufp, TSMLoc obj)
02549 {
02550   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
02551   sdk_assert((sdk_sanity_check_mime_hdr_handle(obj) == TS_SUCCESS) ||
02552              (sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS));
02553 
02554   if (!isWriteable(bufp))
02555     return TS_ERROR;
02556 
02557   MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(obj);
02558 
02559   mime_hdr_fields_clear(((HdrHeapSDKHandle *) bufp)->m_heap, mh);
02560   return TS_SUCCESS;
02561 }
02562 
02563 int
02564 TSMimeHdrFieldsCount(TSMBuffer bufp, TSMLoc obj)
02565 {
02566   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
02567   sdk_assert((sdk_sanity_check_mime_hdr_handle(obj) == TS_SUCCESS) ||
02568              (sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS));
02569 
02570   MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(obj);
02571   return mime_hdr_fields_count(mh);
02572 }
02573 
02574 // The following three helper functions should not be used in plugins! Since they are not used
02575 // by plugins, there's no need to validate the input.
02576 const char *
02577 TSMimeFieldValueGet(TSMBuffer /* bufp ATS_UNUSED */, TSMLoc field_obj, int idx, int *value_len_ptr)
02578 {
02579   MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *) field_obj;
02580 
02581   if (idx >= 0) {
02582     return mime_field_value_get_comma_val(handle->field_ptr, value_len_ptr, idx);
02583   } else {
02584     return mime_field_value_get(handle->field_ptr, value_len_ptr);
02585   }
02586 
02587   *value_len_ptr = 0;
02588   return NULL;
02589 }
02590 
02591 void
02592 TSMimeFieldValueSet(TSMBuffer bufp, TSMLoc field_obj, int idx, const char *value, int length)
02593 {
02594   MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *) field_obj;
02595   HdrHeap *heap = ((HdrHeapSDKHandle *) bufp)->m_heap;
02596 
02597   if (length == -1)
02598     length = strlen(value);
02599 
02600   if (idx >= 0)
02601     mime_field_value_set_comma_val(heap, handle->mh, handle->field_ptr, idx, value, length);
02602   else
02603     mime_field_value_set(heap, handle->mh, handle->field_ptr, value, length, true);
02604 }
02605 
02606 void
02607 TSMimeFieldValueInsert(TSMBuffer bufp, TSMLoc field_obj, const char *value, int length, int idx)
02608 {
02609   MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *) field_obj;
02610   HdrHeap *heap = ((HdrHeapSDKHandle *) bufp)->m_heap;
02611 
02612   if (length == -1)
02613     length = strlen(value);
02614 
02615   mime_field_value_insert_comma_val(heap, handle->mh, handle->field_ptr, idx, value, length);
02616 }
02617 
02618 
02619 /****************/
02620 /* MimeHdrField */
02621 /****************/
02622 
02623 // TSMBuffer: pointers to HdrHeapSDKHandle objects
02624 // TSMLoc:    pointers to MIMEFieldSDKHandle objects
02625 
02626 int
02627 TSMimeHdrFieldEqual(TSMBuffer bufp, TSMLoc hdr_obj, TSMLoc field1_obj, TSMLoc field2_obj)
02628 {
02629   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
02630   sdk_assert(sdk_sanity_check_field_handle(field1_obj, hdr_obj) == TS_SUCCESS);
02631   sdk_assert(sdk_sanity_check_field_handle(field2_obj, hdr_obj) == TS_SUCCESS);
02632 
02633   MIMEFieldSDKHandle *field1_handle = (MIMEFieldSDKHandle *) field1_obj;
02634   MIMEFieldSDKHandle *field2_handle = (MIMEFieldSDKHandle *) field2_obj;
02635 
02636   if ((field1_handle == NULL) || (field2_handle == NULL))
02637     return (field1_handle == field2_handle);
02638   return (field1_handle->field_ptr == field2_handle->field_ptr);
02639 }
02640 
02641 TSMLoc
02642 TSMimeHdrFieldGet(TSMBuffer bufp, TSMLoc hdr_obj, int idx)
02643 {
02644   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
02645   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr_obj) == TS_SUCCESS) ||
02646              (sdk_sanity_check_http_hdr_handle(hdr_obj) == TS_SUCCESS));
02647   sdk_assert(idx >= 0);
02648 
02649   MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(hdr_obj);
02650   MIMEField *f = mime_hdr_field_get(mh, idx);
02651 
02652   if (f == NULL)
02653     return TS_NULL_MLOC;
02654 
02655   MIMEFieldSDKHandle *h = sdk_alloc_field_handle(bufp, mh);
02656 
02657   h->field_ptr = f;
02658   return reinterpret_cast<TSMLoc>(h);
02659 }
02660 
02661 TSMLoc
02662 TSMimeHdrFieldFind(TSMBuffer bufp, TSMLoc hdr_obj, const char *name, int length)
02663 {
02664   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
02665   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr_obj) == TS_SUCCESS) ||
02666              (sdk_sanity_check_http_hdr_handle(hdr_obj) == TS_SUCCESS));
02667   sdk_assert(sdk_sanity_check_null_ptr((void*)name) == TS_SUCCESS);
02668 
02669   if (length == -1)
02670     length = strlen(name);
02671 
02672   MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(hdr_obj);
02673   MIMEField *f = mime_hdr_field_find(mh, name, length);
02674 
02675   if (f == NULL)
02676     return TS_NULL_MLOC;
02677 
02678   MIMEFieldSDKHandle *h = sdk_alloc_field_handle(bufp, mh);
02679 
02680   h->field_ptr = f;
02681   return reinterpret_cast<TSMLoc>(h);
02682 }
02683 
02684 TSReturnCode
02685 TSMimeHdrFieldAppend(TSMBuffer bufp, TSMLoc mh_mloc, TSMLoc field_mloc)
02686 {
02687   // Allow to modify the buffer only
02688   // if bufp is modifiable. If bufp is not modifiable return
02689   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
02690   // return value of function from void to TSReturnCode.
02691   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
02692   sdk_assert((sdk_sanity_check_mime_hdr_handle(mh_mloc) == TS_SUCCESS) ||
02693              (sdk_sanity_check_http_hdr_handle(mh_mloc) == TS_SUCCESS));
02694   sdk_assert(sdk_sanity_check_field_handle(field_mloc) == TS_SUCCESS);
02695 
02696   if (!isWriteable(bufp))
02697     return TS_ERROR;
02698 
02699   MIMEField *mh_field;
02700   MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(mh_mloc);
02701   MIMEFieldSDKHandle *field_handle = (MIMEFieldSDKHandle *) field_mloc;
02702 
02703   //////////////////////////////////////////////////////////////////////
02704   // The field passed in field_mloc might have been allocated from    //
02705   // inside a MIME header (the correct way), or it might have been    //
02706   // created in isolation as a "standalone field" (the old way).      //
02707   //                                                                  //
02708   // If it's a standalone field (the associated mime header is NULL), //
02709   // then we need to now allocate a real field inside the header,     //
02710   // copy over the data, and convert the standalone field into a      //
02711   // forwarding pointer to the real field, in case it's used again    //
02712   //////////////////////////////////////////////////////////////////////
02713   if (field_handle->mh == NULL) {
02714     HdrHeap *heap = (HdrHeap *) (((HdrHeapSDKHandle *) bufp)->m_heap);
02715 
02716     // allocate a new hdr field and copy any pre-set info
02717     mh_field = mime_field_create(heap, mh);
02718 
02719     // FIX: is it safe to copy everything over?
02720     memcpy(mh_field, field_handle->field_ptr, sizeof(MIMEField));
02721 
02722     // now set up the forwarding ptr from standalone field to hdr field
02723     field_handle->mh = mh;
02724     field_handle->field_ptr = mh_field;
02725   }
02726 
02727   ink_assert(field_handle->mh == mh);
02728   ink_assert(field_handle->field_ptr->m_ptr_name);
02729 
02730   mime_hdr_field_attach(mh, field_handle->field_ptr, 1, NULL);
02731   return TS_SUCCESS;
02732 }
02733 
02734 TSReturnCode
02735 TSMimeHdrFieldRemove(TSMBuffer bufp, TSMLoc mh_mloc, TSMLoc field_mloc)
02736 {
02737   // Allow to modify the buffer only
02738   // if bufp is modifiable. If bufp is not modifiable return
02739   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
02740   // return value of function from void to TSReturnCode.
02741   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
02742   sdk_assert((sdk_sanity_check_mime_hdr_handle(mh_mloc) == TS_SUCCESS) ||
02743              (sdk_sanity_check_http_hdr_handle(mh_mloc) == TS_SUCCESS));
02744   sdk_assert(sdk_sanity_check_field_handle(field_mloc, mh_mloc) == TS_SUCCESS);
02745 
02746   if (!isWriteable(bufp))
02747     return TS_ERROR;
02748 
02749   MIMEFieldSDKHandle *field_handle = (MIMEFieldSDKHandle *) field_mloc;
02750 
02751   if (field_handle->mh != NULL) {
02752     MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(mh_mloc);
02753     ink_assert(mh == field_handle->mh);
02754     sdk_sanity_check_field_handle(field_mloc, mh_mloc);
02755     mime_hdr_field_detach(mh, field_handle->field_ptr, false);        // only detach this dup
02756   }
02757   return TS_SUCCESS;
02758 }
02759 
02760 TSReturnCode
02761 TSMimeHdrFieldDestroy(TSMBuffer bufp, TSMLoc mh_mloc, TSMLoc field_mloc)
02762 {
02763   // Allow to modify the buffer only
02764   // if bufp is modifiable. If bufp is not modifiable return
02765   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
02766   // return value of function from void to TSReturnCode.
02767   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
02768   sdk_assert((sdk_sanity_check_mime_hdr_handle(mh_mloc) == TS_SUCCESS) ||
02769              (sdk_sanity_check_http_hdr_handle(mh_mloc) == TS_SUCCESS));
02770   sdk_assert(sdk_sanity_check_field_handle(field_mloc, mh_mloc) == TS_SUCCESS);
02771 
02772   if (!isWriteable(bufp))
02773     return TS_ERROR;
02774 
02775   MIMEFieldSDKHandle *field_handle = (MIMEFieldSDKHandle *) field_mloc;
02776 
02777   if (field_handle->mh == NULL) { // NOT SUPPORTED!!
02778     ink_release_assert(!"Failed MH");
02779   } else {
02780     MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(mh_mloc);
02781     HdrHeap *heap = (HdrHeap *) (((HdrHeapSDKHandle *) bufp)->m_heap);
02782 
02783     ink_assert(mh == field_handle->mh);
02784     if (sdk_sanity_check_field_handle(field_mloc, mh_mloc) != TS_SUCCESS)
02785       return TS_ERROR;
02786 
02787     // detach and delete this field, but not all dups
02788     mime_hdr_field_delete(heap, mh, field_handle->field_ptr, false);
02789   }
02790   // for consistence, the handle will not be released here.
02791   // users will be required to do it.
02792   return TS_SUCCESS;
02793 }
02794 
02795 TSReturnCode
02796 TSMimeHdrFieldCreate(TSMBuffer bufp, TSMLoc mh_mloc, TSMLoc *locp)
02797 {
02798   // Allow to modify the buffer only
02799   // if bufp is modifiable. If bufp is not modifiable return
02800   // TS_ERROR. If not allowed, return NULL.
02801   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
02802   sdk_assert((sdk_sanity_check_mime_hdr_handle(mh_mloc) == TS_SUCCESS) ||
02803              (sdk_sanity_check_http_hdr_handle(mh_mloc) == TS_SUCCESS));
02804   sdk_assert(sdk_sanity_check_null_ptr((void*)locp) == TS_SUCCESS);
02805 
02806   if (!isWriteable(bufp))
02807     return TS_ERROR;
02808 
02809   MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(mh_mloc);
02810   HdrHeap *heap = (HdrHeap *) (((HdrHeapSDKHandle *) bufp)->m_heap);
02811   MIMEFieldSDKHandle *h = sdk_alloc_field_handle(bufp, mh);
02812 
02813   h->field_ptr = mime_field_create(heap, mh);
02814   *locp = reinterpret_cast<TSMLoc>(h);
02815   return TS_SUCCESS;
02816 }
02817 
02818 TSReturnCode
02819 TSMimeHdrFieldCreateNamed(TSMBuffer bufp, TSMLoc mh_mloc, const char *name, int name_len, TSMLoc *locp)
02820 {
02821   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
02822   sdk_assert((sdk_sanity_check_mime_hdr_handle(mh_mloc) == TS_SUCCESS) ||
02823              (sdk_sanity_check_http_hdr_handle(mh_mloc) == TS_SUCCESS));
02824   sdk_assert(sdk_sanity_check_null_ptr((void*)name) == TS_SUCCESS);
02825   sdk_assert(sdk_sanity_check_null_ptr((void*)locp) == TS_SUCCESS);
02826 
02827   if (!isWriteable(bufp))
02828     return TS_ERROR;
02829 
02830   if (name_len == -1)
02831     name_len = strlen(name);
02832 
02833   MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(mh_mloc);
02834   HdrHeap *heap = (HdrHeap *) (((HdrHeapSDKHandle *) bufp)->m_heap);
02835   MIMEFieldSDKHandle *h = sdk_alloc_field_handle(bufp, mh);
02836   h->field_ptr = mime_field_create_named(heap, mh, name, name_len);
02837   *locp = reinterpret_cast<TSMLoc>(h);
02838   return TS_SUCCESS;
02839 }
02840 
02841 TSReturnCode
02842 TSMimeHdrFieldCopy(TSMBuffer dest_bufp, TSMLoc dest_hdr, TSMLoc dest_field, TSMBuffer src_bufp, TSMLoc src_hdr, TSMLoc src_field)
02843 {
02844   // Allow to modify the buffer only
02845   // if bufp is modifiable. If bufp is not modifiable return
02846   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
02847   // return value of function from void to TSReturnCode.
02848   sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
02849   sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
02850   sdk_assert((sdk_sanity_check_mime_hdr_handle(src_hdr) == TS_SUCCESS) ||
02851              (sdk_sanity_check_http_hdr_handle(src_hdr) == TS_SUCCESS));
02852   sdk_assert((sdk_sanity_check_mime_hdr_handle(dest_hdr) == TS_SUCCESS) ||
02853              (sdk_sanity_check_http_hdr_handle(dest_hdr) == TS_SUCCESS));
02854   sdk_assert(sdk_sanity_check_field_handle(src_field, src_hdr) == TS_SUCCESS);
02855   sdk_assert(sdk_sanity_check_field_handle(dest_field, dest_hdr) == TS_SUCCESS);
02856 
02857   if (!isWriteable(dest_bufp))
02858     return TS_ERROR;
02859 
02860   bool dest_attached;
02861   MIMEFieldSDKHandle *s_handle = (MIMEFieldSDKHandle *) src_field;
02862   MIMEFieldSDKHandle *d_handle = (MIMEFieldSDKHandle *) dest_field;
02863   HdrHeap *d_heap = ((HdrHeapSDKHandle *) dest_bufp)->m_heap;
02864 
02865   // FIX: This tortuous detach/change/attach algorithm is due to the
02866   //      fact that we can't change the name of an attached header (assertion)
02867 
02868   // TODO: This is never used ... is_live() has no side effects, so this should be ok
02869   // to not call, so commented out
02870   // src_attached = (s_handle->mh && s_handle->field_ptr->is_live());
02871   dest_attached = (d_handle->mh && d_handle->field_ptr->is_live());
02872 
02873   if (dest_attached)
02874     mime_hdr_field_detach(d_handle->mh, d_handle->field_ptr, false);
02875 
02876   mime_field_name_value_set(d_heap, d_handle->mh, d_handle->field_ptr,
02877                             s_handle->field_ptr->m_wks_idx,
02878                             s_handle->field_ptr->m_ptr_name,
02879                             s_handle->field_ptr->m_len_name,
02880                             s_handle->field_ptr->m_ptr_value, s_handle->field_ptr->m_len_value, 0, 0, true);
02881 
02882   if (dest_attached)
02883     mime_hdr_field_attach(d_handle->mh, d_handle->field_ptr, 1, NULL);
02884   return TS_SUCCESS;
02885 }
02886 
02887 TSReturnCode
02888 TSMimeHdrFieldClone(TSMBuffer dest_bufp, TSMLoc dest_hdr, TSMBuffer src_bufp, TSMLoc src_hdr, TSMLoc src_field, TSMLoc *locp)
02889 {
02890   // Allow to modify the buffer only
02891   // if bufp is modifiable. If bufp is not modifiable return
02892   // TS_ERROR. If not allowed, return NULL.
02893   sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
02894   sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
02895   sdk_assert((sdk_sanity_check_mime_hdr_handle(dest_hdr) == TS_SUCCESS) ||
02896              (sdk_sanity_check_http_hdr_handle(dest_hdr) == TS_SUCCESS));
02897   sdk_assert((sdk_sanity_check_mime_hdr_handle(src_hdr) == TS_SUCCESS) ||
02898              (sdk_sanity_check_http_hdr_handle(src_hdr) == TS_SUCCESS));
02899   sdk_assert(sdk_sanity_check_field_handle(src_field, src_hdr) == TS_SUCCESS);
02900   sdk_assert(sdk_sanity_check_null_ptr((void*)locp) == TS_SUCCESS);
02901 
02902   if (!isWriteable(dest_bufp))
02903     return TS_ERROR;
02904 
02905   // This is sort of sub-optimal, since we'll check the args again. TODO.
02906   if (TSMimeHdrFieldCreate(dest_bufp, dest_hdr, locp) == TS_SUCCESS) {
02907     TSMimeHdrFieldCopy(dest_bufp, dest_hdr, *locp, src_bufp, src_hdr, src_field);
02908     return TS_SUCCESS;
02909   }
02910   // TSMimeHdrFieldCreate() failed for some reason.
02911   return TS_ERROR;
02912 }
02913 
02914 TSReturnCode
02915 TSMimeHdrFieldCopyValues(TSMBuffer dest_bufp, TSMLoc dest_hdr, TSMLoc dest_field, TSMBuffer src_bufp, TSMLoc src_hdr,
02916                          TSMLoc src_field)
02917 {
02918   // Allow to modify the buffer only
02919   // if bufp is modifiable. If bufp is not modifiable return
02920   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
02921   // return value of function from void to TSReturnCode.
02922   sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
02923   sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
02924   sdk_assert((sdk_sanity_check_mime_hdr_handle(src_hdr) == TS_SUCCESS) ||
02925              (sdk_sanity_check_http_hdr_handle(src_hdr) == TS_SUCCESS));
02926   sdk_assert((sdk_sanity_check_mime_hdr_handle(dest_hdr) == TS_SUCCESS) ||
02927              (sdk_sanity_check_http_hdr_handle(dest_hdr) == TS_SUCCESS));
02928   sdk_assert(sdk_sanity_check_field_handle(src_field, src_hdr) == TS_SUCCESS);
02929   sdk_assert(sdk_sanity_check_field_handle(dest_field, dest_hdr) == TS_SUCCESS);
02930 
02931   if (!isWriteable(dest_bufp))
02932     return TS_ERROR;
02933 
02934   MIMEFieldSDKHandle *s_handle = (MIMEFieldSDKHandle *) src_field;
02935   MIMEFieldSDKHandle *d_handle = (MIMEFieldSDKHandle *) dest_field;
02936   HdrHeap *d_heap = ((HdrHeapSDKHandle *) dest_bufp)->m_heap;
02937   MIMEField *s_field, *d_field;
02938 
02939   s_field = s_handle->field_ptr;
02940   d_field = d_handle->field_ptr;
02941   mime_field_value_set(d_heap, d_handle->mh, d_field, s_field->m_ptr_value, s_field->m_len_value, true);
02942   return TS_SUCCESS;
02943 }
02944 
02945 // TODO: This is implemented horribly slowly, but who's using it anyway?
02946 //       If we threaded all the MIMEFields, this function could be easier,
02947 //       but we'd have to print dups in order and we'd need a flag saying
02948 //       end of dup list or dup follows.
02949 TSMLoc
02950 TSMimeHdrFieldNext(TSMBuffer bufp, TSMLoc hdr, TSMLoc field)
02951 {
02952   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
02953   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) ||
02954              (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
02955   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
02956 
02957   MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *) field;
02958 
02959   if (handle->mh == NULL)
02960     return TS_NULL_MLOC;
02961 
02962   int slotnum = mime_hdr_field_slotnum(handle->mh, handle->field_ptr);
02963   if (slotnum == -1)
02964     return TS_NULL_MLOC;
02965 
02966   while (1) {
02967     ++slotnum;
02968     MIMEField *f = mime_hdr_field_get_slotnum(handle->mh, slotnum);
02969 
02970     if (f == NULL)
02971       return TS_NULL_MLOC;
02972     if (f->is_live()) {
02973       MIMEFieldSDKHandle *h = sdk_alloc_field_handle(bufp, handle->mh);
02974 
02975       h->field_ptr = f;
02976       return reinterpret_cast<TSMLoc>(h);
02977     }
02978   }
02979   return TS_NULL_MLOC; // Shouldn't happen.
02980 }
02981 
02982 TSMLoc
02983 TSMimeHdrFieldNextDup(TSMBuffer bufp, TSMLoc hdr, TSMLoc field)
02984 {
02985   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
02986   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) ||
02987              (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
02988   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
02989 
02990   MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(hdr);
02991   MIMEFieldSDKHandle *field_handle = (MIMEFieldSDKHandle *) field;
02992   MIMEField *next = field_handle->field_ptr->m_next_dup;
02993   if (next == NULL)
02994     return TS_NULL_MLOC;
02995 
02996   MIMEFieldSDKHandle *next_handle = sdk_alloc_field_handle(bufp, mh);
02997   next_handle->field_ptr = next;
02998   return (TSMLoc)next_handle;
02999 }
03000 
03001 int
03002 TSMimeHdrFieldLengthGet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field)
03003 {
03004   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03005   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) ||
03006              (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
03007   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
03008 
03009   MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *) field;
03010   return mime_field_length_get(handle->field_ptr);
03011 }
03012 
03013 const char *
03014 TSMimeHdrFieldNameGet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int *length)
03015 {
03016   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03017   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) ||
03018              (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
03019   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
03020   sdk_assert(sdk_sanity_check_null_ptr((void*)length) == TS_SUCCESS);
03021 
03022   MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *) field;
03023   return mime_field_name_get(handle->field_ptr, length);
03024 }
03025 
03026 TSReturnCode
03027 TSMimeHdrFieldNameSet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, const char *name, int length)
03028 {
03029   // Allow to modify the buffer only
03030   // if bufp is modifiable. If bufp is not modifiable return
03031   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
03032   // return value of function from void to TSReturnCode.
03033   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03034   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) ||
03035              (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
03036   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
03037   sdk_assert(sdk_sanity_check_null_ptr((void*) name) == TS_SUCCESS);
03038 
03039   if (!isWriteable(bufp))
03040     return TS_ERROR;
03041 
03042   if (length == -1)
03043     length = strlen(name);
03044 
03045   MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *) field;
03046   HdrHeap *heap = ((HdrHeapSDKHandle *) bufp)->m_heap;
03047 
03048   int attached = (handle->mh && handle->field_ptr->is_live());
03049 
03050   if (attached)
03051     mime_hdr_field_detach(handle->mh, handle->field_ptr, false);
03052 
03053   handle->field_ptr->name_set(heap, handle->mh, name, length);
03054 
03055   if (attached)
03056     mime_hdr_field_attach(handle->mh, handle->field_ptr, 1, NULL);
03057   return TS_SUCCESS;
03058 }
03059 
03060 TSReturnCode
03061 TSMimeHdrFieldValuesClear(TSMBuffer bufp, TSMLoc hdr, TSMLoc field)
03062 {
03063   // Allow to modify the buffer only
03064   // if bufp is modifiable. If bufp is not modifiable return
03065   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
03066   // return value of function from void to TSReturnCode.
03067   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03068   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) ||
03069              (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
03070   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
03071 
03072   if (!isWriteable(bufp))
03073     return TS_ERROR;
03074 
03075   MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *) field;
03076   HdrHeap *heap = ((HdrHeapSDKHandle *) bufp)->m_heap;
03077 
03078   /**
03079    * Modified the string value passed from an empty string ("") to NULL.
03080    * An empty string is also considered to be a token. The correct value of
03081    * the field after this function should be NULL.
03082    */
03083   mime_field_value_set(heap, handle->mh, handle->field_ptr, NULL, 0, 1);
03084   return TS_SUCCESS;
03085 }
03086 
03087 int
03088 TSMimeHdrFieldValuesCount(TSMBuffer bufp, TSMLoc hdr, TSMLoc field)
03089 {
03090   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03091   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) ||
03092              (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
03093   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
03094 
03095   MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *) field;
03096   return mime_field_value_get_comma_val_count(handle->field_ptr);
03097 }
03098 
03099 const char*
03100 TSMimeHdrFieldValueStringGet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, int *value_len_ptr) {
03101   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03102   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) ||
03103              (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
03104   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
03105   sdk_assert(sdk_sanity_check_null_ptr((void*) value_len_ptr) == TS_SUCCESS);
03106 
03107   return TSMimeFieldValueGet(bufp, field, idx, value_len_ptr);
03108 }
03109 
03110 time_t
03111 TSMimeHdrFieldValueDateGet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field)
03112 {
03113   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03114   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) ||
03115              (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
03116   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
03117 
03118   int value_len;
03119   const char *value_str = TSMimeFieldValueGet(bufp, field, -1, &value_len);
03120 
03121   if (value_str == NULL)
03122     return (time_t) 0;
03123 
03124   return mime_parse_date(value_str, value_str + value_len);
03125 }
03126 
03127 int
03128 TSMimeHdrFieldValueIntGet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx)
03129 {
03130   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03131   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) ||
03132              (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
03133   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
03134 
03135   int value_len;
03136   const char *value_str = TSMimeFieldValueGet(bufp, field, idx, &value_len);
03137 
03138   if (value_str == NULL)
03139     return 0;
03140 
03141   return mime_parse_int(value_str, value_str + value_len);
03142 }
03143 
03144 int64_t
03145 TSMimeHdrFieldValueInt64Get(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx)
03146 {
03147   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03148   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) ||
03149              (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
03150   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
03151 
03152   int value_len;
03153   const char *value_str = TSMimeFieldValueGet(bufp, field, idx, &value_len);
03154 
03155   if (value_str == NULL)
03156     return 0;
03157 
03158   return mime_parse_int64(value_str, value_str + value_len);
03159 }
03160 
03161 unsigned int
03162 TSMimeHdrFieldValueUintGet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx)
03163 {
03164   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03165   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) ||
03166              (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
03167   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
03168 
03169   int value_len;
03170   const char *value_str = TSMimeFieldValueGet(bufp, field, idx, &value_len);
03171 
03172   if (value_str == NULL)
03173     return 0;
03174 
03175   return mime_parse_uint(value_str, value_str + value_len);
03176 }
03177 
03178 TSReturnCode
03179 TSMimeHdrFieldValueStringSet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, const char *value, int length)
03180 {
03181   // Allow to modify the buffer only
03182   // if bufp is modifiable. If bufp is not modifiable return
03183   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
03184   // return value of function from void to TSReturnCode.
03185   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03186   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) ||
03187              (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
03188   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
03189   sdk_assert(sdk_sanity_check_null_ptr((void*) value) == TS_SUCCESS);
03190 
03191   if (!isWriteable(bufp))
03192     return TS_ERROR;
03193 
03194   if (length == -1)
03195     length = strlen(value);
03196 
03197   TSMimeFieldValueSet(bufp, field, idx, value, length);
03198   return TS_SUCCESS;
03199 }
03200 
03201 TSReturnCode
03202 TSMimeHdrFieldValueDateSet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, time_t value)
03203 {
03204   // Allow to modify the buffer only
03205   // if bufp is modifiable. If bufp is not modifiable return
03206   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
03207   // return value of function from void to TSReturnCode.
03208   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03209   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) ||
03210              (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
03211   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
03212 
03213   if (!isWriteable(bufp))
03214     return TS_ERROR;
03215 
03216   char tmp[33];
03217   int len = mime_format_date(tmp, value);
03218 
03219     // idx is ignored and we overwrite all existing values
03220     // TSMimeFieldValueSet(bufp, field_obj, idx, tmp, len);
03221   TSMimeFieldValueSet(bufp, field, -1, tmp, len);
03222   return TS_SUCCESS;
03223 }
03224 
03225 TSReturnCode
03226 TSMimeHdrFieldValueIntSet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, int value)
03227 {
03228   // Allow to modify the buffer only
03229   // if bufp is modifiable. If bufp is not modifiable return
03230   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
03231   // return value of function from void to TSReturnCode.
03232   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03233   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) ||
03234              (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
03235   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
03236 
03237   if (!isWriteable(bufp))
03238     return TS_ERROR;
03239 
03240   char tmp[16];
03241   int len = mime_format_int(tmp, value, sizeof(tmp));
03242 
03243   TSMimeFieldValueSet(bufp, field, idx, tmp, len);
03244   return TS_SUCCESS;
03245 }
03246 
03247 TSReturnCode
03248 TSMimeHdrFieldValueInt64Set(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, int64_t value)
03249 {
03250   // Allow to modify the buffer only
03251   // if bufp is modifiable. If bufp is not modifiable return
03252   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
03253   // return value of function from void to TSReturnCode.
03254   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03255   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) ||
03256              (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
03257   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
03258 
03259   if (!isWriteable(bufp))
03260     return TS_ERROR;
03261 
03262   char tmp[20];
03263   int len = mime_format_int64(tmp, value, sizeof(tmp));
03264 
03265   TSMimeFieldValueSet(bufp, field, idx, tmp, len);
03266   return TS_SUCCESS;
03267 }
03268 
03269 TSReturnCode
03270 TSMimeHdrFieldValueUintSet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, unsigned int value)
03271 {
03272   // Allow to modify the buffer only
03273   // if bufp is modifiable. If bufp is not modifiable return
03274   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
03275   // return value of function from void to TSReturnCode.
03276   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03277   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) ||
03278              (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
03279   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
03280 
03281   if (!isWriteable(bufp))
03282     return TS_ERROR;
03283 
03284   char tmp[16];
03285   int len = mime_format_uint(tmp, value, sizeof(tmp));
03286 
03287   TSMimeFieldValueSet(bufp, field, idx, tmp, len);
03288   return TS_SUCCESS;
03289 }
03290 
03291 TSReturnCode
03292 TSMimeHdrFieldValueAppend(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, const char *value, int length)
03293 {
03294   // Allow to modify the buffer only
03295   // if bufp is modifiable. If bufp is not modifiable return
03296   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
03297   // return value of function from void to TSReturnCode.
03298   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03299   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) ||
03300              (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
03301   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
03302   sdk_assert(sdk_sanity_check_null_ptr((void*)value) == TS_SUCCESS);
03303   sdk_assert(idx >= 0);
03304 
03305   if (!isWriteable(bufp))
03306     return TS_ERROR;
03307 
03308   MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *) field;
03309   HdrHeap *heap = ((HdrHeapSDKHandle *) bufp)->m_heap;
03310 
03311   if (length == -1)
03312     length = strlen(value);
03313   mime_field_value_extend_comma_val(heap, handle->mh, handle->field_ptr, idx, value, length);
03314   return TS_SUCCESS;
03315 }
03316 
03317 TSReturnCode
03318 TSMimeHdrFieldValueStringInsert(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, const char *value, int length)
03319 {
03320   // Allow to modify the buffer only
03321   // if bufp is modifiable. If bufp is not modifiable return
03322   // TS_ERROR, else return TS_SUCCESS.
03323   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03324   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) ||
03325              (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
03326   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
03327   sdk_assert(sdk_sanity_check_null_ptr((void*) value) == TS_SUCCESS);
03328 
03329   if (!isWriteable(bufp))
03330     return TS_ERROR;
03331 
03332   if (length == -1)
03333     length = strlen(value);
03334   TSMimeFieldValueInsert(bufp, field, value, length, idx);
03335   return TS_SUCCESS;
03336 }
03337 
03338 TSReturnCode
03339 TSMimeHdrFieldValueIntInsert(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, int value)
03340 {
03341   // Allow to modify the buffer only
03342   // if bufp is modifiable. If bufp is not modifiable return
03343   // TS_ERROR, else return TS_SUCCESS.
03344   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03345   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) ||
03346              (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
03347   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
03348 
03349   if (!isWriteable(bufp))
03350     return TS_ERROR;
03351 
03352   char tmp[16];
03353   int len = mime_format_int(tmp, value, sizeof(tmp));
03354 
03355   TSMimeFieldValueInsert(bufp, field, tmp, len, idx);
03356   return TS_SUCCESS;
03357 }
03358 
03359 TSReturnCode
03360 TSMimeHdrFieldValueUintInsert(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, unsigned int value)
03361 {
03362   // Allow to modify the buffer only
03363   // if bufp is modifiable. If bufp is not modifiable return
03364   // TS_ERROR, else return TS_SUCCESS.
03365   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03366   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) ||
03367              (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
03368   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
03369 
03370   if (!isWriteable(bufp))
03371     return TS_ERROR;
03372 
03373   char tmp[16];
03374   int len = mime_format_uint(tmp, value, sizeof(tmp));
03375 
03376   TSMimeFieldValueInsert(bufp, field, tmp, len, idx);
03377   return TS_SUCCESS;
03378 }
03379 
03380 TSReturnCode
03381 TSMimeHdrFieldValueDateInsert(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, time_t value)
03382 {
03383   // Allow to modify the buffer only
03384   // if bufp is modifiable. If bufp is not modifiable return
03385   // TS_ERROR, else return TS_SUCCESS
03386   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03387   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) ||
03388              (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
03389   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
03390 
03391   if (!isWriteable(bufp))
03392     return TS_ERROR;
03393 
03394   if (TSMimeHdrFieldValuesClear(bufp, hdr, field) == TS_ERROR)
03395     return TS_ERROR;
03396 
03397   char tmp[33];
03398   int len = mime_format_date(tmp, value);
03399     // idx ignored, overwrite all exisiting values
03400     // (void)TSMimeFieldValueInsert(bufp, field_obj, tmp, len, idx);
03401   (void) TSMimeFieldValueSet(bufp, field, -1, tmp, len);
03402   return TS_SUCCESS;
03403 }
03404 
03405 TSReturnCode
03406 TSMimeHdrFieldValueDelete(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx)
03407 {
03408   // Allow to modify the buffer only
03409   // if bufp is modifiable. If bufp is not modifiable return
03410   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
03411   // return value of function from void to TSReturnCode.
03412   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03413   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) ||
03414              (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
03415   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
03416   sdk_assert(idx >= 0);
03417 
03418   if (!isWriteable(bufp))
03419     return TS_ERROR;
03420 
03421   MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *) field;
03422   HdrHeap *heap = ((HdrHeapSDKHandle *) bufp)->m_heap;
03423 
03424   mime_field_value_delete_comma_val(heap, handle->mh, handle->field_ptr, idx);
03425   return TS_SUCCESS;
03426 }
03427 
03428 /**************/
03429 /* HttpParser */
03430 /**************/
03431 TSHttpParser
03432 TSHttpParserCreate(void)
03433 {
03434   TSHttpParser parser = reinterpret_cast<TSHttpParser>(ats_malloc(sizeof(HTTPParser)));
03435   http_parser_init((HTTPParser *) parser);
03436 
03437   return parser;
03438 }
03439 
03440 void
03441 TSHttpParserClear(TSHttpParser parser)
03442 {
03443   sdk_assert(sdk_sanity_check_http_parser(parser) == TS_SUCCESS);
03444   http_parser_clear((HTTPParser *) parser);
03445 }
03446 
03447 void
03448 TSHttpParserDestroy(TSHttpParser parser)
03449 {
03450   sdk_assert(sdk_sanity_check_http_parser(parser) == TS_SUCCESS);
03451   http_parser_clear((HTTPParser *) parser);
03452   ats_free(parser);
03453 }
03454 
03455 /***********/
03456 /* HttpHdr */
03457 /***********/
03458 
03459 
03460 TSMLoc
03461 TSHttpHdrCreate(TSMBuffer bufp)
03462 {
03463   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03464 
03465   HTTPHdr h;
03466   h.m_heap = ((HdrHeapSDKHandle *) bufp)->m_heap;
03467   h.create(HTTP_TYPE_UNKNOWN);
03468   return (TSMLoc)(h.m_http);
03469 }
03470 
03471 void
03472 TSHttpHdrDestroy(TSMBuffer bufp, TSMLoc obj)
03473 {
03474   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03475   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
03476 
03477   // No more objects counts in heap or deallocation
03478   //   so do nothing!
03479 
03480   // HDR FIX ME - Did this free the MBuffer in Pete's old system
03481 }
03482 
03483 TSReturnCode
03484 TSHttpHdrClone(TSMBuffer dest_bufp, TSMBuffer src_bufp, TSMLoc src_hdr, TSMLoc *locp)
03485 {
03486   // Allow to modify the buffer only
03487   // if bufp is modifiable. If bufp is not modifiable return
03488   // TS_ERROR. If not allowed, return NULL.
03489   sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
03490   sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
03491   sdk_assert(sdk_sanity_check_http_hdr_handle(src_hdr) == TS_SUCCESS);
03492 
03493   if (!isWriteable(dest_bufp))
03494     return TS_ERROR;
03495 
03496   HdrHeap *s_heap, *d_heap;
03497   HTTPHdrImpl *s_hh, *d_hh;
03498 
03499   s_heap = ((HdrHeapSDKHandle *) src_bufp)->m_heap;
03500   d_heap = ((HdrHeapSDKHandle *) dest_bufp)->m_heap;
03501   s_hh = (HTTPHdrImpl *) src_hdr;
03502 
03503   if (s_hh->m_type != HDR_HEAP_OBJ_HTTP_HEADER)
03504     return TS_ERROR;
03505 
03506   // TODO: This is never used
03507   // inherit_strs = (s_heap != d_heap ? true : false);
03508   d_hh = http_hdr_clone(s_hh, s_heap, d_heap);
03509   *locp = (TSMLoc)d_hh;
03510 
03511   return TS_SUCCESS;
03512 }
03513 
03514 TSReturnCode
03515 TSHttpHdrCopy(TSMBuffer dest_bufp, TSMLoc dest_obj, TSMBuffer src_bufp, TSMLoc src_obj)
03516 {
03517   // Allow to modify the buffer only
03518   // if bufp is modifiable. If bufp is not modifiable return
03519   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
03520   // return value of function from void to TSReturnCode.
03521   sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
03522   sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
03523   sdk_assert(sdk_sanity_check_http_hdr_handle(dest_obj) == TS_SUCCESS);
03524   sdk_assert(sdk_sanity_check_http_hdr_handle(src_obj) == TS_SUCCESS);
03525 
03526   if (! isWriteable(dest_bufp))
03527     return TS_ERROR;
03528 
03529   bool inherit_strs;
03530   HdrHeap *s_heap, *d_heap;
03531   HTTPHdrImpl *s_hh, *d_hh;
03532 
03533   s_heap = ((HdrHeapSDKHandle *) src_bufp)->m_heap;
03534   d_heap = ((HdrHeapSDKHandle *) dest_bufp)->m_heap;
03535   s_hh = (HTTPHdrImpl *) src_obj;
03536   d_hh = (HTTPHdrImpl *) dest_obj;
03537 
03538   if ((s_hh->m_type != HDR_HEAP_OBJ_HTTP_HEADER) || (d_hh->m_type != HDR_HEAP_OBJ_HTTP_HEADER))
03539     return TS_ERROR;
03540 
03541   inherit_strs = (s_heap != d_heap ? true : false);
03542   TSHttpHdrTypeSet(dest_bufp, dest_obj, (TSHttpType) (s_hh->m_polarity));
03543   http_hdr_copy_onto(s_hh, s_heap, d_hh, d_heap, inherit_strs);
03544   return TS_SUCCESS;
03545 }
03546 
03547 void
03548 TSHttpHdrPrint(TSMBuffer bufp, TSMLoc obj, TSIOBuffer iobufp)
03549 {
03550   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03551   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
03552   sdk_assert(sdk_sanity_check_iocore_structure(iobufp) == TS_SUCCESS);
03553 
03554   MIOBuffer *b = (MIOBuffer *) iobufp;
03555   IOBufferBlock *blk;
03556   HTTPHdr h;
03557   int bufindex;
03558   int tmp, dumpoffset;
03559   int done;
03560 
03561   SET_HTTP_HDR(h, bufp, obj);
03562   ink_assert(h.m_http->m_type == HDR_HEAP_OBJ_HTTP_HEADER);
03563 
03564   dumpoffset = 0;
03565   do {
03566     blk = b->get_current_block();
03567     if (!blk || blk->write_avail() == 0) {
03568       b->add_block();
03569       blk = b->get_current_block();
03570     }
03571 
03572     bufindex = 0;
03573     tmp = dumpoffset;
03574 
03575     done = h.print(blk->end(), blk->write_avail(), &bufindex, &tmp);
03576 
03577     dumpoffset += bufindex;
03578     b->fill(bufindex);
03579   } while (!done);
03580 }
03581 
03582 TSParseResult
03583 TSHttpHdrParseReq(TSHttpParser parser, TSMBuffer bufp, TSMLoc obj, const char **start, const char *end)
03584 {
03585   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03586   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
03587   sdk_assert(sdk_sanity_check_null_ptr((void*)start) == TS_SUCCESS);
03588   sdk_assert(sdk_sanity_check_null_ptr((void*)*start) == TS_SUCCESS);
03589   sdk_assert(sdk_sanity_check_null_ptr((void*)end) == TS_SUCCESS);
03590 
03591   if (!isWriteable(bufp))
03592     return TS_PARSE_ERROR;
03593 
03594   HTTPHdr h;
03595 
03596   SET_HTTP_HDR(h, bufp, obj);
03597   ink_assert(h.m_http->m_type == HDR_HEAP_OBJ_HTTP_HEADER);
03598   TSHttpHdrTypeSet(bufp, obj, TS_HTTP_TYPE_REQUEST);
03599   return (TSParseResult)h.parse_req((HTTPParser *) parser, start, end, false);
03600 }
03601 
03602 TSParseResult
03603 TSHttpHdrParseResp(TSHttpParser parser, TSMBuffer bufp, TSMLoc obj, const char **start, const char *end)
03604 {
03605   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03606   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
03607   sdk_assert(sdk_sanity_check_null_ptr((void*)start) == TS_SUCCESS);
03608   sdk_assert(sdk_sanity_check_null_ptr((void*)*start) == TS_SUCCESS);
03609   sdk_assert(sdk_sanity_check_null_ptr((void*)end) == TS_SUCCESS);
03610 
03611   if (!isWriteable(bufp))
03612     return TS_PARSE_ERROR;
03613 
03614   HTTPHdr h;
03615 
03616   SET_HTTP_HDR(h, bufp, obj);
03617   ink_assert(h.m_http->m_type == HDR_HEAP_OBJ_HTTP_HEADER);
03618   TSHttpHdrTypeSet(bufp, obj, TS_HTTP_TYPE_RESPONSE);
03619   return (TSParseResult)h.parse_resp((HTTPParser *) parser, start, end, false);
03620 }
03621 
03622 int
03623 TSHttpHdrLengthGet(TSMBuffer bufp, TSMLoc obj)
03624 {
03625   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03626   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
03627 
03628   HTTPHdr h;
03629 
03630   SET_HTTP_HDR(h, bufp, obj);
03631   ink_assert(h.m_http->m_type == HDR_HEAP_OBJ_HTTP_HEADER);
03632   return h.length_get();
03633 }
03634 
03635 TSHttpType
03636 TSHttpHdrTypeGet(TSMBuffer bufp, TSMLoc obj)
03637 {
03638   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03639   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
03640 
03641   HTTPHdr h;
03642   SET_HTTP_HDR(h, bufp, obj);
03643   /* Don't need the assert as the check is done in sdk_sanity_check_http_hdr_handle
03644      ink_assert(h.m_http->m_type == HDR_HEAP_OBJ_HTTP_HEADER);
03645    */
03646   return (TSHttpType)h.type_get();
03647 }
03648 
03649 TSReturnCode
03650 TSHttpHdrTypeSet(TSMBuffer bufp, TSMLoc obj, TSHttpType type)
03651 {
03652   // Allow to modify the buffer only
03653   // if bufp is modifiable. If bufp is not modifiable return
03654   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
03655   // return value of function from void to TSReturnCode.
03656   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03657   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
03658   sdk_assert((type >= TS_HTTP_TYPE_UNKNOWN) && (type <= TS_HTTP_TYPE_RESPONSE));
03659 
03660   if (!isWriteable(bufp))
03661     return TS_ERROR;
03662 
03663   HTTPHdr h;
03664 
03665   SET_HTTP_HDR(h, bufp, obj);
03666   ink_assert(h.m_http->m_type == HDR_HEAP_OBJ_HTTP_HEADER);
03667 
03668   // FIX: why are we using an HTTPHdr here?  why can't we
03669   //      just manipulate the impls directly?
03670 
03671   // In Pete's MBuffer system you can change the type
03672   //   at will.  Not so anymore.  We need to try to
03673   //   fake the difference.  We not going to let
03674   //   people change the types of a header.  If they
03675   //   try, too bad.
03676   if (h.m_http->m_polarity == HTTP_TYPE_UNKNOWN) {
03677     if (type == (TSHttpType) HTTP_TYPE_REQUEST) {
03678       h.m_http->u.req.m_url_impl = url_create(h.m_heap);
03679       h.m_http->m_polarity = (HTTPType) type;
03680     } else if (type == (TSHttpType) HTTP_TYPE_RESPONSE) {
03681       h.m_http->m_polarity = (HTTPType) type;
03682     }
03683   }
03684   return TS_SUCCESS;
03685 }
03686 
03687 int
03688 TSHttpHdrVersionGet(TSMBuffer bufp, TSMLoc obj)
03689 {
03690   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03691   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
03692 
03693   HTTPHdr h;
03694 
03695   SET_HTTP_HDR(h, bufp, obj);
03696   HTTPVersion ver = h.version_get();
03697   return ver.m_version;
03698 }
03699 
03700 TSReturnCode
03701 TSHttpHdrVersionSet(TSMBuffer bufp, TSMLoc obj, int ver)
03702 {
03703   // Allow to modify the buffer only
03704   // if bufp is modifiable. If bufp is not modifiable return
03705   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
03706   // return value of function from void to TSReturnCode.
03707   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03708   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
03709 
03710   if (!isWriteable(bufp))
03711     return TS_ERROR;
03712 
03713   HTTPHdr h;
03714   HTTPVersion version(ver);
03715 
03716   SET_HTTP_HDR(h, bufp, obj);
03717   ink_assert(h.m_http->m_type == HDR_HEAP_OBJ_HTTP_HEADER);
03718 
03719   h.version_set(version);
03720   return TS_SUCCESS;
03721 }
03722 
03723 const char *
03724 TSHttpHdrMethodGet(TSMBuffer bufp, TSMLoc obj, int *length)
03725 {
03726   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03727   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
03728   sdk_assert(sdk_sanity_check_null_ptr((void*)length) == TS_SUCCESS);
03729 
03730   HTTPHdr h;
03731 
03732   SET_HTTP_HDR(h, bufp, obj);
03733   return h.method_get(length);
03734 }
03735 
03736 TSReturnCode
03737 TSHttpHdrMethodSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
03738 {
03739   // Allow to modify the buffer only
03740   // if bufp is modifiable. If bufp is not modifiable return
03741   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
03742   // return value of function from void to TSReturnCode.
03743   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03744   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
03745   sdk_assert(sdk_sanity_check_null_ptr((void*)value) == TS_SUCCESS);
03746 
03747   if (!isWriteable(bufp))
03748     return TS_ERROR;
03749 
03750   HTTPHdr h;
03751 
03752   SET_HTTP_HDR(h, bufp, obj);
03753   if (length < 0)
03754     length = strlen(value);
03755 
03756   h.method_set(value, length);
03757   return TS_SUCCESS;
03758 }
03759 
03760 TSReturnCode
03761 TSHttpHdrUrlGet(TSMBuffer bufp, TSMLoc obj, TSMLoc *locp)
03762 {
03763   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03764   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
03765 
03766   HTTPHdrImpl *hh = (HTTPHdrImpl *) obj;
03767 
03768   if (hh->m_polarity != HTTP_TYPE_REQUEST)
03769     return TS_ERROR;
03770 
03771   *locp = ((TSMLoc)hh->u.req.m_url_impl);
03772   return TS_SUCCESS;
03773 }
03774 
03775 TSReturnCode
03776 TSHttpHdrUrlSet(TSMBuffer bufp, TSMLoc obj, TSMLoc url)
03777 {
03778   // Allow to modify the buffer only
03779   // if bufp is modifiable. If bufp is not modifiable return
03780   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
03781   // return value of function from void to TSReturnCode.
03782   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03783   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
03784   sdk_assert(sdk_sanity_check_url_handle(url) == TS_SUCCESS);
03785 
03786   if (!isWriteable(bufp))
03787     return TS_ERROR;
03788 
03789   HdrHeap *heap = ((HdrHeapSDKHandle *) bufp)->m_heap;
03790   HTTPHdrImpl *hh = (HTTPHdrImpl *) obj;
03791 
03792   if (hh->m_type != HDR_HEAP_OBJ_HTTP_HEADER)
03793     return TS_ERROR;
03794 
03795   URLImpl *url_impl = (URLImpl *) url;
03796   http_hdr_url_set(heap, hh, url_impl);
03797   return TS_SUCCESS;
03798 }
03799 
03800 TSHttpStatus
03801 TSHttpHdrStatusGet(TSMBuffer bufp, TSMLoc obj)
03802 {
03803   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03804   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
03805 
03806   HTTPHdr h;
03807 
03808   SET_HTTP_HDR(h, bufp, obj);
03809   return (TSHttpStatus)h.status_get();
03810 }
03811 
03812 TSReturnCode
03813 TSHttpHdrStatusSet(TSMBuffer bufp, TSMLoc obj, TSHttpStatus status)
03814 {
03815   // Allow to modify the buffer only
03816   // if bufp is modifiable. If bufp is not modifiable return
03817   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
03818   // return value of function from void to TSReturnCode.
03819   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03820   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
03821 
03822   if (!isWriteable(bufp))
03823     return TS_ERROR;
03824 
03825   HTTPHdr h;
03826 
03827   SET_HTTP_HDR(h, bufp, obj);
03828   ink_assert(h.m_http->m_type == HDR_HEAP_OBJ_HTTP_HEADER);
03829   h.status_set((HTTPStatus) status);
03830   return TS_SUCCESS;
03831 }
03832 
03833 const char *
03834 TSHttpHdrReasonGet(TSMBuffer bufp, TSMLoc obj, int *length)
03835 {
03836   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03837   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
03838   sdk_assert(sdk_sanity_check_null_ptr((void*)length) == TS_SUCCESS);
03839 
03840   HTTPHdr h;
03841 
03842   SET_HTTP_HDR(h, bufp, obj);
03843   return h.reason_get(length);
03844 }
03845 
03846 TSReturnCode
03847 TSHttpHdrReasonSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
03848 {
03849   // Allow to modify the buffer only
03850   // if bufp is modifiable. If bufp is not modifiable return
03851   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
03852   // return value of function from void to TSReturnCode.
03853   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
03854   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
03855   sdk_assert(sdk_sanity_check_null_ptr((void*) value) == TS_SUCCESS);
03856 
03857   if (!isWriteable(bufp))
03858     return TS_ERROR;
03859 
03860   HTTPHdr h;
03861 
03862   SET_HTTP_HDR(h, bufp, obj);
03863   /* Don't need the assert as the check is done in sdk_sanity_check_http_hdr_handle
03864      ink_assert(h.m_http->m_type == HDR_HEAP_OBJ_HTTP_HEADER);
03865   */
03866 
03867   if (length < 0)
03868     length = strlen(value);
03869   h.reason_set(value, length);
03870   return TS_SUCCESS;
03871 }
03872 
03873 const char *
03874 TSHttpHdrReasonLookup(TSHttpStatus status)
03875 {
03876   return http_hdr_reason_lookup((HTTPStatus) status);
03877 }
03878 
03879 
03880 ////////////////////////////////////////////////////////////////////
03881 //
03882 // Cache
03883 //
03884 ////////////////////////////////////////////////////////////////////
03885 
03886 inline TSReturnCode
03887 sdk_sanity_check_cachekey(TSCacheKey key)
03888 {
03889   if (NULL == key)
03890     return TS_ERROR;
03891 
03892   return TS_SUCCESS;
03893 }
03894 
03895 TSCacheKey
03896 TSCacheKeyCreate(void)
03897 {
03898   TSCacheKey key = (TSCacheKey)new CacheInfo();
03899 
03900   // TODO: Probably remove this when we can be use "NEW" can't fail.
03901   sdk_assert(sdk_sanity_check_cachekey(key) == TS_SUCCESS);
03902   return key;
03903 }
03904 
03905 TSReturnCode
03906 TSCacheKeyDigestSet(TSCacheKey key, const char *input, int length)
03907 {
03908   sdk_assert(sdk_sanity_check_cachekey(key) == TS_SUCCESS);
03909   sdk_assert(sdk_sanity_check_iocore_structure((void*) input) == TS_SUCCESS);
03910   sdk_assert(length > 0);
03911   CacheInfo* ci = reinterpret_cast<CacheInfo*>(key);
03912   
03913   if (ci->magic != CACHE_INFO_MAGIC_ALIVE)
03914     return TS_ERROR;
03915 
03916   MD5Context().hash_immediate(ci->cache_key, input, length);
03917   return TS_SUCCESS;
03918 }
03919 
03920 TSReturnCode
03921 TSCacheKeyDigestFromUrlSet(TSCacheKey key, TSMLoc url)
03922 {
03923   sdk_assert(sdk_sanity_check_cachekey(key) == TS_SUCCESS);
03924 
03925   if (((CacheInfo *) key)->magic != CACHE_INFO_MAGIC_ALIVE)
03926     return TS_ERROR;
03927 
03928   url_MD5_get((URLImpl *) url, &((CacheInfo *) key)->cache_key);
03929   return TS_SUCCESS;
03930 }
03931 
03932 TSReturnCode
03933 TSCacheKeyDataTypeSet(TSCacheKey key, TSCacheDataType type)
03934 {
03935   sdk_assert(sdk_sanity_check_cachekey(key) == TS_SUCCESS);
03936 
03937   if (((CacheInfo *) key)->magic != CACHE_INFO_MAGIC_ALIVE)
03938     return TS_ERROR;
03939 
03940   switch (type) {
03941   case TS_CACHE_DATA_TYPE_NONE:
03942     ((CacheInfo *) key)->frag_type = CACHE_FRAG_TYPE_NONE;
03943     break;
03944   case TS_CACHE_DATA_TYPE_OTHER:      /* other maps to http */
03945   case TS_CACHE_DATA_TYPE_HTTP:
03946     ((CacheInfo *) key)->frag_type = CACHE_FRAG_TYPE_HTTP;
03947     break;
03948   default:
03949     return TS_ERROR;
03950   }
03951 
03952   return TS_SUCCESS;
03953 }
03954 
03955 TSReturnCode
03956 TSCacheKeyHostNameSet(TSCacheKey key, const char *hostname, int host_len)
03957 {
03958   sdk_assert(sdk_sanity_check_cachekey(key) == TS_SUCCESS);
03959   sdk_assert(sdk_sanity_check_null_ptr((void*)hostname) == TS_SUCCESS);
03960   sdk_assert(host_len > 0);
03961 
03962   if (((CacheInfo *) key)->magic != CACHE_INFO_MAGIC_ALIVE)
03963     return TS_ERROR;
03964 
03965   CacheInfo *i = (CacheInfo *) key;
03966   /* need to make a copy of the hostname. The caller
03967      might deallocate it anytime in the future */
03968   i->hostname = (char *)ats_malloc(host_len);
03969   memcpy(i->hostname, hostname, host_len);
03970   i->len = host_len;
03971   return TS_SUCCESS;
03972 }
03973 
03974 TSReturnCode
03975 TSCacheKeyPinnedSet(TSCacheKey key, time_t pin_in_cache)
03976 {
03977   sdk_assert(sdk_sanity_check_cachekey(key) == TS_SUCCESS);
03978 
03979   if (((CacheInfo *) key)->magic != CACHE_INFO_MAGIC_ALIVE)
03980     return TS_ERROR;
03981 
03982   CacheInfo *i = (CacheInfo *) key;
03983   i->pin_in_cache = pin_in_cache;
03984   return TS_SUCCESS;
03985 }
03986 
03987 TSReturnCode
03988 TSCacheKeyDestroy(TSCacheKey key)
03989 {
03990   sdk_assert(sdk_sanity_check_cachekey(key) == TS_SUCCESS);
03991 
03992   if (((CacheInfo *) key)->magic != CACHE_INFO_MAGIC_ALIVE)
03993     return TS_ERROR;
03994 
03995   CacheInfo *i = (CacheInfo *) key;
03996 
03997   ats_free(i->hostname);
03998   i->magic = CACHE_INFO_MAGIC_DEAD;
03999   delete i;
04000   return TS_SUCCESS;
04001 }
04002 
04003 TSCacheHttpInfo
04004 TSCacheHttpInfoCopy(TSCacheHttpInfo infop)
04005 {
04006   CacheHTTPInfo *new_info = new CacheHTTPInfo;
04007 
04008   new_info->copy((CacheHTTPInfo *) infop);
04009   return reinterpret_cast<TSCacheHttpInfo>(new_info);
04010 }
04011 
04012 void
04013 TSCacheHttpInfoReqGet(TSCacheHttpInfo infop, TSMBuffer *bufp, TSMLoc *obj)
04014 {
04015   CacheHTTPInfo *info = (CacheHTTPInfo *)infop;
04016 
04017   *(reinterpret_cast<HTTPHdr**>(bufp)) = info->request_get();
04018   *obj = reinterpret_cast<TSMLoc>(info->request_get()->m_http);
04019   sdk_sanity_check_mbuffer(*bufp);
04020 }
04021 
04022 
04023 void
04024 TSCacheHttpInfoRespGet(TSCacheHttpInfo infop, TSMBuffer *bufp, TSMLoc *obj)
04025 {
04026   CacheHTTPInfo *info = (CacheHTTPInfo *) infop;
04027 
04028   *(reinterpret_cast<HTTPHdr**>(bufp)) = info->response_get();
04029   *obj = reinterpret_cast<TSMLoc>(info->response_get()->m_http);
04030   sdk_sanity_check_mbuffer(*bufp);
04031 }
04032 
04033 time_t
04034 TSCacheHttpInfoReqSentTimeGet(TSCacheHttpInfo infop)
04035 {
04036   CacheHTTPInfo *info = (CacheHTTPInfo *) infop;
04037   return info->request_sent_time_get();
04038 }
04039 
04040 time_t
04041 TSCacheHttpInfoRespReceivedTimeGet(TSCacheHttpInfo infop)
04042 {
04043   CacheHTTPInfo *info = (CacheHTTPInfo *) infop;
04044   return info->response_received_time_get();
04045 }
04046 
04047 int64_t
04048 TSCacheHttpInfoSizeGet(TSCacheHttpInfo infop)
04049 {
04050   CacheHTTPInfo *info = (CacheHTTPInfo *) infop;
04051   return info->object_size_get();
04052 }
04053 
04054 void
04055 TSCacheHttpInfoReqSet(TSCacheHttpInfo infop, TSMBuffer bufp, TSMLoc obj)
04056 {
04057   HTTPHdr h;
04058 
04059   SET_HTTP_HDR(h, bufp, obj);
04060 
04061   CacheHTTPInfo *info = (CacheHTTPInfo *) infop;
04062   info->request_set(&h);
04063 }
04064 
04065 
04066 void
04067 TSCacheHttpInfoRespSet(TSCacheHttpInfo infop, TSMBuffer bufp, TSMLoc obj)
04068 {
04069   HTTPHdr h;
04070 
04071   SET_HTTP_HDR(h, bufp, obj);
04072 
04073   CacheHTTPInfo *info = (CacheHTTPInfo *) infop;
04074   info->response_set(&h);
04075 }
04076 
04077 
04078 int
04079 TSCacheHttpInfoVector(TSCacheHttpInfo infop, void *data, int length)
04080 {
04081   CacheHTTPInfo *info = (CacheHTTPInfo *) infop;
04082   CacheHTTPInfoVector vector;
04083 
04084   vector.insert(info);
04085 
04086   int size = vector.marshal_length();
04087 
04088   if (size > length)
04089     // error
04090     return 0;
04091 
04092   return vector.marshal((char *) data, length);
04093 }
04094 
04095 
04096 void
04097 TSCacheHttpInfoDestroy(TSCacheHttpInfo infop)
04098 {
04099   ((CacheHTTPInfo *) infop)->destroy();
04100 }
04101 
04102 TSCacheHttpInfo
04103 TSCacheHttpInfoCreate(void)
04104 {
04105   CacheHTTPInfo *info = new CacheHTTPInfo;
04106   info->create();
04107 
04108   return reinterpret_cast<TSCacheHttpInfo>(info);
04109 }
04110 
04111 
04112 ////////////////////////////////////////////////////////////////////
04113 //
04114 // Configuration
04115 //
04116 ////////////////////////////////////////////////////////////////////
04117 
04118 unsigned int
04119 TSConfigSet(unsigned int id, void *data, TSConfigDestroyFunc funcp)
04120 {
04121   INKConfigImpl *config = new INKConfigImpl;
04122   config->mdata = data;
04123   config->m_destroy_func = funcp;
04124   return configProcessor.set(id, config);
04125 }
04126 
04127 TSConfig
04128 TSConfigGet(unsigned int id)
04129 {
04130   return reinterpret_cast<TSConfig>(configProcessor.get(id));
04131 }
04132 
04133 void
04134 TSConfigRelease(unsigned int id, TSConfig configp)
04135 {
04136   configProcessor.release(id, (ConfigInfo *) configp);
04137 }
04138 
04139 void *
04140 TSConfigDataGet(TSConfig configp)
04141 {
04142   INKConfigImpl *config = (INKConfigImpl *) configp;
04143   return config->mdata;
04144 }
04145 
04146 ////////////////////////////////////////////////////////////////////
04147 //
04148 // Management
04149 //
04150 ////////////////////////////////////////////////////////////////////
04151 
04152 void
04153 TSMgmtUpdateRegister(TSCont contp, const char *plugin_name)
04154 {
04155   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
04156   sdk_assert(sdk_sanity_check_null_ptr((void*)plugin_name) == TS_SUCCESS);
04157 
04158   global_config_cbs->insert((INKContInternal *)contp, plugin_name);
04159 }
04160 
04161 TSReturnCode
04162 TSMgmtIntGet(const char *var_name, TSMgmtInt *result)
04163 {
04164   return RecGetRecordInt((char *) var_name, (RecInt *) result) == REC_ERR_OKAY ? TS_SUCCESS : TS_ERROR;
04165 }
04166 
04167 TSReturnCode
04168 TSMgmtCounterGet(const char *var_name, TSMgmtCounter *result)
04169 {
04170   return RecGetRecordCounter((char *) var_name, (RecCounter *) result) == REC_ERR_OKAY ? TS_SUCCESS : TS_ERROR;
04171 }
04172 
04173 TSReturnCode
04174 TSMgmtFloatGet(const char *var_name, TSMgmtFloat *result)
04175 {
04176   return RecGetRecordFloat((char *) var_name, (RecFloat *) result) == REC_ERR_OKAY ? TS_SUCCESS : TS_ERROR;
04177 }
04178 
04179 TSReturnCode
04180 TSMgmtStringGet(const char *var_name, TSMgmtString *result)
04181 {
04182   RecString tmp = 0;
04183   (void) RecGetRecordString_Xmalloc((char *) var_name, &tmp);
04184 
04185   if (tmp) {
04186     *result = tmp;
04187     return TS_SUCCESS;
04188   }
04189 
04190   return TS_ERROR;
04191 }
04192 
04193 ////////////////////////////////////////////////////////////////////
04194 //
04195 // Continuations
04196 //
04197 ////////////////////////////////////////////////////////////////////
04198 
04199 TSCont
04200 TSContCreate(TSEventFunc funcp, TSMutex mutexp)
04201 {
04202   // mutexp can be NULL
04203   if (mutexp != NULL)
04204     sdk_assert(sdk_sanity_check_mutex(mutexp) == TS_SUCCESS);
04205 
04206   INKContInternal *i = INKContAllocator.alloc();
04207 
04208   i->init(funcp, mutexp);
04209   return (TSCont)i;
04210 }
04211 
04212 void
04213 TSContDestroy(TSCont contp)
04214 {
04215   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
04216 
04217   INKContInternal *i = (INKContInternal *) contp;
04218 
04219   i->destroy();
04220 }
04221 
04222 void
04223 TSContDataSet(TSCont contp, void *data)
04224 {
04225   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
04226 
04227   INKContInternal *i = (INKContInternal *) contp;
04228 
04229   i->mdata = data;
04230 }
04231 
04232 void *
04233 TSContDataGet(TSCont contp)
04234 {
04235   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
04236 
04237   INKContInternal *i = (INKContInternal *) contp;
04238 
04239   return i->mdata;
04240 }
04241 
04242 TSAction
04243 TSContSchedule(TSCont contp, ink_hrtime timeout, TSThreadPool tp)
04244 {
04245   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
04246 
04247   FORCE_PLUGIN_MUTEX(contp);
04248 
04249   INKContInternal *i = (INKContInternal *) contp;
04250   TSAction action;
04251 
04252   if (ink_atomic_increment((int *) &i->m_event_count, 1) < 0)
04253     ink_assert (!"not reached");
04254 
04255   EventType etype;
04256 
04257   switch (tp) {
04258   case TS_THREAD_POOL_NET:
04259   case TS_THREAD_POOL_DEFAULT:
04260     etype = ET_NET;
04261     break;
04262   case TS_THREAD_POOL_TASK:
04263       etype = ET_TASK;
04264       break;
04265   case TS_THREAD_POOL_SSL:
04266     etype = ET_TASK; // Should be ET_SSL
04267     break;
04268   case TS_THREAD_POOL_DNS:
04269     etype = ET_DNS;
04270     break;
04271   case TS_THREAD_POOL_REMAP:
04272     etype = ET_TASK; // Should be ET_REMAP
04273     break;
04274   case TS_THREAD_POOL_CLUSTER:
04275     etype = ET_CLUSTER;
04276     break;
04277   case TS_THREAD_POOL_UDP:
04278     etype = ET_UDP;
04279     break;
04280   default:
04281     etype = ET_TASK;
04282     break;
04283   }
04284 
04285   if (timeout == 0) {
04286     action = reinterpret_cast<TSAction>(eventProcessor.schedule_imm(i, etype));
04287   } else {
04288     action = reinterpret_cast<TSAction>(eventProcessor.schedule_in(i, HRTIME_MSECONDS(timeout), etype));
04289   }
04290 
04291 /* This is a hack. SHould be handled in ink_types */
04292   action = (TSAction) ((uintptr_t) action | 0x1);
04293   return action;
04294 }
04295 
04296 TSAction
04297 TSContScheduleEvery(TSCont contp, ink_hrtime every, TSThreadPool tp)
04298 {
04299   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
04300 
04301   FORCE_PLUGIN_MUTEX(contp);
04302 
04303   INKContInternal *i = (INKContInternal *) contp;
04304   TSAction action;
04305 
04306   if (ink_atomic_increment((int *) &i->m_event_count, 1) < 0)
04307     ink_assert (!"not reached");
04308 
04309   EventType etype;
04310 
04311   switch (tp) {
04312   case TS_THREAD_POOL_NET:
04313   case TS_THREAD_POOL_DEFAULT:
04314     etype = ET_NET;
04315     break;
04316   case TS_THREAD_POOL_TASK:
04317     etype = ET_TASK;
04318     break;
04319   default:
04320     etype = ET_TASK;
04321     break;
04322   }
04323 
04324   action = reinterpret_cast<TSAction>(eventProcessor.schedule_every(i, HRTIME_MSECONDS(every), etype));
04325 
04326   /* This is a hack. SHould be handled in ink_types */
04327   action = (TSAction) ((uintptr_t) action | 0x1);
04328   return action;
04329 }
04330 
04331 TSAction
04332 TSHttpSchedule(TSCont contp, TSHttpTxn txnp, ink_hrtime timeout)
04333 {
04334   sdk_assert(sdk_sanity_check_iocore_structure (contp) == TS_SUCCESS);
04335 
04336   FORCE_PLUGIN_MUTEX(contp);
04337 
04338   INKContInternal *i = (INKContInternal *) contp;
04339 
04340   if (ink_atomic_increment((int *) &i->m_event_count, 1) < 0)
04341     ink_assert (!"not reached");
04342 
04343   TSAction action;
04344   Continuation *cont  = (Continuation*)contp;
04345   HttpSM *sm = (HttpSM*)txnp;
04346 
04347   sm->set_http_schedule(cont);
04348 
04349   if (timeout == 0) {
04350     action = reinterpret_cast<TSAction>(eventProcessor.schedule_imm(sm, ET_NET));
04351   } else {
04352     action = reinterpret_cast<TSAction>(eventProcessor.schedule_in(sm, HRTIME_MSECONDS (timeout), ET_NET));
04353   }
04354 
04355   action = (TSAction) ((uintptr_t) action | 0x1);
04356   return action;
04357 }
04358 
04359 int
04360 TSContCall(TSCont contp, TSEvent event, void *edata)
04361 {
04362   Continuation *c = (Continuation *) contp;
04363   return c->handleEvent((int) event, edata);
04364 }
04365 
04366 TSMutex
04367 TSContMutexGet(TSCont contp)
04368 {
04369   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
04370 
04371   Continuation *c = (Continuation *)contp;
04372   return (TSMutex) ((ProxyMutex *)c->mutex);
04373 }
04374 
04375 
04376 /* HTTP hooks */
04377 
04378 void
04379 TSHttpHookAdd(TSHttpHookID id, TSCont contp)
04380 {
04381   sdk_assert(sdk_sanity_check_continuation(contp) == TS_SUCCESS);
04382   sdk_assert(sdk_sanity_check_hook_id(id) == TS_SUCCESS);
04383 
04384   http_global_hooks->append(id, (INKContInternal *)contp);
04385 }
04386 
04387 void
04388 TSLifecycleHookAdd(TSLifecycleHookID id, TSCont contp)
04389 {
04390   sdk_assert(sdk_sanity_check_continuation(contp) == TS_SUCCESS);
04391   sdk_assert(sdk_sanity_check_lifecycle_hook_id(id) == TS_SUCCESS);
04392 
04393   lifecycle_hooks->append(id, (INKContInternal *)contp);
04394 }
04395 
04396 void
04397 TSHttpIcpDynamicSet(int value)
04398 {
04399   int32_t old_value, new_value;
04400 
04401   new_value = (value == 0) ? 0 : 1;
04402   old_value = icp_dynamic_enabled;
04403   while (old_value != new_value) {
04404     if (ink_atomic_cas(&icp_dynamic_enabled, old_value, new_value))
04405       break;
04406     old_value = icp_dynamic_enabled;
04407   }
04408 }
04409 
04410 /* HTTP sessions */
04411 void
04412 TSHttpSsnHookAdd(TSHttpSsn ssnp, TSHttpHookID id, TSCont contp)
04413 {
04414   sdk_assert(sdk_sanity_check_http_ssn(ssnp) == TS_SUCCESS);
04415   sdk_assert(sdk_sanity_check_continuation(contp) == TS_SUCCESS);
04416   sdk_assert(sdk_sanity_check_hook_id(id) == TS_SUCCESS);
04417 
04418   HttpClientSession *cs = (HttpClientSession *) ssnp;
04419   cs->ssn_hook_append(id, (INKContInternal *) contp);
04420 }
04421 
04422 int
04423 TSHttpSsnTransactionCount(TSHttpSsn ssnp)
04424 {
04425   sdk_assert(sdk_sanity_check_http_ssn(ssnp) == TS_SUCCESS);
04426 
04427   HttpClientSession* cs = (HttpClientSession*)ssnp;
04428   return cs->get_transact_count();
04429 }
04430 
04431 class TSHttpSsnCallback : public Continuation
04432 {
04433 public:
04434   TSHttpSsnCallback(HttpClientSession *cs, TSEvent event)
04435     : Continuation(cs->mutex), m_cs(cs), m_event(event)
04436   {
04437     SET_HANDLER(&TSHttpSsnCallback::event_handler);
04438   }
04439 
04440   int event_handler(int, void*)
04441   {
04442     m_cs->handleEvent((int) m_event, 0);
04443     delete this;
04444     return 0;
04445   }
04446 
04447 private:
04448   HttpClientSession *m_cs;
04449   TSEvent m_event;
04450 };
04451 
04452 
04453 void
04454 TSHttpSsnReenable(TSHttpSsn ssnp, TSEvent event)
04455 {
04456   sdk_assert(sdk_sanity_check_http_ssn(ssnp) == TS_SUCCESS);
04457 
04458   HttpClientSession *cs = (HttpClientSession *) ssnp;
04459   EThread *eth = this_ethread();
04460 
04461   // If this function is being executed on a thread created by the API
04462   // which is DEDICATED, the continuation needs to be called back on a
04463   // REGULAR thread.
04464   if (eth->tt != REGULAR) {
04465     eventProcessor.schedule_imm(new TSHttpSsnCallback(cs, event), ET_NET);
04466   } else {
04467     MUTEX_TRY_LOCK(trylock, cs->mutex, eth);
04468     if (!trylock) {
04469       eventProcessor.schedule_imm(new TSHttpSsnCallback(cs, event), ET_NET);
04470     } else {
04471       cs->handleEvent((int) event, 0);
04472     }
04473   }
04474 }
04475 
04476 
04477 /* HTTP transactions */
04478 void
04479 TSHttpTxnHookAdd(TSHttpTxn txnp, TSHttpHookID id, TSCont contp)
04480 {
04481   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
04482   sdk_assert(sdk_sanity_check_continuation(contp) == TS_SUCCESS);
04483   sdk_assert(sdk_sanity_check_hook_id(id) == TS_SUCCESS);
04484 
04485   HttpSM *sm = (HttpSM *) txnp;
04486   sm->txn_hook_append(id, (INKContInternal *) contp);
04487 }
04488 
04489 
04490 // Private api function for gzip plugin.
04491 //  This function should only appear in TsapiPrivate.h
04492 TSReturnCode
04493 TSHttpTxnHookRegisteredFor(TSHttpTxn txnp, TSHttpHookID id, TSEventFunc funcp)
04494 {
04495   HttpSM *sm = (HttpSM *) txnp;
04496   APIHook *hook = sm->txn_hook_get(id);
04497 
04498   while (hook != NULL) {
04499     if (hook->m_cont && hook->m_cont->m_event_func == funcp) {
04500       return TS_SUCCESS;
04501     }
04502     hook = hook->m_link.next;
04503   }
04504 
04505   return TS_ERROR;
04506 }
04507 
04508 TSHttpSsn
04509 TSHttpTxnSsnGet(TSHttpTxn txnp)
04510 {
04511   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
04512 
04513   HttpSM *sm = (HttpSM *) txnp;
04514   return (TSHttpSsn)sm->ua_session;
04515 }
04516 
04517 // TODO: Is this still necessary ??
04518 void
04519 TSHttpTxnClientKeepaliveSet(TSHttpTxn txnp, int set)
04520 {
04521   HttpSM *sm = (HttpSM *) txnp;
04522   HttpTransact::State *s = &(sm->t_state);
04523 
04524   s->hdr_info.trust_response_cl = (set != 0) ? true : false;
04525 }
04526 
04527 TSReturnCode
04528 TSHttpTxnClientReqGet(TSHttpTxn txnp, TSMBuffer *bufp, TSMLoc *obj)
04529 {
04530   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
04531   sdk_assert(sdk_sanity_check_null_ptr((void*) bufp) == TS_SUCCESS);
04532   sdk_assert(sdk_sanity_check_null_ptr((void*) obj) == TS_SUCCESS);
04533 
04534   HttpSM *sm = (HttpSM *) txnp;
04535   HTTPHdr *hptr = &(sm->t_state.hdr_info.client_request);
04536 
04537   if (hptr->valid()) {
04538     *(reinterpret_cast<HTTPHdr**>(bufp)) = hptr;
04539     *obj = reinterpret_cast<TSMLoc>(hptr->m_http);
04540     if (sdk_sanity_check_mbuffer(*bufp) == TS_SUCCESS) {
04541       hptr->mark_target_dirty();
04542       return TS_SUCCESS;;
04543     }
04544   }
04545   return TS_ERROR;
04546 }
04547 
04548 // pristine url is the url before remap
04549 TSReturnCode
04550 TSHttpTxnPristineUrlGet(TSHttpTxn txnp, TSMBuffer *bufp, TSMLoc *url_loc)
04551 {
04552   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
04553   sdk_assert(sdk_sanity_check_null_ptr((void*)bufp) == TS_SUCCESS);
04554   sdk_assert(sdk_sanity_check_null_ptr((void*)url_loc) == TS_SUCCESS);
04555 
04556   HttpSM *sm = (HttpSM*) txnp;
04557   HTTPHdr *hptr = &(sm->t_state.hdr_info.client_request);
04558 
04559   if (hptr->valid()) {
04560     *(reinterpret_cast<HTTPHdr**>(bufp)) = hptr;
04561     *url_loc = (TSMLoc)sm->t_state.pristine_url.m_url_impl;
04562 
04563     if ((sdk_sanity_check_mbuffer(*bufp) == TS_SUCCESS) && (*url_loc))
04564       return TS_SUCCESS;
04565   }
04566   return TS_ERROR;
04567 }
04568 
04569 // Shortcut to just get the URL.
04570 char*
04571 TSHttpTxnEffectiveUrlStringGet(TSHttpTxn txnp, int *length)
04572 {
04573   sdk_assert(TS_SUCCESS == sdk_sanity_check_txn(txnp));
04574   sdk_assert(sdk_sanity_check_null_ptr((void*)length) == TS_SUCCESS);
04575 
04576   HttpSM *sm = reinterpret_cast<HttpSM*>(txnp);
04577   return sm->t_state.hdr_info.client_request.url_string_get(0, length);
04578 }
04579 
04580 TSReturnCode
04581 TSHttpTxnClientRespGet(TSHttpTxn txnp, TSMBuffer *bufp, TSMLoc *obj)
04582 {
04583   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
04584   sdk_assert(sdk_sanity_check_null_ptr((void*) bufp) == TS_SUCCESS);
04585   sdk_assert(sdk_sanity_check_null_ptr((void*) obj) == TS_SUCCESS);
04586 
04587   HttpSM *sm = (HttpSM *) txnp;
04588   HTTPHdr *hptr = &(sm->t_state.hdr_info.client_response);
04589 
04590   if (hptr->valid()) {
04591     *(reinterpret_cast<HTTPHdr**>(bufp)) = hptr;
04592     *obj = reinterpret_cast<TSMLoc>(hptr->m_http);
04593     sdk_sanity_check_mbuffer(*bufp);
04594     return TS_SUCCESS;
04595   }
04596 
04597   return TS_ERROR;
04598 }
04599 
04600 
04601 TSReturnCode
04602 TSHttpTxnServerReqGet(TSHttpTxn txnp, TSMBuffer *bufp, TSMLoc *obj)
04603 {
04604   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
04605   sdk_assert(sdk_sanity_check_null_ptr((void*) bufp) == TS_SUCCESS);
04606   sdk_assert(sdk_sanity_check_null_ptr((void*) obj) == TS_SUCCESS);
04607 
04608   HttpSM *sm = (HttpSM *) txnp;
04609   HTTPHdr *hptr = &(sm->t_state.hdr_info.server_request);
04610 
04611   if (hptr->valid()) {
04612     *(reinterpret_cast<HTTPHdr**>(bufp)) = hptr;
04613     *obj = reinterpret_cast<TSMLoc>(hptr->m_http);
04614     sdk_sanity_check_mbuffer(*bufp);
04615     return TS_SUCCESS;
04616   }
04617 
04618   return TS_ERROR;
04619 }
04620 
04621 TSReturnCode
04622 TSHttpTxnServerRespGet(TSHttpTxn txnp, TSMBuffer *bufp, TSMLoc *obj)
04623 {
04624   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
04625   sdk_assert(sdk_sanity_check_null_ptr((void*) bufp) == TS_SUCCESS);
04626   sdk_assert(sdk_sanity_check_null_ptr((void*) obj) == TS_SUCCESS);
04627 
04628   HttpSM *sm = (HttpSM *) txnp;
04629   HTTPHdr *hptr = &(sm->t_state.hdr_info.server_response);
04630 
04631   if (hptr->valid()) {
04632     *(reinterpret_cast<HTTPHdr**>(bufp)) = hptr;
04633     *obj = reinterpret_cast<TSMLoc>(hptr->m_http);
04634     sdk_sanity_check_mbuffer(*bufp);
04635     return TS_SUCCESS;
04636   }
04637 
04638   return TS_ERROR;
04639 }
04640 
04641 TSReturnCode
04642 TSHttpTxnCachedReqGet(TSHttpTxn txnp, TSMBuffer *bufp, TSMLoc *obj)
04643 {
04644   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
04645   sdk_assert(sdk_sanity_check_null_ptr((void*) bufp) == TS_SUCCESS);
04646   sdk_assert(sdk_sanity_check_null_ptr((void*) obj) == TS_SUCCESS);
04647 
04648   HttpSM *sm = (HttpSM *) txnp;
04649   HTTPInfo *cached_obj = sm->t_state.cache_info.object_read;
04650 
04651   // The following check is need to prevent the HttpSM handle copy from going bad
04652   // Since the cache manages the header buffer, sm->t_state.cache_info.object_read
04653   // is the only way to tell if handle has gone bad.
04654   if ((!cached_obj) || (!cached_obj->valid())) {
04655     return TS_ERROR;
04656   }
04657 
04658   HTTPHdr *cached_hdr = sm->t_state.cache_info.object_read->request_get();
04659 
04660   if (!cached_hdr->valid()) {
04661     return TS_ERROR;
04662   }
04663   // We can't use the HdrHeapSDKHandle structure in the RamCache since multiple
04664   // threads can access. We need to create our own for the transaction and return that.
04665   HdrHeapSDKHandle **handle = &(sm->t_state.cache_req_hdr_heap_handle);
04666 
04667   if (*handle == NULL) {
04668     *handle = (HdrHeapSDKHandle *) sm->t_state.arena.alloc(sizeof(HdrHeapSDKHandle));
04669     (*handle)->m_heap = cached_hdr->m_heap;
04670   }
04671 
04672   *(reinterpret_cast<HdrHeapSDKHandle**>(bufp)) = *handle;
04673   *obj = reinterpret_cast<TSMLoc>(cached_hdr->m_http);
04674   sdk_sanity_check_mbuffer(*bufp);
04675 
04676   return TS_SUCCESS;
04677 }
04678 
04679 TSReturnCode
04680 TSHttpTxnCachedRespGet(TSHttpTxn txnp, TSMBuffer *bufp, TSMLoc *obj)
04681 {
04682   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
04683   sdk_assert(sdk_sanity_check_null_ptr((void*) bufp) == TS_SUCCESS);
04684   sdk_assert(sdk_sanity_check_null_ptr((void*) obj) == TS_SUCCESS);
04685 
04686   HttpSM *sm = (HttpSM *) txnp;
04687   HTTPInfo *cached_obj = sm->t_state.cache_info.object_read;
04688 
04689   // The following check is need to prevent the HttpSM handle copy from going bad
04690   // Since the cache manages the header buffer, sm->t_state.cache_info.object_read
04691   // is the only way to tell if handle has gone bad.
04692   if ((!cached_obj) || (!cached_obj->valid())) {
04693     return TS_ERROR;
04694   }
04695 
04696   HTTPHdr *cached_hdr = sm->t_state.cache_info.object_read->response_get();
04697 
04698   if (!cached_hdr->valid()) {
04699     return TS_ERROR;
04700   }
04701   // We can't use the HdrHeapSDKHandle structure in the RamCache since multiple
04702   //  threads can access.  We need to create our own for the transaction and return that.
04703   HdrHeapSDKHandle **handle = &(sm->t_state.cache_resp_hdr_heap_handle);
04704 
04705   if (*handle == NULL) {
04706     *handle = (HdrHeapSDKHandle *) sm->t_state.arena.alloc(sizeof(HdrHeapSDKHandle));
04707     (*handle)->m_heap = cached_hdr->m_heap;
04708   }
04709 
04710   *(reinterpret_cast<HdrHeapSDKHandle**>(bufp)) = *handle;
04711   *obj = reinterpret_cast<TSMLoc>(cached_hdr->m_http);
04712   sdk_sanity_check_mbuffer(*bufp);
04713 
04714   return TS_SUCCESS;
04715 }
04716 
04717 
04718 TSReturnCode
04719 TSHttpTxnCachedRespModifiableGet(TSHttpTxn txnp, TSMBuffer *bufp, TSMLoc *obj)
04720 {
04721   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
04722   sdk_assert(sdk_sanity_check_null_ptr((void*) bufp) == TS_SUCCESS);
04723   sdk_assert(sdk_sanity_check_null_ptr((void*) obj) == TS_SUCCESS);
04724 
04725   HttpSM *sm = (HttpSM *) txnp;
04726   HttpTransact::State *s = &(sm->t_state);
04727   HTTPHdr *c_resp = NULL;
04728   HTTPInfo *cached_obj = sm->t_state.cache_info.object_read;
04729   HTTPInfo *cached_obj_store = &(sm->t_state.cache_info.object_store);
04730 
04731   if ((!cached_obj) || (!cached_obj->valid()))
04732     return TS_ERROR;
04733 
04734   if (!cached_obj_store->valid())
04735     cached_obj_store->create();
04736 
04737   c_resp = cached_obj_store->response_get();
04738   if (c_resp == NULL || !c_resp->valid())
04739     cached_obj_store->response_set(cached_obj->response_get());
04740   c_resp = cached_obj_store->response_get();
04741   s->api_modifiable_cached_resp = true;
04742 
04743   ink_assert(c_resp != NULL && c_resp->valid());
04744   *(reinterpret_cast<HTTPHdr**>(bufp)) = c_resp;
04745   *obj = reinterpret_cast<TSMLoc>(c_resp->m_http);
04746   sdk_sanity_check_mbuffer(*bufp);
04747 
04748   return TS_SUCCESS;
04749 }
04750 
04751 TSReturnCode
04752 TSHttpTxnCacheLookupStatusGet(TSHttpTxn txnp, int *lookup_status)
04753 {
04754   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
04755   sdk_assert(sdk_sanity_check_null_ptr((void*) lookup_status) == TS_SUCCESS);
04756 
04757   HttpSM *sm = (HttpSM *) txnp;
04758 
04759   switch (sm->t_state.cache_lookup_result) {
04760   case HttpTransact::CACHE_LOOKUP_MISS:
04761   case HttpTransact::CACHE_LOOKUP_DOC_BUSY:
04762     *lookup_status = TS_CACHE_LOOKUP_MISS;
04763     break;
04764   case HttpTransact::CACHE_LOOKUP_HIT_STALE:
04765     *lookup_status = TS_CACHE_LOOKUP_HIT_STALE;
04766     break;
04767   case HttpTransact::CACHE_LOOKUP_HIT_WARNING:
04768   case HttpTransact::CACHE_LOOKUP_HIT_FRESH:
04769     *lookup_status = TS_CACHE_LOOKUP_HIT_FRESH;
04770     break;
04771   case HttpTransact::CACHE_LOOKUP_SKIPPED:
04772     *lookup_status = TS_CACHE_LOOKUP_SKIPPED;
04773     break;
04774   case HttpTransact::CACHE_LOOKUP_NONE:
04775   default:
04776     return TS_ERROR;
04777   };
04778   return TS_SUCCESS;
04779 }
04780 
04781 TSReturnCode
04782 TSHttpTxnCacheLookupCountGet(TSHttpTxn txnp, int *lookup_count)
04783 {
04784   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
04785   sdk_assert(sdk_sanity_check_null_ptr((void*) lookup_count) == TS_SUCCESS);
04786 
04787   HttpSM *sm = (HttpSM *)txnp;
04788   *lookup_count = sm->t_state.cache_info.lookup_count;
04789   return TS_SUCCESS;
04790 }
04791 
04792 
04793 /* two hooks this function may gets called:
04794    TS_HTTP_READ_CACHE_HDR_HOOK   &
04795    TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK
04796  */
04797 TSReturnCode
04798 TSHttpTxnCacheLookupStatusSet(TSHttpTxn txnp, int cachelookup)
04799 {
04800   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
04801 
04802   HttpSM *sm = (HttpSM *) txnp;
04803   HttpTransact::CacheLookupResult_t *sm_status = &(sm->t_state.cache_lookup_result);
04804 
04805   // converting from a miss to a hit is not allowed
04806   if (*sm_status == HttpTransact::CACHE_LOOKUP_MISS && cachelookup != TS_CACHE_LOOKUP_MISS)
04807     return TS_ERROR;
04808 
04809   // here is to handle converting a hit to a miss
04810   if (cachelookup == TS_CACHE_LOOKUP_MISS && *sm_status != HttpTransact::CACHE_LOOKUP_MISS) {
04811     sm->t_state.api_cleanup_cache_read = true;
04812     ink_assert(sm->t_state.transact_return_point != NULL);
04813     sm->t_state.transact_return_point = HttpTransact::HandleCacheOpenRead;
04814   }
04815 
04816   switch (cachelookup) {
04817   case TS_CACHE_LOOKUP_MISS:
04818     *sm_status = HttpTransact::CACHE_LOOKUP_MISS;
04819     break;
04820   case TS_CACHE_LOOKUP_HIT_STALE:
04821     *sm_status = HttpTransact::CACHE_LOOKUP_HIT_STALE;
04822     break;
04823   case TS_CACHE_LOOKUP_HIT_FRESH:
04824     *sm_status = HttpTransact::CACHE_LOOKUP_HIT_FRESH;
04825     break;
04826   default:
04827     return TS_ERROR;
04828   }
04829 
04830   return TS_SUCCESS;
04831 }
04832 
04833 TSReturnCode
04834 TSHttpTxnCacheLookupUrlGet(TSHttpTxn txnp, TSMBuffer bufp, TSMLoc obj)
04835 {
04836   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
04837   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
04838   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
04839 
04840   HttpSM *sm = (HttpSM *) txnp;
04841   URL u, *l_url;
04842 
04843   u.m_heap = ((HdrHeapSDKHandle *) bufp)->m_heap;
04844   u.m_url_impl = (URLImpl *) obj;
04845   if (!u.valid())
04846     return TS_ERROR;
04847 
04848   l_url = sm->t_state.cache_info.lookup_url;
04849   if (l_url && l_url->valid()) {
04850     u.copy(l_url);
04851     return TS_SUCCESS;
04852   }
04853 
04854   return TS_ERROR;
04855 }
04856 
04857 // TS-1996: This API will be removed after v3.4.0 is cut. Do not use it!
04858 TSReturnCode
04859 TSHttpTxnNewCacheLookupDo(TSHttpTxn txnp, TSMBuffer bufp, TSMLoc url_loc)
04860 {
04861   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
04862   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
04863   sdk_assert(sdk_sanity_check_url_handle(url_loc) == TS_SUCCESS);
04864 
04865   URL new_url, *client_url, *l_url, *o_url;
04866   INK_MD5 md51, md52;
04867 
04868   new_url.m_heap = ((HdrHeapSDKHandle *) bufp)->m_heap;
04869   new_url.m_url_impl = (URLImpl *) url_loc;
04870   if (!new_url.valid())
04871     return TS_ERROR;
04872 
04873   HttpSM *sm = (HttpSM *) txnp;
04874   HttpTransact::State *s = &(sm->t_state);
04875 
04876   client_url = s->hdr_info.client_request.url_get();
04877   if (!(client_url->valid()))
04878     return TS_ERROR;
04879 
04880   // if l_url is not valid, then no cache lookup has been done yet
04881   // so we shouldn't be calling TSHttpTxnNewCacheLookupDo right now
04882   l_url = s->cache_info.lookup_url;
04883   if (!l_url || !l_url->valid()) {
04884     s->cache_info.lookup_url_storage.create(NULL);
04885     s->cache_info.lookup_url = &(s->cache_info.lookup_url_storage);
04886     l_url = s->cache_info.lookup_url;
04887   } else {
04888     l_url->hash_get(&md51);
04889     new_url.hash_get(&md52);
04890     if (md51 == md52)
04891       return TS_ERROR;
04892     o_url = &(s->cache_info.original_url);
04893     if (!o_url->valid()) {
04894       o_url->create(NULL);
04895       o_url->copy(l_url);
04896     }
04897   }
04898 
04899   // copy the new_url to lookup_url
04900   l_url->copy(&new_url);
04901 
04902   // bypass HttpTransact::HandleFiltering
04903   s->transact_return_point = HttpTransact::DecideCacheLookup;
04904   s->cache_info.action = HttpTransact::CACHE_DO_LOOKUP;
04905   sm->add_cache_sm();
04906   s->api_cleanup_cache_read = true;
04907 
04908   return TS_SUCCESS;
04909 }
04910 
04911 // TS-1996: This API will be removed after v3.4.0 is cut. Do not use it!
04912 TSReturnCode
04913 TSHttpTxnSecondUrlTryLock(TSHttpTxn txnp)
04914 {
04915   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
04916 
04917   HttpSM *sm = (HttpSM *) txnp;
04918   HttpTransact::State *s = &(sm->t_state);
04919   // TSHttpTxnNewCacheLookupDo didn't continue
04920   if (!s->cache_info.original_url.valid())
04921     return TS_ERROR;
04922   sm->add_cache_sm();
04923   s->api_lock_url = HttpTransact::LOCK_URL_SECOND;
04924 
04925   return TS_SUCCESS;
04926 }
04927 
04928 TSReturnCode
04929 TSHttpTxnRedirectRequest(TSHttpTxn txnp, TSMBuffer bufp, TSMLoc url_loc)
04930 {
04931   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
04932   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
04933   sdk_assert(sdk_sanity_check_url_handle(url_loc) == TS_SUCCESS);
04934 
04935   URL u, *o_url, *r_url, *client_url;
04936   HttpSM *sm = (HttpSM *) txnp;
04937   HttpTransact::State *s = &(sm->t_state);
04938 
04939   u.m_heap = ((HdrHeapSDKHandle *) bufp)->m_heap;
04940   u.m_url_impl = (URLImpl *) url_loc;
04941   if (!u.valid())
04942     return TS_ERROR;
04943 
04944   client_url = s->hdr_info.client_request.url_get();
04945   if (!(client_url->valid()))
04946     return TS_ERROR;
04947 
04948   s->redirect_info.redirect_in_process = true;
04949   o_url = &(s->redirect_info.original_url);
04950   if (!o_url->valid()) {
04951     o_url->create(NULL);
04952     o_url->copy(client_url);
04953   }
04954   client_url->copy(&u);
04955 
04956   r_url = &(s->redirect_info.redirect_url);
04957   if (!r_url->valid())
04958     r_url->create(NULL);
04959   r_url->copy(&u);
04960 
04961   s->hdr_info.server_request.destroy();
04962   // we want to close the server session
04963   s->api_release_server_session = true;
04964 
04965   s->request_sent_time = 0;
04966   s->response_received_time = 0;
04967   s->cache_info.write_lock_state = HttpTransact::CACHE_WL_INIT;
04968   s->next_action = HttpTransact::SM_ACTION_REDIRECT_READ;
04969 
04970   return TS_SUCCESS;
04971 }
04972 
04973 /**
04974  * timeout is in msec
04975  * overrides as proxy.config.http.transaction_active_timeout_out
04976 **/
04977 void
04978 TSHttpTxnActiveTimeoutSet(TSHttpTxn txnp, int timeout)
04979 {
04980   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
04981 
04982   HttpTransact::State *s = &(((HttpSM *) txnp)->t_state);
04983   s->api_txn_active_timeout_value = timeout;
04984 }
04985 
04986 /**
04987  * timeout is in msec
04988  * overrides as proxy.config.http.connect_attempts_timeout
04989 **/
04990 void
04991 TSHttpTxnConnectTimeoutSet(TSHttpTxn txnp, int timeout)
04992 {
04993   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
04994 
04995   HttpTransact::State *s = &(((HttpSM *) txnp)->t_state);
04996   s->api_txn_connect_timeout_value = timeout;
04997 }
04998 
04999 /**
05000  * timeout is in msec
05001  * overrides as proxy.config.dns.lookup_timeout
05002 **/
05003 void
05004 TSHttpTxnDNSTimeoutSet(TSHttpTxn txnp, int timeout)
05005 {
05006   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05007 
05008   HttpTransact::State *s = &(((HttpSM *) txnp)->t_state);
05009 
05010   s->api_txn_dns_timeout_value = timeout;
05011 }
05012 
05013 
05014 /**
05015  * timeout is in msec
05016  * overrides as proxy.config.http.transaction_no_activity_timeout_out
05017 **/
05018 void
05019 TSHttpTxnNoActivityTimeoutSet(TSHttpTxn txnp, int timeout)
05020 {
05021   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05022 
05023   HttpTransact::State *s = &(((HttpSM *) txnp)->t_state);
05024   s->api_txn_no_activity_timeout_value = timeout;
05025 }
05026 
05027 TSReturnCode
05028 TSHttpTxnServerRespNoStoreSet(TSHttpTxn txnp, int flag)
05029 {
05030   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05031 
05032   HttpTransact::State *s = &(((HttpSM *) txnp)->t_state);
05033   s->api_server_response_no_store = (flag != 0);
05034 
05035   return TS_SUCCESS;
05036 }
05037 
05038 TSReturnCode
05039 TSHttpTxnServerRespIgnore(TSHttpTxn txnp)
05040 {
05041   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05042 
05043   HttpTransact::State *s = &(((HttpSM *) txnp)->t_state);
05044   HTTPInfo *cached_obj = s->cache_info.object_read;
05045   HTTPHdr *cached_resp;
05046 
05047   if (cached_obj == NULL || !cached_obj->valid())
05048     return TS_ERROR;
05049 
05050   cached_resp = cached_obj->response_get();
05051   if (cached_resp == NULL || !cached_resp->valid())
05052     return TS_ERROR;
05053 
05054   s->api_server_response_ignore = true;
05055 
05056   return TS_SUCCESS;
05057 }
05058 
05059 TSReturnCode
05060 TSHttpTxnShutDown(TSHttpTxn txnp, TSEvent event)
05061 {
05062   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05063 
05064   if (event == TS_EVENT_HTTP_TXN_CLOSE)
05065     return TS_ERROR;
05066 
05067   HttpTransact::State *s = &(((HttpSM *) txnp)->t_state);
05068   s->api_http_sm_shutdown = true;
05069 
05070   return TS_SUCCESS;
05071 }
05072 
05073 TSReturnCode
05074 TSHttpTxnAborted(TSHttpTxn txnp)
05075 {
05076   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05077 
05078   HttpSM *sm = (HttpSM *) txnp;
05079   switch (sm->t_state.squid_codes.log_code) {
05080   case SQUID_LOG_ERR_CLIENT_ABORT:
05081   case SQUID_LOG_TCP_SWAPFAIL:
05082     // check for client abort and cache read error
05083     return TS_SUCCESS;
05084   default:
05085     break;
05086   }
05087 
05088   if (sm->t_state.current.server && sm->t_state.current.server->abort == HttpTransact::ABORTED) {
05089     // check for the server abort
05090     return TS_SUCCESS;
05091   }
05092   // there can be the case of transformation error.
05093   return TS_ERROR;
05094 }
05095 
05096 void
05097 TSHttpTxnReqCacheableSet(TSHttpTxn txnp, int flag)
05098 {
05099   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05100 
05101   HttpSM* sm = (HttpSM*)txnp;
05102   sm->t_state.api_req_cacheable = (flag != 0);
05103 }
05104 
05105 void
05106 TSHttpTxnRespCacheableSet(TSHttpTxn txnp, int flag)
05107 {
05108   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05109 
05110   HttpSM* sm = (HttpSM*)txnp;
05111   sm->t_state.api_resp_cacheable = (flag != 0);
05112 }
05113 
05114 int
05115 TSHttpTxnClientReqIsServerStyle(TSHttpTxn txnp)
05116 {
05117   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05118 
05119   HttpSM *sm = (HttpSM *) txnp;
05120   return (sm->t_state.hdr_info.client_req_is_server_style ? 1 : 0);
05121 }
05122 
05123 void
05124 TSHttpTxnOverwriteExpireTime(TSHttpTxn txnp, time_t expire_time)
05125 {
05126   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05127 
05128   HttpTransact::State *s = &(((HttpSM *) txnp)->t_state);
05129   s->plugin_set_expire_time = expire_time;
05130 }
05131 
05132 TSReturnCode
05133 TSHttpTxnUpdateCachedObject(TSHttpTxn txnp)
05134 {
05135   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05136 
05137   HttpSM *sm = (HttpSM *) txnp;
05138   HttpTransact::State *s = &(sm->t_state);
05139   HTTPInfo *cached_obj_store = &(sm->t_state.cache_info.object_store);
05140   HTTPHdr *client_request = &(sm->t_state.hdr_info.client_request);
05141 
05142   if (!cached_obj_store->valid() || !cached_obj_store->response_get())
05143     return TS_ERROR;
05144 
05145   if (!cached_obj_store->request_get() && !client_request->valid())
05146     return TS_ERROR;
05147 
05148   if (s->cache_info.write_lock_state == HttpTransact::CACHE_WL_READ_RETRY)
05149     return TS_ERROR;
05150 
05151   s->api_update_cached_object = HttpTransact::UPDATE_CACHED_OBJECT_PREPARE;
05152   return TS_SUCCESS;
05153 }
05154 
05155 TSReturnCode
05156 TSHttpTxnTransformRespGet(TSHttpTxn txnp, TSMBuffer *bufp, TSMLoc *obj)
05157 {
05158   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05159 
05160   HttpSM *sm = (HttpSM *) txnp;
05161   HTTPHdr *hptr = &(sm->t_state.hdr_info.transform_response);
05162 
05163   if (hptr->valid()) {
05164     *(reinterpret_cast<HTTPHdr**>(bufp)) = hptr;
05165     *obj = reinterpret_cast<TSMLoc>(hptr->m_http);
05166     return sdk_sanity_check_mbuffer(*bufp);
05167   }
05168 
05169   return TS_ERROR;
05170 }
05171 
05172 void *
05173 TSHttpSsnSSLConnectionGet(TSHttpSsn ssnp)
05174 {
05175   sdk_assert(sdk_sanity_check_null_ptr((void*)ssnp) == TS_SUCCESS);
05176 
05177   HttpClientSession *cs = reinterpret_cast<HttpClientSession *>(ssnp);
05178   if (cs == NULL) {
05179     return NULL;
05180   }
05181 
05182   SSLNetVConnection *ssl_vc = dynamic_cast<SSLNetVConnection *>(cs->get_netvc());
05183   if (ssl_vc == NULL) {
05184     return NULL;
05185   }
05186 
05187   return (void *)ssl_vc->ssl;
05188 }
05189 
05190 sockaddr const*
05191 TSHttpSsnClientAddrGet(TSHttpSsn ssnp)
05192 {
05193   HttpClientSession *cs = reinterpret_cast<HttpClientSession *>(ssnp);
05194 
05195   if (cs == NULL) return 0;
05196 
05197   NetVConnection *vc = cs->get_netvc();
05198   if (vc == NULL) return 0;
05199 
05200   return vc->get_remote_addr();
05201 }
05202 sockaddr const*
05203 TSHttpTxnClientAddrGet(TSHttpTxn txnp)
05204 {
05205   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05206 
05207   TSHttpSsn ssnp = TSHttpTxnSsnGet(txnp);
05208   return TSHttpSsnClientAddrGet(ssnp);
05209 }
05210 
05211 sockaddr const*
05212 TSHttpSsnIncomingAddrGet(TSHttpSsn ssnp)
05213 {
05214   HttpClientSession *cs = reinterpret_cast<HttpClientSession *>(ssnp);
05215 
05216   if (cs == NULL) return 0;
05217 
05218   NetVConnection *vc = cs->get_netvc();
05219   if (vc == NULL) return 0;
05220 
05221   return vc->get_local_addr();
05222 }
05223 sockaddr const*
05224 TSHttpTxnIncomingAddrGet(TSHttpTxn txnp)
05225 {
05226   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05227 
05228   TSHttpSsn ssnp = TSHttpTxnSsnGet(txnp);
05229   return TSHttpSsnIncomingAddrGet(ssnp);
05230 }
05231 
05232 sockaddr const*
05233 TSHttpTxnServerAddrGet(TSHttpTxn txnp)
05234 {
05235   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05236 
05237   HttpSM *sm = reinterpret_cast<HttpSM *>(txnp);
05238   return &sm->t_state.server_info.addr.sa;
05239 }
05240 
05241 TSReturnCode
05242 TSHttpTxnServerAddrSet(TSHttpTxn txnp, struct sockaddr const* addr)
05243 {
05244   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05245 
05246   HttpSM *sm = reinterpret_cast<HttpSM *>(txnp);
05247   if (ats_ip_copy(&sm->t_state.server_info.addr.sa, addr)) {
05248     ats_ip_port_cast(&sm->t_state.server_info.addr.sa) = ats_ip_port_cast(addr);
05249     sm->t_state.server_info.port = htons(ats_ip_port_cast(addr));
05250     sm->t_state.api_server_addr_set = true;
05251     return TS_SUCCESS;
05252   } else {
05253     return TS_ERROR;
05254   }
05255 }
05256 
05257 void
05258 TSHttpTxnClientIncomingPortSet(TSHttpTxn txnp, int port)
05259 {
05260   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05261 
05262   HttpSM *sm = (HttpSM *) txnp;
05263   sm->t_state.client_info.port = port;
05264 }
05265 
05266 // [amc] This might use the port. The code path should do that but it
05267 // hasn't been tested.
05268 TSReturnCode
05269 TSHttpTxnOutgoingAddrSet(TSHttpTxn txnp, const struct sockaddr *addr)
05270 {
05271   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05272   HttpSM *sm = (HttpSM *) txnp;
05273 
05274   sm->ua_session->outbound_port = ats_ip_port_host_order(addr);
05275 
05276   if (ats_is_ip4(addr)) {
05277     sm->ua_session->outbound_ip4.assign(addr);
05278   } else if (ats_is_ip6(addr)) {
05279     sm->ua_session->outbound_ip6.assign(addr);
05280   } else {
05281     sm->ua_session->outbound_ip4.invalidate();
05282     sm->ua_session->outbound_ip6.invalidate();
05283   }
05284   return TS_ERROR;
05285 }
05286 
05287 sockaddr const*
05288 TSHttpTxnNextHopAddrGet(TSHttpTxn txnp)
05289 {
05290   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05291 
05292   HttpSM *sm = reinterpret_cast<HttpSM *>(txnp);
05293 
05294     /**
05295      * Return zero if the server structure is not yet constructed.
05296      */
05297   if (sm->t_state.current.server == NULL)
05298     return NULL;
05299 
05300   return &sm->t_state.current.server->addr.sa;
05301 }
05302 
05303 TSReturnCode
05304 TSHttpTxnOutgoingTransparencySet(TSHttpTxn txnp, int flag)
05305 {
05306   if (TS_SUCCESS != sdk_sanity_check_txn(txnp)) return TS_ERROR;
05307 
05308 # if ! TS_USE_TPROXY
05309   if (flag) return TS_ERROR; // can't enable if it's not configured.
05310 # endif
05311 
05312   HttpSM *sm = reinterpret_cast<HttpSM*>(txnp);
05313   if (NULL == sm || NULL == sm->ua_session) {
05314     return TS_ERROR;
05315   }
05316 
05317   sm->ua_session->f_outbound_transparent = flag;
05318   return TS_SUCCESS;
05319 }
05320 
05321 TSReturnCode
05322 TSHttpTxnClientPacketMarkSet(TSHttpTxn txnp, int mark)
05323 {
05324   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05325   HttpSM *sm = (HttpSM *) txnp;
05326   if (NULL == sm->ua_session) {
05327     return TS_ERROR;
05328   }
05329 
05330   NetVConnection *vc = sm->ua_session->get_netvc();
05331   if (NULL == vc) {
05332     return TS_ERROR;
05333   }
05334 
05335   vc->options.packet_mark = (uint32_t)mark;
05336   vc->apply_options();
05337   return TS_SUCCESS;
05338 }
05339 
05340 TSReturnCode
05341 TSHttpTxnServerPacketMarkSet(TSHttpTxn txnp, int mark)
05342 {
05343   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05344   HttpSM *sm = (HttpSM *) txnp;
05345 
05346   // change the mark on an active server session
05347   if (NULL != sm->ua_session) {
05348     HttpServerSession *ssn = sm->ua_session->get_server_session();
05349     if (NULL != ssn) {
05350       NetVConnection *vc = ssn->get_netvc();
05351       if (vc != NULL) {
05352         vc->options.packet_mark = (uint32_t)mark;
05353         vc->apply_options();
05354       }
05355     }
05356   }
05357 
05358   // update the transactions mark config for future connections
05359   TSHttpTxnConfigIntSet(txnp, TS_CONFIG_NET_SOCK_PACKET_MARK_OUT, mark);
05360   return TS_SUCCESS;
05361 }
05362 
05363 TSReturnCode
05364 TSHttpTxnClientPacketTosSet(TSHttpTxn txnp, int tos)
05365 {
05366   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05367   HttpSM *sm = (HttpSM *) txnp;
05368   if (NULL == sm->ua_session) {
05369     return TS_ERROR;
05370   }
05371 
05372   NetVConnection *vc = sm->ua_session->get_netvc();
05373   if (NULL == vc) {
05374     return TS_ERROR;
05375   }
05376 
05377   vc->options.packet_tos = (uint32_t)tos;
05378   vc->apply_options();
05379   return TS_SUCCESS;
05380 }
05381 
05382 TSReturnCode
05383 TSHttpTxnServerPacketTosSet(TSHttpTxn txnp, int tos)
05384 {
05385   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05386   HttpSM *sm = (HttpSM *) txnp;
05387 
05388   // change the tos on an active server session
05389   if (NULL != sm->ua_session) {
05390     HttpServerSession *ssn = sm->ua_session->get_server_session();
05391     if (NULL != ssn) {
05392       NetVConnection *vc = ssn->get_netvc();
05393       if (vc != NULL) {
05394         vc->options.packet_tos = (uint32_t)tos;
05395         vc->apply_options();
05396       }
05397     }
05398   }
05399 
05400   // update the transactions mark config for future connections
05401   TSHttpTxnConfigIntSet(txnp, TS_CONFIG_NET_SOCK_PACKET_TOS_OUT, tos);
05402   return TS_SUCCESS;
05403 }
05404 
05405 // Set the body, or, if you provide a NULL buffer, clear the body message
05406 void
05407 TSHttpTxnErrorBodySet(TSHttpTxn txnp, char *buf, size_t buflength, char *mimetype)
05408 {
05409   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05410 
05411   HttpSM *sm = (HttpSM *) txnp;
05412   HttpTransact::State *s = &(sm->t_state);
05413 
05414   // Cleanup anything already set.
05415   s->free_internal_msg_buffer();
05416   ats_free(s->internal_msg_buffer_type);
05417 
05418   s->internal_msg_buffer = buf;
05419   s->internal_msg_buffer_size = buf ? buflength : 0;
05420   s->internal_msg_buffer_fast_allocator_size = -1;
05421 
05422   s->internal_msg_buffer_type = mimetype;
05423 }
05424 
05425 void
05426 TSHttpTxnServerRequestBodySet(TSHttpTxn txnp, char *buf, int64_t buflength)
05427 {
05428   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05429 
05430   HttpSM *sm = (HttpSM *) txnp;
05431   HttpTransact::State *s = &(sm->t_state);
05432 
05433   // Cleanup anything already set.
05434   s->free_internal_msg_buffer();
05435 
05436   if (buf) {
05437     s->api_server_request_body_set = true;
05438     s->internal_msg_buffer = buf;
05439     s->internal_msg_buffer_size = buflength;
05440   } else {
05441     s->api_server_request_body_set = false;
05442     s->internal_msg_buffer = NULL;
05443     s->internal_msg_buffer_size = 0;
05444   }
05445   s->internal_msg_buffer_fast_allocator_size = -1;
05446 }
05447 
05448 TSReturnCode
05449 TSHttpTxnParentProxyGet(TSHttpTxn txnp, char **hostname, int *port)
05450 {
05451   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05452 
05453   HttpSM *sm = (HttpSM *) txnp;
05454 
05455   *hostname = sm->t_state.api_info.parent_proxy_name;
05456   *port = sm->t_state.api_info.parent_proxy_port;
05457 
05458   return TS_SUCCESS;
05459 }
05460 
05461 void
05462 TSHttpTxnParentProxySet(TSHttpTxn txnp, char *hostname, int port)
05463 {
05464   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05465   sdk_assert(sdk_sanity_check_null_ptr((void*)hostname) == TS_SUCCESS);
05466   sdk_assert(port > 0);
05467 
05468   HttpSM *sm = (HttpSM *) txnp;
05469 
05470   sm->t_state.api_info.parent_proxy_name = sm->t_state.arena.str_store(hostname, strlen(hostname));
05471   sm->t_state.api_info.parent_proxy_port = port;
05472 }
05473 
05474 void
05475 TSHttpTxnUntransformedRespCache(TSHttpTxn txnp, int on)
05476 {
05477   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05478 
05479   HttpSM *sm = (HttpSM *) txnp;
05480   sm->t_state.api_info.cache_untransformed = (on ? true : false);
05481 }
05482 
05483 void
05484 TSHttpTxnTransformedRespCache(TSHttpTxn txnp, int on)
05485 {
05486   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05487 
05488   HttpSM *sm = (HttpSM *) txnp;
05489   sm->t_state.api_info.cache_transformed = (on ? true : false);
05490 }
05491 
05492 
05493 class TSHttpSMCallback:public Continuation
05494 {
05495 public:
05496   TSHttpSMCallback(HttpSM *sm, TSEvent event)
05497     : Continuation(sm->mutex), m_sm(sm), m_event(event)
05498   {
05499     SET_HANDLER(&TSHttpSMCallback::event_handler);
05500   }
05501 
05502   int event_handler(int, void*)
05503   {
05504     m_sm->state_api_callback((int) m_event, 0);
05505     delete this;
05506     return 0;
05507   }
05508 
05509 private:
05510   HttpSM *m_sm;
05511   TSEvent m_event;
05512 };
05513 
05514 
05515 //----------------------------------------------------------------------------
05516 void
05517 TSHttpTxnReenable(TSHttpTxn txnp, TSEvent event)
05518 {
05519   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05520 
05521   HttpSM *sm = (HttpSM *) txnp;
05522   EThread *eth = this_ethread();
05523 
05524   // TS-2271: If this function is being executed on a thread which was not
05525   // created using the ATS EThread API, eth will be NULL, and the
05526   // continuation needs to be called back on a REGULAR thread.
05527   //
05528   // If this function is being executed on a thread created by the API
05529   // which is DEDICATED, the continuation needs to be called back on a
05530   // REGULAR thread.
05531   if (eth == NULL || eth->tt != REGULAR) {
05532     eventProcessor.schedule_imm(new TSHttpSMCallback(sm, event), ET_NET);
05533   } else {
05534     MUTEX_TRY_LOCK(trylock, sm->mutex, eth);
05535     if (!trylock) {
05536       eventProcessor.schedule_imm(new TSHttpSMCallback(sm, event), ET_NET);
05537     } else {
05538       sm->state_api_callback((int) event, 0);
05539     }
05540   }
05541 }
05542 
05543 TSReturnCode
05544 TSHttpArgIndexReserve(const char* name, const char* description, int *arg_idx)
05545 {
05546   sdk_assert(sdk_sanity_check_null_ptr(arg_idx) == TS_SUCCESS);
05547 
05548   int ix = ink_atomic_increment(&next_argv_index, 1);
05549 
05550   if (ix < HTTP_SSN_TXN_MAX_USER_ARG) {
05551     state_arg_table[ix].name = ats_strdup(name);
05552     state_arg_table[ix].name_len = strlen(state_arg_table[ix].name);
05553     if (description)
05554       state_arg_table[ix].description = ats_strdup(description);
05555     *arg_idx = ix;
05556 
05557     return TS_SUCCESS;
05558   }
05559   return TS_ERROR;
05560 }
05561 
05562 TSReturnCode
05563 TSHttpArgIndexLookup(int arg_idx, const char** name, const char** description)
05564 {
05565   if (sdk_sanity_check_null_ptr(name) == TS_SUCCESS) {
05566     if (state_arg_table[arg_idx].name) {
05567       *name = state_arg_table[arg_idx].name;
05568       if (description)
05569         *description = state_arg_table[arg_idx].description;
05570       return TS_SUCCESS;
05571     }
05572   }
05573   return TS_ERROR;
05574 }
05575 
05576 // Not particularly efficient, but good enough for now.
05577 TSReturnCode
05578 TSHttpArgIndexNameLookup(const char* name, int *arg_idx, const char **description)
05579 {
05580   sdk_assert(sdk_sanity_check_null_ptr(arg_idx) == TS_SUCCESS);
05581 
05582   size_t len = strlen(name);
05583 
05584   for (int ix = 0; ix <  next_argv_index; ++ix) {
05585     if ((len == state_arg_table[ix].name_len) && (0 == strcmp(name, state_arg_table[ix].name))) {
05586       if (description)
05587         *description = state_arg_table[ix].description;
05588       *arg_idx = ix;
05589       return TS_SUCCESS;
05590     }
05591   }
05592   return TS_ERROR;
05593 }
05594 
05595 void
05596 TSHttpTxnArgSet(TSHttpTxn txnp, int arg_idx, void *arg)
05597 {
05598   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05599   sdk_assert(arg_idx >= 0 && arg_idx < HTTP_SSN_TXN_MAX_USER_ARG);
05600 
05601   HttpSM *sm = (HttpSM *) txnp;
05602   sm->t_state.user_args[arg_idx] = arg;
05603 }
05604 
05605 void *
05606 TSHttpTxnArgGet(TSHttpTxn txnp, int arg_idx)
05607 {
05608   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05609   sdk_assert(arg_idx >= 0 && arg_idx < HTTP_SSN_TXN_MAX_USER_ARG);
05610 
05611   HttpSM *sm = (HttpSM *) txnp;
05612   return sm->t_state.user_args[arg_idx];
05613 }
05614 
05615 void
05616 TSHttpSsnArgSet(TSHttpSsn ssnp, int arg_idx, void *arg)
05617 {
05618   sdk_assert(sdk_sanity_check_http_ssn(ssnp) == TS_SUCCESS);
05619   sdk_assert(arg_idx >= 0 && arg_idx < HTTP_SSN_TXN_MAX_USER_ARG);
05620 
05621   HttpClientSession *cs = (HttpClientSession *)ssnp;
05622 
05623   cs->set_user_arg(arg_idx, arg);
05624 }
05625 
05626 void *
05627 TSHttpSsnArgGet(TSHttpSsn ssnp, int arg_idx)
05628 {
05629   sdk_assert(sdk_sanity_check_http_ssn(ssnp) == TS_SUCCESS);
05630   sdk_assert(arg_idx >= 0 && arg_idx < HTTP_SSN_TXN_MAX_USER_ARG);
05631 
05632   HttpClientSession *cs = (HttpClientSession *)ssnp;
05633   return cs->get_user_arg(arg_idx);
05634 }
05635 
05636 void
05637 TSHttpTxnSetHttpRetStatus(TSHttpTxn txnp, TSHttpStatus http_retstatus)
05638 {
05639   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05640 
05641   HttpSM *sm = (HttpSM *) txnp;
05642   sm->t_state.http_return_code = (HTTPStatus) http_retstatus;
05643 }
05644 
05645 /* control channel for HTTP */
05646 TSReturnCode
05647 TSHttpTxnCntl(TSHttpTxn txnp, TSHttpCntlType cntl, void *data)
05648 {
05649   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05650 
05651   HttpSM *sm = (HttpSM *) txnp;
05652 
05653   switch (cntl) {
05654   case TS_HTTP_CNTL_GET_LOGGING_MODE:
05655     {
05656       if (data == NULL)
05657         return TS_ERROR;
05658 
05659       intptr_t *rptr = (intptr_t *) data;
05660 
05661       if (sm->t_state.api_info.logging_enabled) {
05662         *rptr = (intptr_t) TS_HTTP_CNTL_ON;
05663       } else {
05664         *rptr = (intptr_t) TS_HTTP_CNTL_OFF;
05665       }
05666 
05667       return TS_SUCCESS;
05668     }
05669 
05670   case TS_HTTP_CNTL_SET_LOGGING_MODE:
05671     if (data != TS_HTTP_CNTL_ON && data != TS_HTTP_CNTL_OFF) {
05672       return TS_ERROR;
05673     } else {
05674       sm->t_state.api_info.logging_enabled = (bool) data;
05675       return TS_SUCCESS;
05676     }
05677     break;
05678 
05679   case TS_HTTP_CNTL_GET_INTERCEPT_RETRY_MODE:
05680     {
05681       if (data == NULL)
05682         return TS_ERROR;
05683 
05684       intptr_t *rptr = (intptr_t *) data;
05685 
05686       if (sm->t_state.api_info.retry_intercept_failures) {
05687         *rptr = (intptr_t) TS_HTTP_CNTL_ON;
05688       } else {
05689         *rptr = (intptr_t) TS_HTTP_CNTL_OFF;
05690       }
05691 
05692       return TS_SUCCESS;
05693     }
05694 
05695   case TS_HTTP_CNTL_SET_INTERCEPT_RETRY_MODE:
05696     if (data != TS_HTTP_CNTL_ON && data != TS_HTTP_CNTL_OFF) {
05697       return TS_ERROR;
05698     } else {
05699       sm->t_state.api_info.retry_intercept_failures = (bool) data;
05700       return TS_SUCCESS;
05701     }
05702   default:
05703     return TS_ERROR;
05704   }
05705 
05706   return TS_ERROR;
05707 }
05708 
05709 /* This is kinda horky, we have to use TSServerState instead of
05710    HttpTransact::ServerState_t, otherwise we have a prototype
05711    mismatch in the public ts/ts.h interfaces. */
05712 TSServerState
05713 TSHttpTxnServerStateGet(TSHttpTxn txnp)
05714 {
05715   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05716 
05717   HttpTransact::State *s = &(((HttpSM *) txnp)->t_state);
05718   return (TSServerState)s->current.state;
05719 }
05720 
05721 void
05722 TSHttpTxnDebugSet(TSHttpTxn txnp, int on)
05723 {
05724   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05725   ((HttpSM *)txnp)->debug_on = on;
05726 }
05727 
05728 int
05729 TSHttpTxnDebugGet(TSHttpTxn txnp)
05730 {
05731   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05732   return ((HttpSM *)txnp)->debug_on;
05733 }
05734 
05735 void
05736 TSHttpSsnDebugSet(TSHttpSsn ssnp, int on)
05737 {
05738   sdk_assert(sdk_sanity_check_http_ssn(ssnp) == TS_SUCCESS);
05739   ((HttpClientSession *)ssnp)->debug_on = on;
05740 }
05741 
05742 int
05743 TSHttpSsnDebugGet(TSHttpSsn ssnp)
05744 {
05745   sdk_assert(sdk_sanity_check_http_ssn(ssnp) == TS_SUCCESS);
05746   return ((HttpClientSession *)ssnp)->debug();
05747 }
05748 
05749 int
05750 TSHttpTxnClientReqHdrBytesGet(TSHttpTxn txnp)
05751 {
05752   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05753 
05754   HttpSM *sm = (HttpSM *) txnp;
05755   return sm->client_request_hdr_bytes;
05756 }
05757 
05758 int64_t
05759 TSHttpTxnClientReqBodyBytesGet(TSHttpTxn txnp)
05760 {
05761   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05762 
05763   HttpSM *sm = (HttpSM *) txnp;
05764   return sm->client_request_body_bytes;
05765 }
05766 
05767 int
05768 TSHttpTxnServerReqHdrBytesGet(TSHttpTxn txnp)
05769 {
05770   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05771 
05772   HttpSM *sm = (HttpSM *) txnp;
05773   return sm->server_request_hdr_bytes;
05774 }
05775 
05776 int64_t
05777 TSHttpTxnServerReqBodyBytesGet(TSHttpTxn txnp)
05778 {
05779   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05780 
05781   HttpSM *sm = (HttpSM *) txnp;
05782   return sm->server_request_body_bytes;
05783 }
05784 
05785 int
05786 TSHttpTxnServerRespHdrBytesGet(TSHttpTxn txnp)
05787 {
05788   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05789 
05790   HttpSM *sm = (HttpSM *) txnp;
05791   return sm->server_response_hdr_bytes;
05792 }
05793 
05794 int64_t
05795 TSHttpTxnServerRespBodyBytesGet(TSHttpTxn txnp)
05796 {
05797   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05798 
05799   HttpSM *sm = (HttpSM *) txnp;
05800   return sm->server_response_body_bytes;
05801 }
05802 
05803 int
05804 TSHttpTxnClientRespHdrBytesGet(TSHttpTxn txnp)
05805 {
05806   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05807 
05808   HttpSM *sm = (HttpSM *) txnp;
05809   return sm->client_response_hdr_bytes;
05810 }
05811 
05812 int64_t
05813 TSHttpTxnClientRespBodyBytesGet(TSHttpTxn txnp)
05814 {
05815   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05816 
05817   HttpSM *sm = (HttpSM *) txnp;
05818   return sm->client_response_body_bytes;
05819 }
05820 
05821 int
05822 TSHttpTxnPushedRespHdrBytesGet(TSHttpTxn txnp)
05823 {
05824   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05825 
05826   HttpSM *sm = (HttpSM *) txnp;
05827   return sm->pushed_response_hdr_bytes;
05828 }
05829 
05830 int64_t
05831 TSHttpTxnPushedRespBodyBytesGet(TSHttpTxn txnp)
05832 {
05833   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05834 
05835   HttpSM *sm = (HttpSM *) txnp;
05836   return sm->pushed_response_body_bytes;
05837 }
05838 
05839 // Get a particular milestone hrtime'r. Note that this can return 0, which means it has not
05840 // been set yet.
05841 TSReturnCode
05842 TSHttpTxnMilestoneGet(TSHttpTxn txnp, TSMilestonesType milestone, ink_hrtime *time)
05843 {
05844   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05845   sdk_assert(sdk_sanity_check_null_ptr(time) == TS_SUCCESS);
05846   HttpSM *sm = (HttpSM *) txnp;
05847   TSReturnCode ret = TS_SUCCESS;
05848 
05849   switch(milestone) {
05850   case TS_MILESTONE_UA_BEGIN:
05851     *time = sm->milestones.ua_begin;
05852     break;
05853   case TS_MILESTONE_UA_READ_HEADER_DONE:
05854     *time = sm->milestones.ua_read_header_done;
05855     break;
05856   case TS_MILESTONE_UA_BEGIN_WRITE:
05857     *time = sm->milestones.ua_begin_write;
05858     break;
05859   case TS_MILESTONE_UA_CLOSE:
05860     *time = sm->milestones.ua_close;
05861     break;
05862   case TS_MILESTONE_SERVER_FIRST_CONNECT:
05863     *time = sm->milestones.server_first_connect;
05864     break;
05865   case TS_MILESTONE_SERVER_CONNECT:
05866     *time = sm->milestones.server_connect;
05867     break;
05868   case TS_MILESTONE_SERVER_CONNECT_END:
05869     *time = sm->milestones.server_connect_end;
05870     break;
05871   case TS_MILESTONE_SERVER_BEGIN_WRITE:
05872     *time = sm->milestones.server_begin_write;
05873     break;
05874   case TS_MILESTONE_SERVER_FIRST_READ:
05875     *time = sm->milestones.server_first_read;
05876     break;
05877   case TS_MILESTONE_SERVER_READ_HEADER_DONE:
05878     *time = sm->milestones.server_read_header_done;
05879     break;
05880   case TS_MILESTONE_SERVER_CLOSE:
05881     *time = sm->milestones.server_close;
05882     break;
05883   case TS_MILESTONE_CACHE_OPEN_READ_BEGIN:
05884     *time = sm->milestones.cache_open_read_begin;
05885     break;
05886   case TS_MILESTONE_CACHE_OPEN_READ_END:
05887     *time = sm->milestones.cache_open_read_end;
05888     break;
05889   case TS_MILESTONE_CACHE_OPEN_WRITE_BEGIN:
05890     *time = sm->milestones.cache_open_write_begin;
05891     break;
05892   case TS_MILESTONE_CACHE_OPEN_WRITE_END:
05893     *time = sm->milestones.cache_open_write_end;
05894     break;
05895   case TS_MILESTONE_DNS_LOOKUP_BEGIN:
05896     *time = sm->milestones.dns_lookup_begin;
05897     break;
05898   case TS_MILESTONE_DNS_LOOKUP_END:
05899     *time = sm->milestones.dns_lookup_end;
05900     break;
05901   case TS_MILESTONE_SM_START:
05902     *time = sm->milestones.sm_start;
05903     break;
05904   case TS_MILESTONE_SM_FINISH:
05905     *time = sm->milestones.sm_finish;
05906     break;
05907   default:
05908     *time = -1;
05909     ret = TS_ERROR;
05910     break;
05911   }
05912 
05913   return ret;
05914 }
05915 
05916 TSReturnCode
05917 TSHttpTxnCachedRespTimeGet(TSHttpTxn txnp, time_t *resp_time)
05918 {
05919   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05920 
05921   HttpSM *sm = (HttpSM *) txnp;
05922   HTTPInfo *cached_obj = sm->t_state.cache_info.object_read;
05923 
05924   if (cached_obj == NULL || !cached_obj->valid())
05925     return TS_ERROR;
05926 
05927   *resp_time = cached_obj->response_received_time_get();
05928   return TS_SUCCESS;
05929 }
05930 
05931 int
05932 TSHttpTxnLookingUpTypeGet(TSHttpTxn txnp)
05933 {
05934   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
05935 
05936   HttpSM *sm = (HttpSM *) txnp;
05937   HttpTransact::State *s = &(sm->t_state);
05938 
05939   return (int)(s->current.request_to);
05940 }
05941 
05942 int
05943 TSHttpCurrentClientConnectionsGet(void)
05944 {
05945   int64_t S;
05946 
05947   HTTP_READ_DYN_SUM(http_current_client_connections_stat, S);
05948   return (int)S;
05949 }
05950 
05951 int
05952 TSHttpCurrentActiveClientConnectionsGet(void)
05953 {
05954   int64_t S;
05955 
05956   HTTP_READ_DYN_SUM(http_current_active_client_connections_stat, S);
05957   return (int)S;
05958 }
05959 
05960 int
05961 TSHttpCurrentIdleClientConnectionsGet(void)
05962 {
05963   int64_t total = 0;
05964   int64_t active = 0;
05965 
05966   HTTP_READ_DYN_SUM(http_current_client_connections_stat, total);
05967   HTTP_READ_DYN_SUM(http_current_active_client_connections_stat, active);
05968 
05969   if (total >= active)
05970     return (int)(total - active);
05971 
05972   return 0;
05973 }
05974 
05975 int
05976 TSHttpCurrentCacheConnectionsGet(void)
05977 {
05978   int64_t S;
05979 
05980   HTTP_READ_DYN_SUM(http_current_cache_connections_stat, S);
05981   return (int)S;
05982 }
05983 
05984 int
05985 TSHttpCurrentServerConnectionsGet(void)
05986 {
05987   int64_t S;
05988 
05989   HTTP_READ_GLOBAL_DYN_SUM(http_current_server_connections_stat, S);
05990   return (int)S;
05991 }
05992 
05993 
05994 /* HTTP alternate selection */
05995 TSReturnCode
05996 TSHttpAltInfoClientReqGet(TSHttpAltInfo infop, TSMBuffer *bufp, TSMLoc *obj)
05997 {
05998   sdk_assert(sdk_sanity_check_alt_info(infop) == TS_SUCCESS);
05999 
06000   HttpAltInfo *info = (HttpAltInfo *) infop;
06001 
06002   *(reinterpret_cast<HTTPHdr**>(bufp)) = &info->m_client_req;
06003   *obj = reinterpret_cast<TSMLoc>(info->m_client_req.m_http);
06004 
06005   return sdk_sanity_check_mbuffer(*bufp);
06006 }
06007 
06008 TSReturnCode
06009 TSHttpAltInfoCachedReqGet(TSHttpAltInfo infop, TSMBuffer *bufp, TSMLoc *obj)
06010 {
06011   sdk_assert(sdk_sanity_check_alt_info(infop) == TS_SUCCESS);
06012 
06013   HttpAltInfo *info = (HttpAltInfo *) infop;
06014 
06015   *(reinterpret_cast<HTTPHdr**>(bufp)) = &info->m_cached_req;
06016   *obj = reinterpret_cast<TSMLoc>(info->m_cached_req.m_http);
06017 
06018   return sdk_sanity_check_mbuffer(*bufp);
06019 }
06020 
06021 TSReturnCode
06022 TSHttpAltInfoCachedRespGet(TSHttpAltInfo infop, TSMBuffer *bufp, TSMLoc *obj)
06023 {
06024   sdk_assert(sdk_sanity_check_alt_info(infop) == TS_SUCCESS);
06025 
06026   HttpAltInfo *info = (HttpAltInfo *) infop;
06027 
06028   *(reinterpret_cast<HTTPHdr**>(bufp)) = &info->m_cached_resp;
06029   *obj = reinterpret_cast<TSMLoc>(info->m_cached_resp.m_http);
06030 
06031   return sdk_sanity_check_mbuffer(*bufp);
06032 }
06033 
06034 void
06035 TSHttpAltInfoQualitySet(TSHttpAltInfo infop, float quality)
06036 {
06037   sdk_assert(sdk_sanity_check_alt_info(infop) == TS_SUCCESS);
06038 
06039   HttpAltInfo *info = (HttpAltInfo *) infop;
06040   info->m_qvalue = quality;
06041 }
06042 
06043 extern HttpSessionAccept *plugin_http_accept;
06044 extern HttpSessionAccept *plugin_http_transparent_accept;
06045 
06046 TSVConn
06047 TSHttpConnectWithPluginId(sockaddr const* addr, char const* tag, int64_t id)
06048 {
06049   sdk_assert(addr);
06050 
06051   sdk_assert(ats_is_ip(addr));
06052   sdk_assert(ats_ip_port_cast(addr));
06053 
06054   if (plugin_http_accept) {
06055     PluginVCCore *new_pvc = PluginVCCore::alloc();
06056 
06057     new_pvc->set_active_addr(addr);
06058     new_pvc->set_plugin_id(id);
06059     new_pvc->set_plugin_tag(tag);
06060     new_pvc->set_accept_cont(plugin_http_accept);
06061 
06062     PluginVC *return_vc = new_pvc->connect();
06063 
06064     if (return_vc != NULL) {
06065       PluginVC* other_side = return_vc->get_other_side();
06066 
06067       if(other_side != NULL) {
06068         other_side->set_is_internal_request(true);
06069       }
06070     }
06071 
06072     return reinterpret_cast<TSVConn>(return_vc);
06073   }
06074 
06075   return NULL;
06076 }
06077 
06078 TSVConn
06079 TSHttpConnect(sockaddr const* addr)
06080 {
06081   return TSHttpConnectWithPluginId(addr, "plugin", 0);
06082 }
06083 
06084 TSVConn
06085 TSHttpConnectTransparent(sockaddr const* client_addr, sockaddr const* server_addr)
06086 {
06087   sdk_assert(ats_is_ip(client_addr));
06088   sdk_assert(ats_is_ip(server_addr));
06089   sdk_assert(!ats_is_ip_any(client_addr));
06090   sdk_assert(ats_ip_port_cast(client_addr));
06091   sdk_assert(!ats_is_ip_any(server_addr));
06092   sdk_assert(ats_ip_port_cast(server_addr));
06093 
06094   if (plugin_http_transparent_accept) {
06095     PluginVCCore *new_pvc = PluginVCCore::alloc();
06096 
06097     // set active address expects host ordering and the above casts do not
06098     // swap when it is required
06099     new_pvc->set_active_addr(client_addr);
06100     new_pvc->set_passive_addr(server_addr);
06101     new_pvc->set_transparent(true, true);
06102     new_pvc->set_accept_cont(plugin_http_transparent_accept);
06103 
06104     PluginVC *return_vc = new_pvc->connect();
06105 
06106     if (return_vc != NULL) {
06107       PluginVC* other_side = return_vc->get_other_side();
06108 
06109       if(other_side != NULL) {
06110         other_side->set_is_internal_request(true);
06111       }
06112     }
06113 
06114     return reinterpret_cast<TSVConn>(return_vc);
06115   }
06116 
06117   return NULL;
06118 }
06119 
06120 /* Actions */
06121 void
06122 TSActionCancel(TSAction actionp)
06123 {
06124   Action *a;
06125   INKContInternal *i;
06126 
06127 /* This is a hack. SHould be handled in ink_types */
06128   if ((uintptr_t) actionp & 0x1) {
06129     a = (Action *) ((uintptr_t) actionp - 1);
06130     i = (INKContInternal *) a->continuation;
06131     i->handle_event_count(EVENT_IMMEDIATE);
06132   } else {
06133     a = (Action *) actionp;
06134   }
06135 
06136   a->cancel();
06137 }
06138 
06139 // Currently no error handling necessary, actionp can be anything.
06140 int
06141 TSActionDone(TSAction actionp)
06142 {
06143   return ((Action *)actionp == ACTION_RESULT_DONE) ? 1 : 0;
06144 }
06145 
06146 /* Connections */
06147 
06148 TSVConn
06149 TSVConnCreate(TSEventFunc event_funcp, TSMutex mutexp)
06150 {
06151   if (mutexp == NULL)
06152     mutexp = (TSMutex) new_ProxyMutex();
06153 
06154   // TODO: probably don't need this if memory allocations fails properly
06155   sdk_assert(sdk_sanity_check_mutex(mutexp) == TS_SUCCESS);
06156 
06157   INKVConnInternal *i = INKVConnAllocator.alloc();
06158 
06159   sdk_assert(sdk_sanity_check_null_ptr((void*)i) == TS_SUCCESS);
06160 
06161   i->init(event_funcp, mutexp);
06162   return reinterpret_cast<TSVConn>(i);
06163 }
06164 
06165 struct ActionSink : public Continuation
06166 {
06167   ActionSink() : Continuation(NULL) {
06168     SET_HANDLER(&ActionSink::mainEvent);
06169   }
06170 
06171   int mainEvent(int event, void * edata) {
06172     // Just sink the event ...
06173     Debug("iocore_net", "sinking event=%d (%s), edata=%p",
06174         event, HttpDebugNames::get_event_name(event), edata);
06175     return EVENT_CONT;
06176   }
06177 };
06178 
06179 static ActionSink a;
06180 
06181 TSVConn
06182 TSVConnFdCreate(int fd)
06183 {
06184   UnixNetVConnection * vc;
06185 
06186   if (unlikely(fd == NO_FD)) {
06187     return NULL;
06188   }
06189 
06190   vc = (UnixNetVConnection *)netProcessor.allocate_vc(this_ethread());
06191   if (vc == NULL) {
06192     return NULL;
06193   }
06194 
06195   // We need to set an Action to handle NET_EVENT_OPEN* events. Since we have a
06196   // socket already, we don't need to do anything in those events, so we can just
06197   // sink them. It's better to sink them here, than to make the NetVC code more
06198   // complex.
06199   vc->action_ = &a;
06200 
06201   vc->id = net_next_connection_number();
06202   vc->submit_time = ink_get_hrtime();
06203   vc->set_is_transparent(false);
06204   vc->mutex = new_ProxyMutex();
06205 
06206   if (vc->connectUp(this_ethread(), fd) != CONNECT_SUCCESS) {
06207     vc->free(this_ethread());
06208     return NULL;
06209   }
06210 
06211   NET_SUM_GLOBAL_DYN_STAT(net_connections_currently_open_stat, 1);
06212   return reinterpret_cast<TSVConn>(vc);
06213 }
06214 
06215 TSVIO
06216 TSVConnReadVIOGet(TSVConn connp)
06217 {
06218   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
06219 
06220   VConnection *vc = (VConnection *)connp;
06221   TSVIO data;
06222 
06223   if (vc->get_data(TS_API_DATA_READ_VIO, &data)) {
06224     return data;
06225   }
06226 
06227   return NULL;
06228 }
06229 
06230 TSVIO
06231 TSVConnWriteVIOGet(TSVConn connp)
06232 {
06233   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
06234 
06235   VConnection *vc = (VConnection *) connp;
06236   TSVIO data;
06237 
06238   if (vc->get_data(TS_API_DATA_WRITE_VIO, &data)) {
06239     return data;
06240   }
06241 
06242   return NULL;
06243 }
06244 
06245 int
06246 TSVConnClosedGet(TSVConn connp)
06247 {
06248   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
06249 
06250   VConnection *vc = (VConnection *) connp;
06251   int data;
06252 
06253   vc->get_data(TS_API_DATA_CLOSED, &data); // Can not fail for this case
06254   return data;
06255 }
06256 
06257 TSVIO
06258 TSVConnRead(TSVConn connp, TSCont contp, TSIOBuffer bufp, int64_t nbytes)
06259 {
06260   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
06261   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
06262   sdk_assert(sdk_sanity_check_iocore_structure(bufp) == TS_SUCCESS);
06263   sdk_assert(nbytes >= 0);
06264 
06265   FORCE_PLUGIN_MUTEX(contp);
06266   VConnection *vc = (VConnection *) connp;
06267 
06268   return reinterpret_cast<TSVIO>(vc->do_io(VIO::READ, (INKContInternal *) contp, nbytes, (MIOBuffer *) bufp));
06269 }
06270 
06271 TSVIO
06272 TSVConnWrite(TSVConn connp, TSCont contp, TSIOBufferReader readerp, int64_t nbytes)
06273 {
06274   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
06275   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
06276   sdk_assert(sdk_sanity_check_iocore_structure(readerp) == TS_SUCCESS);
06277   sdk_assert(nbytes >= 0);
06278 
06279   FORCE_PLUGIN_MUTEX(contp);
06280   VConnection *vc = (VConnection *) connp;
06281 
06282   return reinterpret_cast<TSVIO>(vc->do_io_write((INKContInternal *) contp, nbytes, (IOBufferReader *) readerp));
06283 }
06284 
06285 void
06286 TSVConnClose(TSVConn connp)
06287 {
06288   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
06289 
06290   VConnection *vc = (VConnection *) connp;
06291   vc->do_io_close();
06292 }
06293 
06294 void
06295 TSVConnAbort(TSVConn connp, int error)
06296 {
06297   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
06298 
06299   VConnection *vc = (VConnection *) connp;
06300   vc->do_io_close(error);
06301 }
06302 
06303 void
06304 TSVConnShutdown(TSVConn connp, int read, int write)
06305 {
06306   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
06307 
06308   VConnection *vc = (VConnection *) connp;
06309 
06310   if (read && write) {
06311     vc->do_io_shutdown(IO_SHUTDOWN_READWRITE);
06312   } else if (read) {
06313     vc->do_io_shutdown(IO_SHUTDOWN_READ);
06314   } else if (write) {
06315     vc->do_io_shutdown(IO_SHUTDOWN_WRITE);
06316   }
06317 }
06318 
06319 int64_t
06320 TSVConnCacheObjectSizeGet(TSVConn connp)
06321 {
06322   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
06323 
06324   CacheVC *vc = (CacheVC *)connp;
06325   return vc->get_object_size();
06326 }
06327 
06328 void
06329 TSVConnCacheHttpInfoSet(TSVConn connp, TSCacheHttpInfo infop)
06330 {
06331   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
06332 
06333   CacheVC *vc = (CacheVC *) connp;
06334   if (vc->base_stat == cache_scan_active_stat)
06335     vc->set_http_info((CacheHTTPInfo *) infop);
06336 }
06337 
06338 /* Transformations */
06339 
06340 TSVConn
06341 TSTransformCreate(TSEventFunc event_funcp, TSHttpTxn txnp)
06342 {
06343   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
06344   // TODO: This is somewhat of a leap of faith, but I think a TSHttpTxn is just another
06345   // fancy continuation?
06346   return TSVConnCreate(event_funcp, TSContMutexGet(reinterpret_cast<TSCont>(txnp)));
06347 }
06348 
06349 TSVConn
06350 TSTransformOutputVConnGet(TSVConn connp)
06351 {
06352   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
06353 
06354   VConnection *vc = (VConnection *) connp;
06355   TSVConn data;
06356 
06357   vc->get_data(TS_API_DATA_OUTPUT_VC, &data); // This case can't fail.
06358   return data;
06359 }
06360 
06361 void
06362 TSHttpTxnServerIntercept(TSCont contp, TSHttpTxn txnp)
06363 {
06364   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
06365   sdk_assert(sdk_sanity_check_continuation(contp) == TS_SUCCESS);
06366 
06367   HttpSM *http_sm = (HttpSM *)txnp;
06368   INKContInternal *i = (INKContInternal *)contp;
06369 
06370   // Must have a mutex
06371   sdk_assert(sdk_sanity_check_null_ptr((void*)i->mutex) == TS_SUCCESS);
06372 
06373   http_sm->plugin_tunnel_type = HTTP_PLUGIN_AS_SERVER;
06374   http_sm->plugin_tunnel = PluginVCCore::alloc();
06375   http_sm->plugin_tunnel->set_accept_cont(i);
06376 }
06377 
06378 void
06379 TSHttpTxnIntercept(TSCont contp, TSHttpTxn txnp)
06380 {
06381   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
06382   sdk_assert(sdk_sanity_check_continuation(contp) == TS_SUCCESS);
06383 
06384   HttpSM *http_sm = (HttpSM *) txnp;
06385   INKContInternal *i = (INKContInternal *) contp;
06386 
06387   // Must have a mutex
06388   sdk_assert(sdk_sanity_check_null_ptr((void*)i->mutex) == TS_SUCCESS);
06389 
06390   http_sm->plugin_tunnel_type = HTTP_PLUGIN_AS_INTERCEPT;
06391   http_sm->plugin_tunnel = PluginVCCore::alloc();
06392   http_sm->plugin_tunnel->set_accept_cont(i);
06393 }
06394 
06395 /* Net VConnections */
06396 void
06397 TSVConnInactivityTimeoutSet(TSVConn connp, TSHRTime timeout)
06398 {
06399   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
06400 
06401   NetVConnection *vc = (NetVConnection *) connp;
06402   vc->set_inactivity_timeout(timeout);
06403 }
06404 
06405 void
06406 TSVConnInactivityTimeoutCancel(TSVConn connp)
06407 {
06408   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
06409 
06410   NetVConnection *vc = (NetVConnection *) connp;
06411   vc->cancel_inactivity_timeout();
06412 }
06413 
06414 void
06415 TSVConnActiveTimeoutSet(TSVConn connp, TSHRTime timeout)
06416 {
06417   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
06418 
06419   NetVConnection *vc = (NetVConnection *) connp;
06420   vc->set_active_timeout(timeout);
06421 }
06422 
06423 void
06424 TSVConnActiveTimeoutCancel(TSVConn connp)
06425 {
06426   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
06427 
06428   NetVConnection *vc = (NetVConnection *) connp;
06429   vc->cancel_active_timeout();
06430 }
06431 
06432 sockaddr const*
06433 TSNetVConnLocalAddrGet(TSVConn connp) {
06434   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
06435   NetVConnection* vc = reinterpret_cast<NetVConnection*>(connp);
06436   return vc->get_local_addr();
06437 }
06438 
06439 
06440 sockaddr const*
06441 TSNetVConnRemoteAddrGet(TSVConn connp) {
06442   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
06443   NetVConnection* vc = reinterpret_cast<NetVConnection*>(connp);
06444   return vc->get_remote_addr();
06445 }
06446 
06447 TSAction
06448 TSNetConnect(TSCont contp, sockaddr const* addr)
06449 {
06450   sdk_assert(sdk_sanity_check_continuation(contp) == TS_SUCCESS);
06451   sdk_assert(ats_is_ip(addr));
06452 
06453   FORCE_PLUGIN_MUTEX(contp);
06454 
06455   return reinterpret_cast<TSAction>(
06456     netProcessor.connect_re(reinterpret_cast<INKContInternal*>(contp), addr)
06457   );
06458 }
06459 
06460 TSAction
06461 TSNetConnectTransparent(TSCont contp, sockaddr const* client_addr, sockaddr const* server_addr)
06462 {
06463   sdk_assert(sdk_sanity_check_continuation(contp) == TS_SUCCESS);
06464   sdk_assert(ats_is_ip(server_addr));
06465   sdk_assert(ats_ip_are_compatible(client_addr, server_addr));
06466 
06467   NetVCOptions opt;
06468   opt.addr_binding = NetVCOptions::FOREIGN_ADDR;
06469   opt.local_ip.assign(client_addr);
06470   opt.local_port = ats_ip_port_host_order(client_addr);
06471 
06472   FORCE_PLUGIN_MUTEX(contp);
06473 
06474   return reinterpret_cast<TSAction>(
06475     netProcessor.connect_re(reinterpret_cast<INKContInternal*>(contp), server_addr, &opt)
06476   );
06477 }
06478 
06479 TSAction
06480 TSNetAccept(TSCont contp, int port, int domain, int accept_threads)
06481 {
06482   NetProcessor::AcceptOptions opt;
06483 
06484   sdk_assert(sdk_sanity_check_continuation(contp) == TS_SUCCESS);
06485   sdk_assert(port > 0);
06486   sdk_assert(accept_threads >= -1);
06487 
06488   // TODO: Does this imply that only one "accept thread" could be
06489   // doing an accept at any time?
06490   FORCE_PLUGIN_MUTEX(contp);
06491 
06492   // If it's not IPv6, force to IPv4.
06493   opt.ip_family = domain == AF_INET6 ? AF_INET6 : AF_INET;
06494   opt.accept_threads = accept_threads;
06495   opt.local_port = port;
06496   opt.frequent_accept = false;
06497 
06498   INKContInternal *i = (INKContInternal *) contp;
06499   return (TSAction)netProcessor.accept(i, opt);
06500 }
06501 
06502 /* From proxy/http/HttpProxyServerMain.c: */
06503 extern bool ssl_register_protocol(const char *, Continuation *);
06504 extern bool ssl_unregister_protocol(const char *, Continuation *);
06505 
06506 TSReturnCode
06507 #if TS_USE_TLS_NPN
06508 TSNetAcceptNamedProtocol(TSCont contp, const char * protocol)
06509 {
06510   sdk_assert(protocol != NULL);
06511   sdk_assert(contp != NULL);
06512   sdk_assert(sdk_sanity_check_continuation(contp) == TS_SUCCESS);
06513 
06514   if (!ssl_register_protocol(protocol, (INKContInternal *)contp)) {
06515     ssl_unregister_protocol(protocol, (INKContInternal *)contp);
06516     return TS_ERROR;
06517   }
06518 
06519   return TS_SUCCESS;
06520 }
06521 #else /* TS_USE_TLS_NPN */
06522 TSNetAcceptNamedProtocol(TSCont, const char *)
06523 {
06524   return TS_ERROR;
06525 }
06526 #endif /* TS_USE_TLS_NPN */
06527 
06528 /* DNS Lookups */
06529 TSAction
06530 TSHostLookup(TSCont contp, const char *hostname, size_t namelen)
06531 {
06532   sdk_assert(sdk_sanity_check_continuation(contp) == TS_SUCCESS);
06533   sdk_assert(sdk_sanity_check_null_ptr((void*)hostname) == TS_SUCCESS);
06534   sdk_assert(namelen > 0);
06535 
06536   FORCE_PLUGIN_MUTEX(contp);
06537 
06538   INKContInternal *i = (INKContInternal *) contp;
06539   return (TSAction)hostDBProcessor.getbyname_re(i, hostname, namelen);
06540 }
06541 
06542 sockaddr const*
06543 TSHostLookupResultAddrGet(TSHostLookupResult lookup_result)
06544 {
06545   sdk_assert(sdk_sanity_check_hostlookup_structure(lookup_result) == TS_SUCCESS);
06546   HostDBInfo* di = reinterpret_cast<HostDBInfo*>(lookup_result);
06547   return di->ip();
06548 }
06549 
06550 /*
06551  * checks if the cache is ready
06552  */
06553 
06554 /* Only TSCacheReady exposed in SDK. No need of TSCacheDataTypeReady */
06555 /* because SDK cache API supports only the data type: NONE */
06556 TSReturnCode
06557 TSCacheReady(int *is_ready)
06558 {
06559   sdk_assert(sdk_sanity_check_null_ptr((void*)is_ready) == TS_SUCCESS);
06560   return TSCacheDataTypeReady(TS_CACHE_DATA_TYPE_NONE, is_ready);
06561 }
06562 
06563 /* Private API (used by Mixt) */
06564 TSReturnCode
06565 TSCacheDataTypeReady(TSCacheDataType type, int *is_ready)
06566 {
06567   sdk_assert(sdk_sanity_check_null_ptr((void*)is_ready) == TS_SUCCESS);
06568 
06569   CacheFragType frag_type;
06570 
06571   switch (type) {
06572   case TS_CACHE_DATA_TYPE_NONE:
06573     frag_type = CACHE_FRAG_TYPE_NONE;
06574     break;
06575   case TS_CACHE_DATA_TYPE_OTHER:      /* other maps to http */
06576   case TS_CACHE_DATA_TYPE_HTTP:
06577     frag_type = CACHE_FRAG_TYPE_HTTP;
06578     break;
06579   default:
06580     *is_ready = 0;
06581     return TS_ERROR;
06582   }
06583 
06584   *is_ready = cacheProcessor.IsCacheReady(frag_type);
06585   return TS_SUCCESS;
06586 }
06587 
06588 /* Cache VConnections */
06589 TSAction
06590 TSCacheRead(TSCont contp, TSCacheKey key)
06591 {
06592   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
06593   sdk_assert(sdk_sanity_check_cachekey(key) == TS_SUCCESS);
06594 
06595   FORCE_PLUGIN_MUTEX(contp);
06596 
06597   CacheInfo *info = (CacheInfo *) key;
06598   Continuation *i = (INKContInternal *) contp;
06599 
06600   return (TSAction)cacheProcessor.open_read(i, &info->cache_key, true, info->frag_type, info->hostname, info->len);
06601 }
06602 
06603 TSAction
06604 TSCacheWrite(TSCont contp, TSCacheKey key)
06605 {
06606   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
06607   sdk_assert(sdk_sanity_check_cachekey(key) == TS_SUCCESS);
06608 
06609   FORCE_PLUGIN_MUTEX(contp);
06610 
06611   CacheInfo *info = (CacheInfo *) key;
06612   Continuation *i = (INKContInternal *) contp;
06613 
06614   return (TSAction)cacheProcessor.open_write(i, &info->cache_key, true, info->frag_type, 0, false, info->pin_in_cache,
06615                                              info->hostname, info->len);
06616 }
06617 
06618 TSAction
06619 TSCacheRemove(TSCont contp, TSCacheKey key)
06620 {
06621   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
06622   sdk_assert(sdk_sanity_check_cachekey(key) == TS_SUCCESS);
06623 
06624   FORCE_PLUGIN_MUTEX(contp);
06625 
06626   CacheInfo *info = (CacheInfo *) key;
06627   INKContInternal *i = (INKContInternal *) contp;
06628 
06629   return (TSAction)cacheProcessor.remove(i, &info->cache_key, true, info->frag_type, true, false, info->hostname, info->len);
06630 }
06631 
06632 TSAction
06633 TSCacheScan(TSCont contp, TSCacheKey key, int KB_per_second)
06634 {
06635   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
06636   // NOTE: key can be NULl here, so don't check for it.
06637 
06638   FORCE_PLUGIN_MUTEX(contp);
06639 
06640   INKContInternal *i = (INKContInternal *) contp;
06641 
06642   if (key) {
06643     CacheInfo *info = (CacheInfo *) key;
06644     return (TSAction)cacheProcessor.scan(i, info->hostname, info->len, KB_per_second);
06645   }
06646   return reinterpret_cast<TSAction>(cacheProcessor.scan(i, 0, 0, KB_per_second));
06647 }
06648 
06649 
06650 /************************   REC Stats API    **************************/
06651 int
06652 TSStatCreate(const char *the_name, TSRecordDataType the_type, TSStatPersistence persist, TSStatSync sync)
06653 {
06654   int id = ink_atomic_increment(&api_rsb_index, 1);
06655   RecRawStatSyncCb syncer = RecRawStatSyncCount;
06656 
06657   // TODO: This only supports "int" data types at this point, since the "Raw" stats
06658   // interfaces only supports integers. Going forward, we could extend either the "Raw"
06659   // stats APIs, or make non-int use the direct (synchronous) stats APIs (slower).
06660   if ((sdk_sanity_check_null_ptr((void*)the_name) != TS_SUCCESS) ||
06661       (sdk_sanity_check_null_ptr((void*)api_rsb) != TS_SUCCESS) ||
06662       (id >= api_rsb->max_stats))
06663     return TS_ERROR;
06664 
06665   switch (sync) {
06666   case TS_STAT_SYNC_SUM:
06667     syncer = RecRawStatSyncSum;
06668     break;
06669   case TS_STAT_SYNC_AVG:
06670     syncer = RecRawStatSyncAvg;
06671     break;
06672   case TS_STAT_SYNC_TIMEAVG:
06673     syncer = RecRawStatSyncHrTimeAvg;
06674     break;
06675   default:
06676     syncer = RecRawStatSyncCount;
06677     break;
06678   }
06679 
06680   switch (persist) {
06681   case TS_STAT_PERSISTENT:
06682     RecRegisterRawStat(api_rsb, RECT_PLUGIN, the_name, (RecDataT)the_type, RECP_PERSISTENT, id, syncer);
06683     break;
06684   case TS_STAT_NON_PERSISTENT:
06685     RecRegisterRawStat(api_rsb, RECT_PLUGIN, the_name, (RecDataT)the_type, RECP_NON_PERSISTENT, id, syncer);
06686     break;
06687   default:
06688     return TS_ERROR;
06689   }
06690 
06691   return id;
06692 }
06693 
06694 void
06695 TSStatIntIncrement(int the_stat, TSMgmtInt amount)
06696 {
06697   RecIncrRawStat(api_rsb, NULL, the_stat, amount);
06698 }
06699 
06700 void
06701 TSStatIntDecrement(int the_stat, TSMgmtInt amount)
06702 {
06703   RecDecrRawStat(api_rsb, NULL, the_stat, amount);
06704 }
06705 
06706 TSMgmtInt
06707 TSStatIntGet(int the_stat)
06708 {
06709   TSMgmtInt value;
06710 
06711   RecGetGlobalRawStatSum(api_rsb, the_stat, &value);
06712   return value;
06713 }
06714 
06715 void
06716 TSStatIntSet(int the_stat, TSMgmtInt value)
06717 {
06718   RecSetGlobalRawStatSum(api_rsb, the_stat, value);
06719 }
06720 
06721 TSReturnCode
06722 TSStatFindName(const char* name, int *idp)
06723 {
06724   sdk_assert(sdk_sanity_check_null_ptr((void*)name) == TS_SUCCESS);
06725 
06726   if (RecGetRecordOrderAndId(name, NULL, idp) == REC_ERR_OKAY)
06727     return TS_SUCCESS;
06728 
06729   return TS_ERROR;
06730 }
06731 
06732 
06733 /**************************    Stats API    ****************************/
06734 // THESE APIS ARE DEPRECATED, USE THE REC APIs INSTEAD
06735 // #define ink_sanity_check_stat_structure(_x) TS_SUCCESS
06736 
06737 inline TSReturnCode
06738 ink_sanity_check_stat_structure(void *obj)
06739 {
06740   if (obj == NULL)
06741     return TS_ERROR;
06742 
06743   return TS_SUCCESS;
06744 }
06745 
06746 /**************************   Tracing API   ****************************/
06747 // returns 1 or 0 to indicate whether TS is being run with a debug tag.
06748 int
06749 TSIsDebugTagSet(const char *t)
06750 {
06751   return (diags->on(t, DiagsTagType_Debug)) ? 1 : 0;
06752 }
06753 
06754 void
06755 TSDebugSpecific(int debug_flag, const char *tag, const char *format_str, ...)
06756 {
06757   if (diags->on(tag, DiagsTagType_Debug) || (debug_flag  && diags->on())) {
06758     va_list ap;
06759 
06760     va_start(ap, format_str);
06761     diags->print_va(tag, DL_Diag, NULL, format_str, ap);
06762     va_end(ap);
06763   }
06764 }
06765 
06766 // Plugins would use TSDebug just as the TS internal uses Debug
06767 // e.g. TSDebug("plugin-cool", "Snoopy is a cool guy even after %d requests.\n", num_reqs);
06768 void
06769 TSDebug(const char *tag, const char *format_str, ...)
06770 {
06771   if (diags->on(tag, DiagsTagType_Debug)) {
06772     va_list ap;
06773 
06774     va_start(ap, format_str);
06775     diags->print_va(tag, DL_Diag, NULL, format_str, ap);
06776     va_end(ap);
06777   }
06778 }
06779 
06780 /**************************   Logging API   ****************************/
06781 
06782 TSReturnCode
06783 TSTextLogObjectCreate(const char *filename, int mode, TSTextLogObject *new_object)
06784 {
06785   sdk_assert(sdk_sanity_check_null_ptr((void*)filename) == TS_SUCCESS);
06786   sdk_assert(sdk_sanity_check_null_ptr((void*)new_object) == TS_SUCCESS);
06787 
06788   if (mode <0 || mode >= TS_LOG_MODE_INVALID_FLAG) {
06789     *new_object = NULL;
06790     return TS_ERROR;
06791   }
06792 
06793   TextLogObject *tlog = new TextLogObject(filename, Log::config->logfile_dir,
06794                                           (bool) mode & TS_LOG_MODE_ADD_TIMESTAMP,
06795                                           NULL,
06796                                           Log::config->rolling_enabled,
06797                                           Log::config->collation_preproc_threads,
06798                                           Log::config->rolling_interval_sec,
06799                                           Log::config->rolling_offset_hr,
06800                                           Log::config->rolling_size_mb);
06801   if (tlog == NULL) {
06802     *new_object = NULL;
06803     return TS_ERROR;
06804   }
06805 
06806   int err = (mode & TS_LOG_MODE_DO_NOT_RENAME ?
06807              Log::config->log_object_manager.manage_api_object(tlog, 0) :
06808              Log::config->log_object_manager.manage_api_object(tlog));
06809   if (err != LogObjectManager::NO_FILENAME_CONFLICTS) {
06810     delete tlog;
06811     *new_object = NULL;
06812     return TS_ERROR;
06813   }
06814 
06815   *new_object = (TSTextLogObject) tlog;
06816   return TS_SUCCESS;
06817 }
06818 
06819 TSReturnCode
06820 TSTextLogObjectWrite(TSTextLogObject the_object, const char *format, ...)
06821 {
06822   sdk_assert(sdk_sanity_check_iocore_structure(the_object) == TS_SUCCESS);
06823   sdk_assert(sdk_sanity_check_null_ptr((void*)format) == TS_SUCCESS);
06824 
06825   TSReturnCode retVal = TS_SUCCESS;
06826 
06827   va_list ap;
06828   va_start(ap, format);
06829   switch (((TextLogObject *) the_object)->va_write(format, ap)) {
06830   case (Log::LOG_OK):
06831   case (Log::SKIP):
06832   case (Log::AGGR):
06833     break;
06834   case (Log::FULL):
06835     retVal = TS_ERROR;
06836     break;
06837   case (Log::FAIL):
06838     retVal = TS_ERROR;
06839     break;
06840   default:
06841     ink_assert(!"invalid return code");
06842   }
06843   va_end(ap);
06844 
06845   return retVal;
06846 }
06847 
06848 void
06849 TSTextLogObjectFlush(TSTextLogObject the_object)
06850 {
06851   sdk_assert(sdk_sanity_check_iocore_structure(the_object) == TS_SUCCESS);
06852 
06853   ((TextLogObject *) the_object)->force_new_buffer();
06854 }
06855 
06856 TSReturnCode
06857 TSTextLogObjectDestroy(TSTextLogObject the_object)
06858 {
06859   sdk_assert(sdk_sanity_check_iocore_structure(the_object) == TS_SUCCESS);
06860 
06861   if (Log::config->log_object_manager.unmanage_api_object((TextLogObject *) the_object))
06862     return TS_SUCCESS;
06863 
06864   return TS_ERROR;
06865 }
06866 
06867 void
06868 TSTextLogObjectHeaderSet(TSTextLogObject the_object, const char *header)
06869 {
06870   sdk_assert(sdk_sanity_check_iocore_structure(the_object) == TS_SUCCESS);
06871 
06872   ((TextLogObject *) the_object)->set_log_file_header(header);
06873 }
06874 
06875 TSReturnCode
06876 TSTextLogObjectRollingEnabledSet(TSTextLogObject the_object, int rolling_enabled)
06877 {
06878   sdk_assert(sdk_sanity_check_iocore_structure(the_object) == TS_SUCCESS);
06879 
06880   if (LogRollingEnabledIsValid(rolling_enabled)) {
06881     ((TextLogObject *) the_object)->set_rolling_enabled((Log::RollingEnabledValues)rolling_enabled);
06882     return TS_SUCCESS;
06883   }
06884 
06885   return TS_ERROR;
06886 }
06887 
06888 void
06889 TSTextLogObjectRollingIntervalSecSet(TSTextLogObject the_object, int rolling_interval_sec)
06890 {
06891   sdk_assert(sdk_sanity_check_iocore_structure(the_object) == TS_SUCCESS);
06892 
06893   ((TextLogObject *) the_object)->set_rolling_interval_sec(rolling_interval_sec);
06894 }
06895 
06896 void
06897 TSTextLogObjectRollingOffsetHrSet(TSTextLogObject the_object, int rolling_offset_hr)
06898 {
06899   sdk_assert(sdk_sanity_check_iocore_structure(the_object) == TS_SUCCESS);
06900 
06901   ((TextLogObject *) the_object)->set_rolling_offset_hr(rolling_offset_hr);
06902 }
06903 
06904 TSReturnCode
06905 TSHttpSsnClientFdGet(TSHttpSsn ssnp, int *fdp)
06906 {
06907   sdk_assert(sdk_sanity_check_null_ptr((void*)fdp) == TS_SUCCESS);
06908 
06909   HttpClientSession *cs = (HttpClientSession *) ssnp;
06910 
06911   if (cs == NULL)
06912     return TS_ERROR;
06913 
06914   NetVConnection *vc = cs->get_netvc();
06915   if (vc == NULL)
06916     return TS_ERROR;
06917 
06918   *fdp = vc->get_socket();
06919   return TS_SUCCESS;
06920 }
06921 TSReturnCode
06922 TSHttpTxnClientFdGet(TSHttpTxn txnp, int *fdp)
06923 {
06924   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
06925   sdk_assert(sdk_sanity_check_null_ptr((void*)fdp) == TS_SUCCESS);
06926 
06927   TSHttpSsn ssnp = TSHttpTxnSsnGet(txnp);
06928   return TSHttpSsnClientFdGet(ssnp, fdp);
06929 }
06930 
06931 /* Matcher Utils */
06932 char *
06933 TSMatcherReadIntoBuffer(char *file_name, int *file_len)
06934 {
06935   sdk_assert(sdk_sanity_check_null_ptr((void*)file_name) == TS_SUCCESS);
06936   return readIntoBuffer((char *) file_name, "TSMatcher", file_len);
06937 }
06938 
06939 char *
06940 TSMatcherTokLine(char *buffer, char **last)
06941 {
06942   sdk_assert(sdk_sanity_check_null_ptr((void*)buffer) == TS_SUCCESS);
06943   return tokLine(buffer, last);
06944 }
06945 
06946 char *
06947 TSMatcherExtractIPRange(char *match_str, uint32_t *addr1, uint32_t *addr2)
06948 {
06949   sdk_assert(sdk_sanity_check_null_ptr((void*)match_str) == TS_SUCCESS);
06950   return (char*)ExtractIpRange(match_str, addr1, addr2);
06951 }
06952 // Conflict in header due to overload (must be C compatible).
06953 char *
06954 TSMatcherExtractIPRange(char *match_str, sockaddr* addr1, sockaddr* addr2)
06955 {
06956   sdk_assert(sdk_sanity_check_null_ptr((void*)match_str) == TS_SUCCESS);
06957   return (char*)ExtractIpRange(match_str, addr1, addr2);
06958 }
06959 
06960 TSMatcherLine
06961 TSMatcherLineCreate(void)
06962 {
06963   return reinterpret_cast<TSMatcherLine>(ats_malloc(sizeof(matcher_line)));
06964 }
06965 
06966 void
06967 TSMatcherLineDestroy(TSMatcherLine ml)
06968 {
06969   sdk_assert(sdk_sanity_check_null_ptr((void*)ml) == TS_SUCCESS);
06970   ats_free(ml);
06971 }
06972 
06973 const char *
06974 TSMatcherParseSrcIPConfigLine(char *line, TSMatcherLine ml)
06975 {
06976   sdk_assert(sdk_sanity_check_null_ptr((void*)line) == TS_SUCCESS);
06977   return parseConfigLine(line, (matcher_line *) ml, &ip_allow_tags);
06978 }
06979 
06980 char *
06981 TSMatcherLineName(TSMatcherLine ml, int element)
06982 {
06983   sdk_assert(sdk_sanity_check_null_ptr((void*)ml) == TS_SUCCESS);
06984   return (((matcher_line *) ml)->line)[0][element];
06985 }
06986 
06987 char *
06988 TSMatcherLineValue(TSMatcherLine ml, int element)
06989 {
06990   sdk_assert(sdk_sanity_check_null_ptr((void*)ml) == TS_SUCCESS);
06991   return (((matcher_line *) ml)->line)[1][element];
06992 }
06993 
06994 /* Configuration Setting */
06995 TSReturnCode
06996 TSMgmtConfigIntSet(const char *var_name, TSMgmtInt value)
06997 {
06998   TSMgmtInt result;
06999   char *buffer;
07000 
07001   // is this a valid integer?
07002   if (TSMgmtIntGet(var_name, &result) != TS_SUCCESS)
07003     return TS_ERROR;
07004 
07005   // construct a buffer
07006   int buffer_size = strlen(var_name) + 1 + 32 + 1 + 64 + 1;
07007 
07008   buffer = (char *) alloca(buffer_size);
07009   snprintf(buffer, buffer_size, "%s %d %" PRId64 "", var_name, MGMT_INT, value);
07010 
07011   // tell manager to set the configuration; note that this is not
07012   // transactional (e.g. we return control to the plugin before the
07013   // value is commited to disk by the manager)
07014   RecSignalManager(MGMT_SIGNAL_PLUGIN_SET_CONFIG, buffer);
07015 
07016   return TS_SUCCESS;
07017 }
07018 
07019 void
07020 TSICPFreshnessFuncSet(TSPluginFreshnessCalcFunc funcp)
07021 {
07022   pluginFreshnessCalcFunc = (PluginFreshnessCalcFunc) funcp;
07023 }
07024 
07025 TSReturnCode
07026 TSICPCachedReqGet(TSCont contp, TSMBuffer *bufp, TSMLoc *obj)
07027 {
07028   sdk_assert(sdk_sanity_check_continuation(contp) == TS_SUCCESS);
07029   sdk_assert(sdk_sanity_check_null_ptr((void*)bufp) == TS_SUCCESS);
07030   sdk_assert(sdk_sanity_check_null_ptr((void*)obj) == TS_SUCCESS);
07031 
07032   ICPPeerReadCont *sm = (ICPPeerReadCont *)contp;
07033   HTTPInfo *cached_obj;
07034 
07035   cached_obj = sm->_object_read;
07036   if (cached_obj == NULL || !cached_obj->valid())
07037     return TS_ERROR;
07038 
07039   HTTPHdr *cached_hdr = cached_obj->request_get();
07040   if (!cached_hdr->valid())
07041     return TS_ERROR;;
07042 
07043   // We can't use the HdrHeapSDKHandle structure in the RamCache since multiple
07044   //  threads can access.  We need to create our own for the transaction and return that.
07045   HdrHeapSDKHandle **handle = &(sm->_cache_req_hdr_heap_handle);
07046 
07047   if (*handle == NULL) {
07048     *handle = (HdrHeapSDKHandle *)ats_malloc(sizeof(HdrHeapSDKHandle));
07049     (*handle)->m_heap = cached_hdr->m_heap;
07050   }
07051 
07052   *(reinterpret_cast<HdrHeapSDKHandle**>(bufp)) = *handle;
07053   *obj = reinterpret_cast<TSMLoc>(cached_hdr->m_http);
07054 
07055   return sdk_sanity_check_mbuffer(*bufp);
07056 }
07057 
07058 TSReturnCode
07059 TSICPCachedRespGet(TSCont contp, TSMBuffer *bufp, TSMLoc *obj)
07060 {
07061   sdk_assert(sdk_sanity_check_continuation(contp) == TS_SUCCESS);
07062   sdk_assert(sdk_sanity_check_null_ptr((void*)bufp) == TS_SUCCESS);
07063   sdk_assert(sdk_sanity_check_null_ptr((void*)obj) == TS_SUCCESS);
07064 
07065   ICPPeerReadCont *sm = (ICPPeerReadCont *) contp;
07066   HTTPInfo *cached_obj;
07067 
07068   cached_obj = sm->_object_read;
07069   if (cached_obj == NULL || !cached_obj->valid())
07070     return TS_ERROR;
07071 
07072   HTTPHdr *cached_hdr = cached_obj->response_get();
07073   if (!cached_hdr->valid())
07074     return TS_ERROR;
07075 
07076   // We can't use the HdrHeapSDKHandle structure in the RamCache since multiple
07077   //  threads can access.  We need to create our own for the transaction and return that.
07078   HdrHeapSDKHandle **handle = &(sm->_cache_resp_hdr_heap_handle);
07079 
07080   if (*handle == NULL) {
07081     *handle = (HdrHeapSDKHandle *)ats_malloc(sizeof(HdrHeapSDKHandle));
07082     (*handle)->m_heap = cached_hdr->m_heap;
07083   }
07084 
07085   *(reinterpret_cast<HdrHeapSDKHandle**>(bufp)) = *handle;
07086   *obj = reinterpret_cast<TSMLoc>(cached_hdr->m_http);
07087 
07088   return sdk_sanity_check_mbuffer(*bufp);
07089 }
07090 
07091 TSReturnCode
07092 TSCacheUrlSet(TSHttpTxn txnp, const char *url, int length)
07093 {
07094   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
07095 
07096   HttpSM *sm = (HttpSM *) txnp;
07097   Debug("cache_url", "[TSCacheUrlSet]");
07098 
07099   if (sm->t_state.cache_info.lookup_url == NULL) {
07100     Debug("cache_url", "[TSCacheUrlSet] changing the cache url to: %s", url);
07101 
07102     if (length == -1)
07103       length = strlen(url);
07104 
07105     sm->t_state.cache_info.lookup_url_storage.create(NULL);
07106     sm->t_state.cache_info.lookup_url = &(sm->t_state.cache_info.lookup_url_storage);
07107     sm->t_state.cache_info.lookup_url->parse(url, length);
07108     return TS_SUCCESS;
07109   }
07110 
07111   return TS_ERROR;
07112 }
07113 
07114 void
07115 TSCacheHttpInfoKeySet(TSCacheHttpInfo infop, TSCacheKey keyp)
07116 {
07117   // TODO: Check input ?
07118   CacheHTTPInfo *info = (CacheHTTPInfo *) infop;
07119   INK_MD5 *key = (INK_MD5 *)keyp;
07120 
07121   info->object_key_set(*key);
07122 }
07123 
07124 void
07125 TSCacheHttpInfoSizeSet(TSCacheHttpInfo infop, int64_t size)
07126 {
07127   // TODO: Check input ?
07128   CacheHTTPInfo *info = (CacheHTTPInfo *) infop;
07129 
07130   info->object_size_set(size);
07131 }
07132 
07133 // This API tells the core to follow normal (301/302) redirects using the
07134 // standard Location: URL. This does not need to be called if you set an
07135 // explicit URL using TSRedirectUrlSet().
07136 TSReturnCode
07137 TSHttpTxnFollowRedirect(TSHttpTxn txnp, int on)
07138 {
07139   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
07140 
07141   HttpSM *sm = (HttpSM *) txnp;
07142 
07143   sm->enable_redirection = (on ? true : false);
07144   return TS_SUCCESS;
07145 }
07146 
07147 // this function should be called at TS_EVENT_HTTP_READ_RESPONSE_HDR
07148 void
07149 TSHttpTxnRedirectUrlSet(TSHttpTxn txnp, const char* url, const int url_len)
07150 {
07151   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
07152   sdk_assert(sdk_sanity_check_null_ptr((void*)url) == TS_SUCCESS);
07153 
07154   HttpSM *sm = (HttpSM*) txnp;
07155 
07156   if (sm->redirect_url != NULL) {
07157     ats_free(sm->redirect_url);
07158     sm->redirect_url = NULL;
07159     sm->redirect_url_len = 0;
07160   }
07161 
07162   sm->redirect_url = (char*)url;
07163   sm->redirect_url_len = url_len;
07164   sm->enable_redirection = true;
07165 }
07166 
07167 // Deprecated, remove for v6.0.0
07168 void
07169 TSRedirectUrlSet(TSHttpTxn txnp, const char* url, const int url_len)
07170 {
07171   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
07172   sdk_assert(sdk_sanity_check_null_ptr((void*)url) == TS_SUCCESS);
07173 
07174   HttpSM *sm = (HttpSM*) txnp;
07175 
07176   if (sm->redirect_url != NULL) {
07177     ats_free(sm->redirect_url);
07178     sm->redirect_url = NULL;
07179     sm->redirect_url_len = 0;
07180   }
07181 
07182   sm->redirect_url = (char*)ats_malloc(url_len + 1);
07183   ink_strlcpy(sm->redirect_url, url, url_len + 1);
07184   sm->redirect_url_len = url_len;
07185   // have to turn redirection on for this transaction if user wants to redirect to another URL
07186   if (sm->enable_redirection == false) {
07187     sm->enable_redirection = true;
07188     // max-out "redirection_tries" to avoid the regular redirection being turned on in
07189     // this transaction improperly. This variable doesn't affect the custom-redirection
07190     sm->redirection_tries = HttpConfig::m_master.number_of_redirections;
07191   }
07192 }
07193 
07194 const char*
07195 TSHttpTxnRedirectUrlGet(TSHttpTxn txnp, int *url_len_ptr)
07196 {
07197   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
07198 
07199   HttpSM *sm = (HttpSM*)txnp;
07200 
07201   *url_len_ptr = sm->redirect_url_len;
07202   return sm->redirect_url;
07203 }
07204 
07205 // Deprecated, remove for v6.0.0
07206 const char*
07207 TSRedirectUrlGet(TSHttpTxn txnp, int *url_len_ptr)
07208 {
07209   return TSHttpTxnRedirectUrlGet(txnp, url_len_ptr);
07210 }
07211 
07212 int
07213 TSHttpTxnRedirectRetries(TSHttpTxn txnp)
07214 {
07215   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
07216 
07217   HttpSM *sm = (HttpSM*)txnp;
07218 
07219   return sm->redirection_tries;
07220 }
07221 
07222 char*
07223 TSFetchRespGet(TSHttpTxn txnp, int *length)
07224 {
07225   sdk_assert(sdk_sanity_check_null_ptr((void*)length) == TS_SUCCESS);
07226   FetchSM *fetch_sm = (FetchSM*)txnp;
07227   return fetch_sm->resp_get(length);
07228 }
07229 
07230 TSReturnCode
07231 TSFetchPageRespGet(TSHttpTxn txnp, TSMBuffer *bufp, TSMLoc *obj)
07232 {
07233   sdk_assert(sdk_sanity_check_null_ptr((void*)bufp) == TS_SUCCESS);
07234   sdk_assert(sdk_sanity_check_null_ptr((void*)obj) == TS_SUCCESS);
07235 
07236   HTTPHdr *hptr = (HTTPHdr*) txnp;
07237 
07238   if (hptr->valid()) {
07239     *(reinterpret_cast<HTTPHdr**>(bufp)) = hptr;
07240     *obj = reinterpret_cast<TSMLoc>(hptr->m_http);
07241     return sdk_sanity_check_mbuffer(*bufp);
07242   }
07243 
07244   return TS_ERROR;
07245 }
07246 
07247 // Fetchpages SM
07248 extern ClassAllocator<FetchSM> FetchSMAllocator;
07249 
07250 void
07251 TSFetchPages(TSFetchUrlParams_t *params)
07252 {
07253   TSFetchUrlParams_t *myparams = params;
07254 
07255   while (myparams != NULL) {
07256     FetchSM *fetch_sm =  FetchSMAllocator.alloc();
07257     sockaddr* addr = ats_ip_sa_cast(&myparams->ip);
07258 
07259     fetch_sm->init((Continuation*)myparams->contp, myparams->options,myparams->events, myparams->request, myparams->request_len, addr);
07260     fetch_sm->httpConnect();
07261     myparams= myparams->next;
07262   }
07263 }
07264 
07265 void
07266 TSFetchUrl(const char* headers, int request_len, sockaddr const* ip , TSCont contp, TSFetchWakeUpOptions callback_options,TSFetchEvent events)
07267 {
07268   if (callback_options != NO_CALLBACK) {
07269     sdk_assert(sdk_sanity_check_continuation(contp) == TS_SUCCESS);
07270   }
07271 
07272   FetchSM *fetch_sm =  FetchSMAllocator.alloc();
07273 
07274   fetch_sm->init((Continuation*)contp, callback_options, events, headers, request_len, ip);
07275   fetch_sm->httpConnect();
07276 }
07277 
07278 TSFetchSM
07279 TSFetchCreate(TSCont contp, const char *method,
07280               const char *url, const char *version,
07281               struct sockaddr const* client_addr, int flags)
07282 {
07283   sdk_assert(sdk_sanity_check_continuation(contp) == TS_SUCCESS);
07284   sdk_assert(ats_is_ip(client_addr));
07285 
07286   FetchSM *fetch_sm = FetchSMAllocator.alloc();
07287 
07288   fetch_sm->ext_init((Continuation*)contp, method, url, version,
07289                      client_addr, flags);
07290 
07291   return (TSFetchSM)fetch_sm;
07292 }
07293 
07294 void
07295 TSFetchHeaderAdd(TSFetchSM fetch_sm,
07296                  const char *name, int name_len,
07297                  const char *value, int value_len)
07298 {
07299   sdk_assert(sdk_sanity_check_fetch_sm(fetch_sm) == TS_SUCCESS);
07300 
07301   ((FetchSM*)fetch_sm)->ext_add_header(name, name_len, value, value_len);
07302 }
07303 
07304 void
07305 TSFetchWriteData(TSFetchSM fetch_sm, const void *data, size_t len)
07306 {
07307   sdk_assert(sdk_sanity_check_fetch_sm(fetch_sm) == TS_SUCCESS);
07308 
07309   ((FetchSM*)fetch_sm)->ext_write_data(data, len);
07310 }
07311 
07312 ssize_t
07313 TSFetchReadData(TSFetchSM fetch_sm, void *buf, size_t len)
07314 {
07315   sdk_assert(sdk_sanity_check_fetch_sm(fetch_sm) == TS_SUCCESS);
07316 
07317   return ((FetchSM*)fetch_sm)->ext_read_data((char *)buf, len);
07318 }
07319 
07320 void
07321 TSFetchLaunch(TSFetchSM fetch_sm)
07322 {
07323   sdk_assert(sdk_sanity_check_fetch_sm(fetch_sm) == TS_SUCCESS);
07324 
07325   ((FetchSM*)fetch_sm)->ext_lanuch();
07326 }
07327 
07328 void
07329 TSFetchDestroy(TSFetchSM fetch_sm)
07330 {
07331   sdk_assert(sdk_sanity_check_fetch_sm(fetch_sm) == TS_SUCCESS);
07332 
07333   ((FetchSM*)fetch_sm)->ext_destroy();
07334 }
07335 
07336 void
07337 TSFetchUserDataSet(TSFetchSM fetch_sm, void *data)
07338 {
07339   sdk_assert(sdk_sanity_check_fetch_sm(fetch_sm) == TS_SUCCESS);
07340 
07341   ((FetchSM*)fetch_sm)->ext_set_user_data(data);
07342 }
07343 
07344 # if 0
07345 void
07346 TSFetchClientProtoStackSet(TSFetchSM fetch_sm, TSClientProtoStack proto_stack)
07347 {
07348   sdk_assert(sdk_sanity_check_fetch_sm(fetch_sm) == TS_SUCCESS);
07349 
07350   ((FetchSM*)fetch_sm)->ext_set_proto_stack(proto_stack);
07351 }
07352 
07353 TSClientProtoStack
07354 TSFetchClientProtoStackGet(TSFetchSM fetch_sm)
07355 {
07356   sdk_assert(sdk_sanity_check_fetch_sm(fetch_sm) == TS_SUCCESS);
07357 
07358   return ((FetchSM*)fetch_sm)->ext_get_proto_stack();
07359 }
07360 # endif
07361 
07362 void*
07363 TSFetchUserDataGet(TSFetchSM fetch_sm)
07364 {
07365   sdk_assert(sdk_sanity_check_fetch_sm(fetch_sm) == TS_SUCCESS);
07366 
07367   return ((FetchSM*)fetch_sm)->ext_get_user_data();
07368 }
07369 
07370 TSMBuffer
07371 TSFetchRespHdrMBufGet(TSFetchSM fetch_sm)
07372 {
07373   sdk_assert(sdk_sanity_check_fetch_sm(fetch_sm) == TS_SUCCESS);
07374 
07375   return ((FetchSM*)fetch_sm)->resp_hdr_bufp();
07376 }
07377 
07378 TSMLoc
07379 TSFetchRespHdrMLocGet(TSFetchSM fetch_sm)
07380 {
07381   sdk_assert(sdk_sanity_check_fetch_sm(fetch_sm) == TS_SUCCESS);
07382 
07383   return ((FetchSM*)fetch_sm)->resp_hdr_mloc();
07384 }
07385 
07386 TSReturnCode
07387 TSHttpIsInternalSession(TSHttpSsn ssnp)
07388 {
07389   HttpClientSession *cs = (HttpClientSession *) ssnp;
07390   if (!cs) {
07391     return TS_ERROR;
07392   }
07393 
07394   NetVConnection *vc = cs->get_netvc();
07395   if (!vc) {
07396     return TS_ERROR;
07397   }
07398 
07399   return vc->get_is_internal_request() ? TS_SUCCESS : TS_ERROR;
07400 }
07401 
07402 TSReturnCode
07403 TSHttpIsInternalRequest(TSHttpTxn txnp)
07404 {
07405   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
07406   return TSHttpIsInternalSession(TSHttpTxnSsnGet(txnp));
07407 }
07408 
07409 
07410 TSReturnCode
07411 TSAIORead(int fd, off_t offset, char* buf, size_t buffSize, TSCont contp)
07412 {
07413   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
07414 
07415   Continuation* pCont = (Continuation*)contp;
07416   AIOCallback* pAIO = new_AIOCallback();
07417 
07418   if (pAIO == NULL)
07419     return TS_ERROR;
07420 
07421   pAIO->aiocb.aio_fildes = fd;
07422   pAIO->aiocb.aio_offset = offset;
07423   pAIO->aiocb.aio_nbytes = buffSize;
07424 
07425 
07426   pAIO->aiocb.aio_buf = buf;
07427   pAIO->action = pCont;
07428   pAIO->thread = ((ProxyMutex*) pCont->mutex)->thread_holding;
07429 
07430   if (ink_aio_read(pAIO, 1) == 1)
07431     return TS_SUCCESS;
07432 
07433   return TS_ERROR;
07434 }
07435 
07436 char*
07437 TSAIOBufGet(TSAIOCallback data)
07438 {
07439   AIOCallback* pAIO = (AIOCallback*)data;
07440   return (char*)pAIO->aiocb.aio_buf;
07441 }
07442 
07443 int
07444 TSAIONBytesGet(TSAIOCallback data)
07445 {
07446   AIOCallback* pAIO = (AIOCallback*)data;
07447   return (int)pAIO->aio_result;
07448 }
07449 
07450 TSReturnCode
07451 TSAIOWrite(int fd, off_t offset, char* buf, const size_t bufSize, TSCont contp)
07452 {
07453   sdk_assert(sdk_sanity_check_iocore_structure (contp) == TS_SUCCESS);
07454 
07455   Continuation* pCont = (Continuation*) contp;
07456   AIOCallback* pAIO = new_AIOCallback();
07457 
07458   // TODO: Might be able to remove this when allocations can never fail.
07459   sdk_assert(sdk_sanity_check_null_ptr((void*)pAIO) == TS_SUCCESS);
07460 
07461   pAIO->aiocb.aio_fildes = fd;
07462   pAIO->aiocb.aio_offset = offset;
07463   pAIO->aiocb.aio_buf = buf;
07464   pAIO->aiocb.aio_nbytes = bufSize;
07465   pAIO->action = pCont;
07466   pAIO->thread = ((ProxyMutex*) pCont->mutex)->thread_holding;
07467 
07468   if (ink_aio_write(pAIO, 1) == 1)
07469     return TS_SUCCESS;
07470 
07471   return TS_ERROR;
07472 }
07473 
07474 TSReturnCode
07475 TSAIOThreadNumSet(int thread_num)
07476 {
07477 #if AIO_MODE == AIO_MODE_NATIVE
07478   (void)thread_num;
07479   return TS_SUCCESS;
07480 #else
07481   if (ink_aio_thread_num_set(thread_num))
07482     return TS_SUCCESS;
07483 
07484   return TS_ERROR;
07485 #endif
07486 }
07487 
07488 void
07489 TSRecordDump(int rec_type, TSRecordDumpCb callback, void *edata)
07490 {
07491   RecDumpRecords((RecT)rec_type, (RecDumpEntryCb)callback, edata);
07492 }
07493 
07494 /* ability to skip the remap phase of the State Machine
07495    this only really makes sense in TS_HTTP_READ_REQUEST_HDR_HOOK
07496 */
07497 void
07498 TSSkipRemappingSet(TSHttpTxn txnp, int flag)
07499 {
07500   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
07501 
07502   HttpSM *sm = (HttpSM*) txnp;
07503   sm->t_state.api_skip_all_remapping = (flag != 0);
07504 }
07505 
07506 // Little helper function to find the struct member
07507 static void*
07508 _conf_to_memberp(TSOverridableConfigKey conf,
07509     OverridableHttpConfigParams *overridableHttpConfig,
07510     OverridableDataType *typep)
07511 {
07512   // The default is "Byte", make sure to override that for those configs which are "Int".
07513   OverridableDataType typ = OVERRIDABLE_TYPE_BYTE;
07514   void* ret = NULL;
07515 
07516   switch (conf) {
07517   case TS_CONFIG_URL_REMAP_PRISTINE_HOST_HDR:
07518     ret = &overridableHttpConfig->maintain_pristine_host_hdr;
07519     break;
07520   case TS_CONFIG_HTTP_CHUNKING_ENABLED:
07521     ret = &overridableHttpConfig->chunking_enabled;
07522     break;
07523   case TS_CONFIG_HTTP_NEGATIVE_CACHING_ENABLED:
07524     ret = &overridableHttpConfig->negative_caching_enabled;
07525     break;
07526   case TS_CONFIG_HTTP_NEGATIVE_CACHING_LIFETIME:
07527     typ = OVERRIDABLE_TYPE_INT;
07528     ret = &overridableHttpConfig->negative_caching_lifetime;
07529     break;
07530   case TS_CONFIG_HTTP_CACHE_WHEN_TO_REVALIDATE:
07531     ret = &overridableHttpConfig->cache_when_to_revalidate;
07532     break;
07533   case TS_CONFIG_HTTP_KEEP_ALIVE_ENABLED_IN:
07534     ret = &overridableHttpConfig->keep_alive_enabled_in;
07535     break;
07536   case TS_CONFIG_HTTP_KEEP_ALIVE_ENABLED_OUT:
07537     ret = &overridableHttpConfig->keep_alive_enabled_out;
07538     break;
07539   case TS_CONFIG_HTTP_KEEP_ALIVE_POST_OUT:
07540     ret = &overridableHttpConfig->keep_alive_post_out;
07541     break;
07542   case TS_CONFIG_HTTP_SHARE_SERVER_SESSIONS:
07543     ink_assert("Deprecated config key value - TS_CONFIG_HTTP_SHARE_SERVER_SESSIONS");
07544 //    ret = &overridableHttpConfig->share_server_sessions;
07545     break;
07546   case TS_CONFIG_HTTP_SERVER_SESSION_SHARING_POOL:
07547     ret = &overridableHttpConfig->server_session_sharing_pool;
07548     break;
07549   case TS_CONFIG_HTTP_SERVER_SESSION_SHARING_MATCH:
07550     ret = &overridableHttpConfig->server_session_sharing_match;
07551     break;
07552   case TS_CONFIG_NET_SOCK_RECV_BUFFER_SIZE_OUT:
07553     typ = OVERRIDABLE_TYPE_INT;
07554     ret = &overridableHttpConfig->sock_recv_buffer_size_out;
07555     break;
07556   case TS_CONFIG_NET_SOCK_SEND_BUFFER_SIZE_OUT:
07557     typ = OVERRIDABLE_TYPE_INT;
07558     ret = &overridableHttpConfig->sock_send_buffer_size_out;
07559     break;
07560   case TS_CONFIG_NET_SOCK_OPTION_FLAG_OUT:
07561     typ = OVERRIDABLE_TYPE_INT;
07562     ret = &overridableHttpConfig->sock_option_flag_out;
07563     break;
07564   case TS_CONFIG_HTTP_FORWARD_PROXY_AUTH_TO_PARENT:
07565     ret = &overridableHttpConfig->fwd_proxy_auth_to_parent;
07566     break;
07567   case TS_CONFIG_HTTP_ANONYMIZE_REMOVE_FROM:
07568     ret = &overridableHttpConfig->anonymize_remove_from;
07569     break;
07570   case TS_CONFIG_HTTP_ANONYMIZE_REMOVE_REFERER:
07571     ret = &overridableHttpConfig->anonymize_remove_referer;
07572     break;
07573   case TS_CONFIG_HTTP_ANONYMIZE_REMOVE_USER_AGENT:
07574     ret = &overridableHttpConfig->anonymize_remove_user_agent;
07575     break;
07576   case TS_CONFIG_HTTP_ANONYMIZE_REMOVE_COOKIE:
07577     ret = &overridableHttpConfig->anonymize_remove_cookie;
07578     break;
07579   case TS_CONFIG_HTTP_ANONYMIZE_REMOVE_CLIENT_IP:
07580     ret = &overridableHttpConfig->anonymize_remove_client_ip;
07581     break;
07582   case TS_CONFIG_HTTP_ANONYMIZE_INSERT_CLIENT_IP:
07583     ret = &overridableHttpConfig->anonymize_insert_client_ip;
07584     break;
07585   case TS_CONFIG_HTTP_RESPONSE_SERVER_ENABLED:
07586     ret = &overridableHttpConfig->proxy_response_server_enabled;
07587     break;
07588   case TS_CONFIG_HTTP_INSERT_SQUID_X_FORWARDED_FOR:
07589     ret = &overridableHttpConfig->insert_squid_x_forwarded_for;
07590     break;
07591   case TS_CONFIG_HTTP_SERVER_TCP_INIT_CWND:
07592     typ = OVERRIDABLE_TYPE_INT;
07593     ret = &overridableHttpConfig->server_tcp_init_cwnd;
07594     break;
07595   case TS_CONFIG_HTTP_SEND_HTTP11_REQUESTS:
07596     ret = &overridableHttpConfig->send_http11_requests;
07597     break;
07598   case TS_CONFIG_HTTP_CACHE_HTTP:
07599     ret = &overridableHttpConfig->cache_http;
07600     break;
07601   case TS_CONFIG_HTTP_CACHE_CLUSTER_CACHE_LOCAL:
07602     ret = &overridableHttpConfig->cache_cluster_cache_local;
07603     break;
07604   case TS_CONFIG_HTTP_CACHE_IGNORE_CLIENT_NO_CACHE:
07605     ret = &overridableHttpConfig->cache_ignore_client_no_cache;
07606     break;
07607   case TS_CONFIG_HTTP_CACHE_IGNORE_CLIENT_CC_MAX_AGE:
07608     ret = &overridableHttpConfig->cache_ignore_client_cc_max_age;
07609     break;
07610   case TS_CONFIG_HTTP_CACHE_IMS_ON_CLIENT_NO_CACHE:
07611     ret = &overridableHttpConfig->cache_ims_on_client_no_cache;
07612     break;
07613   case TS_CONFIG_HTTP_CACHE_IGNORE_SERVER_NO_CACHE:
07614     ret = &overridableHttpConfig->cache_ignore_server_no_cache;
07615     break;
07616   case TS_CONFIG_HTTP_CACHE_CACHE_RESPONSES_TO_COOKIES:
07617     ret = &overridableHttpConfig->cache_responses_to_cookies;
07618     break;
07619   case TS_CONFIG_HTTP_CACHE_IGNORE_AUTHENTICATION:
07620     ret = &overridableHttpConfig->cache_ignore_auth;
07621     break;
07622   case TS_CONFIG_HTTP_CACHE_CACHE_URLS_THAT_LOOK_DYNAMIC:
07623     ret = &overridableHttpConfig->cache_urls_that_look_dynamic;
07624     break;
07625   case TS_CONFIG_HTTP_CACHE_REQUIRED_HEADERS:
07626     ret = &overridableHttpConfig->cache_required_headers;
07627     break;
07628   case TS_CONFIG_HTTP_INSERT_REQUEST_VIA_STR:
07629     ret = &overridableHttpConfig->insert_request_via_string;
07630     break;
07631   case TS_CONFIG_HTTP_INSERT_RESPONSE_VIA_STR:
07632     ret = &overridableHttpConfig->insert_response_via_string;
07633     break;
07634   case TS_CONFIG_HTTP_CACHE_HEURISTIC_MIN_LIFETIME:
07635     typ = OVERRIDABLE_TYPE_INT;
07636     ret = &overridableHttpConfig->cache_heuristic_min_lifetime;
07637     break;
07638   case TS_CONFIG_HTTP_CACHE_HEURISTIC_MAX_LIFETIME:
07639     typ = OVERRIDABLE_TYPE_INT;
07640     ret = &overridableHttpConfig->cache_heuristic_max_lifetime;
07641     break;
07642   case TS_CONFIG_HTTP_CACHE_GUARANTEED_MIN_LIFETIME:
07643     typ = OVERRIDABLE_TYPE_INT;
07644     ret = &overridableHttpConfig->cache_guaranteed_min_lifetime;
07645     break;
07646   case TS_CONFIG_HTTP_CACHE_GUARANTEED_MAX_LIFETIME:
07647     typ = OVERRIDABLE_TYPE_INT;
07648     ret = &overridableHttpConfig->cache_guaranteed_max_lifetime;
07649     break;
07650   case TS_CONFIG_HTTP_CACHE_MAX_STALE_AGE:
07651     typ = OVERRIDABLE_TYPE_INT;
07652     ret = &overridableHttpConfig->cache_max_stale_age;
07653     break;
07654   case TS_CONFIG_HTTP_KEEP_ALIVE_NO_ACTIVITY_TIMEOUT_IN:
07655     typ = OVERRIDABLE_TYPE_INT;
07656     ret = &overridableHttpConfig->keep_alive_no_activity_timeout_in;
07657     break;
07658   case TS_CONFIG_HTTP_KEEP_ALIVE_NO_ACTIVITY_TIMEOUT_OUT:
07659     typ = OVERRIDABLE_TYPE_INT;
07660     ret = &overridableHttpConfig->keep_alive_no_activity_timeout_out;
07661     break;
07662   case TS_CONFIG_HTTP_TRANSACTION_NO_ACTIVITY_TIMEOUT_IN:
07663     typ = OVERRIDABLE_TYPE_INT;
07664     ret = &overridableHttpConfig->transaction_no_activity_timeout_in;
07665     break;
07666   case TS_CONFIG_HTTP_TRANSACTION_NO_ACTIVITY_TIMEOUT_OUT:
07667     typ = OVERRIDABLE_TYPE_INT;
07668     ret = &overridableHttpConfig->transaction_no_activity_timeout_out;
07669     break;
07670   case TS_CONFIG_HTTP_TRANSACTION_ACTIVE_TIMEOUT_OUT:
07671     typ = OVERRIDABLE_TYPE_INT;
07672     ret = &overridableHttpConfig->transaction_active_timeout_out;
07673     break;
07674   case TS_CONFIG_HTTP_ORIGIN_MAX_CONNECTIONS:
07675     typ = OVERRIDABLE_TYPE_INT;
07676     ret = &overridableHttpConfig->origin_max_connections;
07677     break;
07678   case TS_CONFIG_HTTP_CONNECT_ATTEMPTS_MAX_RETRIES:
07679     typ = OVERRIDABLE_TYPE_INT;
07680     ret = &overridableHttpConfig->connect_attempts_max_retries;
07681     break;
07682   case TS_CONFIG_HTTP_CONNECT_ATTEMPTS_MAX_RETRIES_DEAD_SERVER:
07683     typ = OVERRIDABLE_TYPE_INT;
07684     ret = &overridableHttpConfig->connect_attempts_max_retries_dead_server;
07685     break;
07686   case TS_CONFIG_HTTP_CONNECT_ATTEMPTS_RR_RETRIES:
07687     typ = OVERRIDABLE_TYPE_INT;
07688     ret = &overridableHttpConfig->connect_attempts_rr_retries;
07689     break;
07690   case TS_CONFIG_HTTP_CONNECT_ATTEMPTS_TIMEOUT:
07691     typ = OVERRIDABLE_TYPE_INT;
07692     ret = &overridableHttpConfig->connect_attempts_timeout;
07693     break;
07694   case TS_CONFIG_HTTP_POST_CONNECT_ATTEMPTS_TIMEOUT:
07695     typ = OVERRIDABLE_TYPE_INT;
07696     ret = &overridableHttpConfig->post_connect_attempts_timeout;
07697     break;
07698   case TS_CONFIG_HTTP_DOWN_SERVER_CACHE_TIME:
07699     typ = OVERRIDABLE_TYPE_INT;
07700     ret = &overridableHttpConfig->down_server_timeout;
07701     break;
07702   case TS_CONFIG_HTTP_DOWN_SERVER_ABORT_THRESHOLD:
07703     typ = OVERRIDABLE_TYPE_INT;
07704     ret = &overridableHttpConfig->client_abort_threshold;
07705     break;
07706   case TS_CONFIG_HTTP_CACHE_FUZZ_TIME:
07707     typ = OVERRIDABLE_TYPE_INT;
07708     ret = &overridableHttpConfig->freshness_fuzz_time;
07709     break;
07710   case TS_CONFIG_HTTP_CACHE_FUZZ_MIN_TIME:
07711     typ = OVERRIDABLE_TYPE_INT;
07712     ret = &overridableHttpConfig->freshness_fuzz_min_time;
07713     break;
07714   case TS_CONFIG_HTTP_DOC_IN_CACHE_SKIP_DNS:
07715     ret = &overridableHttpConfig->doc_in_cache_skip_dns;
07716     break;
07717   case TS_CONFIG_HTTP_BACKGROUND_FILL_ACTIVE_TIMEOUT:
07718     typ = OVERRIDABLE_TYPE_INT;
07719     ret = &overridableHttpConfig->background_fill_active_timeout;
07720     break;
07721   case TS_CONFIG_HTTP_RESPONSE_SERVER_STR:
07722     typ = OVERRIDABLE_TYPE_STRING;
07723     ret = &overridableHttpConfig->proxy_response_server_string;
07724     break;
07725   case TS_CONFIG_HTTP_CACHE_HEURISTIC_LM_FACTOR:
07726     typ = OVERRIDABLE_TYPE_FLOAT;
07727     ret = &overridableHttpConfig->cache_heuristic_lm_factor;
07728     break;
07729   case TS_CONFIG_HTTP_CACHE_FUZZ_PROBABILITY:
07730     typ = OVERRIDABLE_TYPE_FLOAT;
07731     ret = &overridableHttpConfig->freshness_fuzz_prob;
07732     break;
07733   case TS_CONFIG_HTTP_BACKGROUND_FILL_COMPLETED_THRESHOLD:
07734     typ = OVERRIDABLE_TYPE_FLOAT;
07735     ret = &overridableHttpConfig->background_fill_threshold;
07736     break;
07737   case TS_CONFIG_NET_SOCK_PACKET_MARK_OUT:
07738     typ = OVERRIDABLE_TYPE_INT;
07739     ret = &overridableHttpConfig->sock_packet_mark_out;
07740     break;
07741   case TS_CONFIG_NET_SOCK_PACKET_TOS_OUT:
07742     typ = OVERRIDABLE_TYPE_INT;
07743     ret = &overridableHttpConfig->sock_packet_tos_out;
07744     break;
07745   case TS_CONFIG_HTTP_INSERT_AGE_IN_RESPONSE:
07746     ret = &overridableHttpConfig->insert_age_in_response;
07747     break;
07748   case TS_CONFIG_HTTP_CHUNKING_SIZE:
07749     typ = OVERRIDABLE_TYPE_INT;
07750     ret = &overridableHttpConfig->http_chunking_size;
07751     break;
07752   case TS_CONFIG_HTTP_FLOW_CONTROL_ENABLED:
07753     ret = &overridableHttpConfig->flow_control_enabled;
07754     break;
07755   case TS_CONFIG_HTTP_FLOW_CONTROL_LOW_WATER_MARK:
07756     typ = OVERRIDABLE_TYPE_INT;
07757     ret = &overridableHttpConfig->flow_low_water_mark;
07758     break;
07759   case TS_CONFIG_HTTP_FLOW_CONTROL_HIGH_WATER_MARK:
07760     typ = OVERRIDABLE_TYPE_INT;
07761     ret = &overridableHttpConfig->flow_high_water_mark;
07762     break;
07763   case TS_CONFIG_HTTP_CACHE_RANGE_LOOKUP:
07764     ret = &overridableHttpConfig->cache_range_lookup;
07765     break;
07766   case TS_CONFIG_HTTP_NORMALIZE_AE_GZIP:
07767     ret = &overridableHttpConfig->normalize_ae_gzip;
07768     break;
07769   case TS_CONFIG_HTTP_DEFAULT_BUFFER_SIZE:
07770     typ = OVERRIDABLE_TYPE_INT;
07771     ret = &overridableHttpConfig->default_buffer_size_index;
07772     break;
07773   case TS_CONFIG_HTTP_DEFAULT_BUFFER_WATER_MARK:
07774     typ = OVERRIDABLE_TYPE_INT;
07775     ret = &overridableHttpConfig->default_buffer_water_mark;
07776     break;
07777   case TS_CONFIG_HTTP_REQUEST_HEADER_MAX_SIZE:
07778     typ = OVERRIDABLE_TYPE_INT;
07779     ret = &overridableHttpConfig->request_hdr_max_size;
07780     break;
07781   case TS_CONFIG_HTTP_RESPONSE_HEADER_MAX_SIZE:
07782     typ = OVERRIDABLE_TYPE_INT;
07783     ret = &overridableHttpConfig->response_hdr_max_size;
07784     break;
07785   case TS_CONFIG_HTTP_NEGATIVE_REVALIDATING_ENABLED:
07786     ret = &overridableHttpConfig->negative_revalidating_enabled;
07787     break;
07788   case TS_CONFIG_HTTP_NEGATIVE_REVALIDATING_LIFETIME:
07789     typ = OVERRIDABLE_TYPE_INT;
07790     ret = &overridableHttpConfig->negative_revalidating_lifetime;
07791     break;
07792   case TS_CONFIG_HTTP_ACCEPT_ENCODING_FILTER_ENABLED:
07793     ret = &overridableHttpConfig->accept_encoding_filter_enabled;
07794     break;
07795   case TS_CONFIG_SSL_HSTS_MAX_AGE:
07796     typ = OVERRIDABLE_TYPE_INT;
07797     ret = &overridableHttpConfig->proxy_response_hsts_max_age;
07798     break;
07799   case TS_CONFIG_SSL_HSTS_INCLUDE_SUBDOMAINS:
07800     ret = &overridableHttpConfig->proxy_response_hsts_include_subdomains;
07801     break;
07802   case TS_CONFIG_HTTP_CACHE_OPEN_READ_RETRY_TIME:
07803     typ = OVERRIDABLE_TYPE_INT;
07804     ret = &overridableHttpConfig->cache_open_read_retry_time;
07805     break;
07806   case TS_CONFIG_HTTP_CACHE_MAX_OPEN_READ_RETRIES:
07807     typ = OVERRIDABLE_TYPE_INT;
07808     ret = &overridableHttpConfig->max_cache_open_read_retries;
07809     break;
07810   case TS_CONFIG_HTTP_CACHE_RANGE_WRITE:
07811     ret = &overridableHttpConfig->cache_range_write;
07812     break;
07813   case TS_CONFIG_HTTP_POST_CHECK_CONTENT_LENGTH_ENABLED:
07814     ret = &overridableHttpConfig->post_check_content_length_enabled;
07815     break;
07816   case TS_CONFIG_HTTP_GLOBAL_USER_AGENT_HEADER:
07817     typ = OVERRIDABLE_TYPE_STRING;
07818     ret = &overridableHttpConfig->global_user_agent_header;
07819     break;
07820 
07821     // This helps avoiding compiler warnings, yet detect unhandled enum members.
07822   case TS_CONFIG_NULL:
07823   case TS_CONFIG_LAST_ENTRY:
07824     typ = OVERRIDABLE_TYPE_NULL;
07825     ret = NULL;
07826     break;
07827   }
07828 
07829   *typep = typ;
07830 
07831   return ret;
07832 }
07833 
07834 /* APIs to manipulate the overridable configuration options.
07835 */
07836 TSReturnCode
07837 TSHttpTxnConfigIntSet(TSHttpTxn txnp, TSOverridableConfigKey conf, TSMgmtInt value)
07838 {
07839   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
07840 
07841   HttpSM *s = reinterpret_cast<HttpSM*>(txnp);
07842   OverridableDataType type;
07843 
07844   s->t_state.setup_per_txn_configs();
07845 
07846   // 4.1.X backwards compatibility - remove for 5.0
07847   if (TS_CONFIG_HTTP_SHARE_SERVER_SESSIONS == conf) {
07848     switch (value) {
07849     case 0: s->t_state.txn_conf->server_session_sharing_match = TS_SERVER_SESSION_SHARING_MATCH_NONE; break;
07850     case 1:
07851       s->t_state.txn_conf->server_session_sharing_match = TS_SERVER_SESSION_SHARING_MATCH_BOTH;
07852       s->t_state.txn_conf->server_session_sharing_pool = TS_SERVER_SESSION_SHARING_POOL_GLOBAL;
07853       break;
07854     case 2:
07855       s->t_state.txn_conf->server_session_sharing_match = TS_SERVER_SESSION_SHARING_MATCH_BOTH;
07856       s->t_state.txn_conf->server_session_sharing_pool = TS_SERVER_SESSION_SHARING_POOL_THREAD;
07857       break;
07858     default:
07859       return TS_ERROR;
07860       break; // make the compiler happy
07861     }
07862     return TS_SUCCESS;
07863   }
07864   // end 4.1.X BC
07865 
07866   void *dest = _conf_to_memberp(conf, s->t_state.txn_conf, &type);
07867 
07868   if (!dest)
07869     return TS_ERROR;
07870 
07871   switch (type) {
07872   case OVERRIDABLE_TYPE_INT:
07873     *(static_cast<TSMgmtInt*>(dest)) = value;
07874     break;
07875   case OVERRIDABLE_TYPE_BYTE:
07876     *(static_cast<TSMgmtByte*>(dest)) = static_cast<TSMgmtByte>(value);
07877     break;
07878   default:
07879     return TS_ERROR;
07880   }
07881 
07882   return TS_SUCCESS;
07883 }
07884 
07885 TSReturnCode
07886 TSHttpTxnConfigIntGet(TSHttpTxn txnp, TSOverridableConfigKey conf, TSMgmtInt *value)
07887 {
07888   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
07889   sdk_assert(sdk_sanity_check_null_ptr((void*)value) == TS_SUCCESS);
07890 
07891   HttpSM *s = reinterpret_cast<HttpSM*>(txnp);
07892   OverridableDataType type;
07893 
07894   // 4.1.X backwards compatibility - remove for 5.0
07895   if (TS_CONFIG_HTTP_SHARE_SERVER_SESSIONS == conf) {
07896     if (s->t_state.txn_conf->server_session_sharing_match == TS_SERVER_SESSION_SHARING_MATCH_NONE)
07897       *value = 0;
07898     else if (s->t_state.txn_conf->server_session_sharing_match == TS_SERVER_SESSION_SHARING_MATCH_BOTH &&
07899              s->t_state.txn_conf->server_session_sharing_pool == TS_SERVER_SESSION_SHARING_POOL_GLOBAL)
07900       *value = 1;
07901     else if (s->t_state.txn_conf->server_session_sharing_match == TS_SERVER_SESSION_SHARING_MATCH_BOTH &&
07902              s->t_state.txn_conf->server_session_sharing_pool == TS_SERVER_SESSION_SHARING_POOL_THREAD)
07903       *value = 2;
07904     else
07905       return TS_ERROR;
07906     return TS_SUCCESS;
07907   }
07908   // end 4.1.X BC
07909 
07910   void* src = _conf_to_memberp(conf, s->t_state.txn_conf, &type);
07911 
07912   if (!src)
07913     return TS_ERROR;
07914 
07915   switch (type) {
07916   case OVERRIDABLE_TYPE_INT:
07917     *value = *(static_cast<TSMgmtInt*>(src));
07918     break;
07919   case OVERRIDABLE_TYPE_BYTE:
07920     *value = *(static_cast<TSMgmtByte*>(src));
07921     break;
07922   default:
07923     return TS_ERROR;
07924   }
07925 
07926   return TS_SUCCESS;
07927 }
07928 
07929 TSReturnCode
07930 TSHttpTxnConfigFloatSet(TSHttpTxn txnp, TSOverridableConfigKey conf, TSMgmtFloat value)
07931 {
07932   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
07933 
07934   HttpSM *s = reinterpret_cast<HttpSM*>(txnp);
07935   OverridableDataType type;
07936 
07937   s->t_state.setup_per_txn_configs();
07938 
07939   TSMgmtFloat* dest = static_cast<TSMgmtFloat*>(_conf_to_memberp(conf, s->t_state.txn_conf, &type));
07940 
07941   if (type != OVERRIDABLE_TYPE_FLOAT)
07942     return TS_ERROR;
07943 
07944   if (dest) {
07945     *dest = value;
07946     return TS_SUCCESS;
07947   }
07948 
07949   return TS_SUCCESS;
07950 }
07951 
07952 TSReturnCode
07953 TSHttpTxnConfigFloatGet(TSHttpTxn txnp, TSOverridableConfigKey conf, TSMgmtFloat *value)
07954 {
07955   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
07956   sdk_assert(sdk_sanity_check_null_ptr((void*)value) == TS_SUCCESS);
07957 
07958   OverridableDataType type;
07959   TSMgmtFloat* dest = static_cast<TSMgmtFloat*>(_conf_to_memberp(conf, ((HttpSM*)txnp)->t_state.txn_conf, &type));
07960 
07961   if (type != OVERRIDABLE_TYPE_FLOAT)
07962     return TS_ERROR;
07963 
07964   if (dest) {
07965     *value = *dest;
07966     return TS_SUCCESS;
07967   }
07968 
07969   return TS_SUCCESS;
07970 }
07971 
07972 TSReturnCode
07973 TSHttpTxnConfigStringSet(TSHttpTxn txnp, TSOverridableConfigKey conf, const char* value, int length)
07974 {
07975   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
07976 
07977   if (length == -1)
07978     length = strlen(value);
07979 
07980   HttpSM *s = (HttpSM*) txnp;
07981 
07982   s->t_state.setup_per_txn_configs();
07983 
07984   switch (conf) {
07985   case TS_CONFIG_HTTP_RESPONSE_SERVER_STR:
07986     if (value && length > 0) {
07987       s->t_state.txn_conf->proxy_response_server_string = const_cast<char*>(value); // The "core" likes non-const char*
07988       s->t_state.txn_conf->proxy_response_server_string_len = length;
07989     } else {
07990       s->t_state.txn_conf->proxy_response_server_string = NULL;
07991       s->t_state.txn_conf->proxy_response_server_string_len = 0;
07992     }
07993     break;
07994   case TS_CONFIG_HTTP_GLOBAL_USER_AGENT_HEADER:
07995     if (value && length > 0) {
07996       s->t_state.txn_conf->global_user_agent_header = const_cast<char*>(value); // The "core" likes non-const char*
07997       s->t_state.txn_conf->global_user_agent_header_size = length;
07998     } else {
07999       s->t_state.txn_conf->global_user_agent_header = NULL;
08000       s->t_state.txn_conf->global_user_agent_header_size = 0;
08001     }
08002     break;
08003   default:
08004     return TS_ERROR;
08005     break;
08006   }
08007 
08008   return TS_SUCCESS;
08009 }
08010 
08011 
08012 TSReturnCode
08013 TSHttpTxnConfigStringGet(TSHttpTxn txnp, TSOverridableConfigKey conf, const char **value, int *length)
08014 {
08015   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
08016   sdk_assert(sdk_sanity_check_null_ptr((void**)value) == TS_SUCCESS);
08017   sdk_assert(sdk_sanity_check_null_ptr((void*)length) == TS_SUCCESS);
08018 
08019   HttpSM *sm = (HttpSM*) txnp;
08020 
08021   switch (conf) {
08022   case TS_CONFIG_HTTP_RESPONSE_SERVER_STR:
08023     *value = sm->t_state.txn_conf->proxy_response_server_string;
08024     *length = sm->t_state.txn_conf->proxy_response_server_string_len;
08025     break;
08026   case TS_CONFIG_HTTP_GLOBAL_USER_AGENT_HEADER:
08027     *value = sm->t_state.txn_conf->global_user_agent_header;
08028     *length = sm->t_state.txn_conf->global_user_agent_header_size;
08029     break;
08030   default:
08031     return TS_ERROR;
08032     break;
08033   }
08034 
08035   return TS_SUCCESS;
08036 }
08037 
08038 
08039 // This is pretty suboptimal, and should only be used outside the critical path.
08040 TSReturnCode
08041 TSHttpTxnConfigFind(const char* name, int length, TSOverridableConfigKey *conf, TSRecordDataType *type)
08042 {
08043   sdk_assert(sdk_sanity_check_null_ptr((void*)name) == TS_SUCCESS);
08044   sdk_assert(sdk_sanity_check_null_ptr((void*)conf) == TS_SUCCESS);
08045 
08046   TSOverridableConfigKey cnf = TS_CONFIG_NULL;
08047   TSRecordDataType typ = TS_RECORDDATATYPE_INT;
08048 
08049   if (length == -1)
08050     length = strlen(name);
08051 
08052   // Lots of string comparisons here, but we avoid quite a few by checking lengths
08053   switch (length) {
08054   case 28:
08055     if (!strncmp(name, "proxy.config.http.cache.http", length))
08056       cnf = TS_CONFIG_HTTP_CACHE_HTTP;
08057     break;
08058 
08059   case 29:
08060     if (!strncmp(name, "proxy.config.ssl.hsts_max_age", length))
08061       cnf = TS_CONFIG_SSL_HSTS_MAX_AGE;
08062     break;
08063 
08064   case 31:
08065     if (!strncmp(name, "proxy.config.http.chunking.size", length))
08066       cnf = TS_CONFIG_HTTP_CHUNKING_SIZE;
08067     break;
08068 
08069   case 33:
08070     if (!strncmp(name, "proxy.config.http.cache.fuzz.time", length))
08071       cnf = TS_CONFIG_HTTP_CACHE_FUZZ_TIME;
08072     break;
08073 
08074   case 34:
08075     if (!strncmp(name, "proxy.config.http.chunking_enabled", length))
08076       cnf = TS_CONFIG_HTTP_CHUNKING_ENABLED;
08077     break;
08078 
08079   case 35:
08080     switch (name[length-1]) {
08081     case 'e':
08082       if (!strncmp(name, "proxy.config.http.cache.range.write", length))
08083         cnf = TS_CONFIG_HTTP_CACHE_RANGE_WRITE;
08084       break;
08085     case 'p':
08086       if (!strncmp(name, "proxy.config.http.normalize_ae_gzip", length))
08087         cnf = TS_CONFIG_HTTP_NORMALIZE_AE_GZIP;
08088       break;
08089     }
08090     break;
08091 
08092   case 36:
08093     switch (name[length-1]) {
08094     case 'p':
08095       if (!strncmp(name, "proxy.config.http.cache.range.lookup", length))
08096         cnf = TS_CONFIG_HTTP_CACHE_RANGE_LOOKUP;
08097       break;
08098     case 't':
08099       if (!strncmp(name, "proxy.config.net.sock_packet_tos_out", length))
08100         cnf = TS_CONFIG_NET_SOCK_PACKET_TOS_OUT;
08101       break;
08102     }
08103     break;
08104 
08105   case 37:
08106     switch (name[length-1]) {
08107     case 'e':
08108       if (!strncmp(name, "proxy.config.http.cache.max_stale_age", length))
08109         cnf = TS_CONFIG_HTTP_CACHE_MAX_STALE_AGE;
08110       else if (!strncmp(name, "proxy.config.http.cache.fuzz.min_time", length))
08111         cnf = TS_CONFIG_HTTP_CACHE_FUZZ_MIN_TIME;
08112       else if (!strncmp(name, "proxy.config.http.default_buffer_size", length))
08113         cnf = TS_CONFIG_HTTP_DEFAULT_BUFFER_SIZE;
08114       break;
08115     case 'r':
08116       if (!strncmp(name, "proxy.config.http.response_server_str", length)) {
08117         cnf = TS_CONFIG_HTTP_RESPONSE_SERVER_STR;
08118         typ = TS_RECORDDATATYPE_STRING;
08119       }
08120       break;
08121     case 't':
08122       if (!strncmp(name, "proxy.config.http.keep_alive_post_out", length))
08123         cnf = TS_CONFIG_HTTP_KEEP_ALIVE_POST_OUT;
08124       else if (!strncmp(name, "proxy.config.net.sock_option_flag_out", length))
08125         cnf = TS_CONFIG_NET_SOCK_OPTION_FLAG_OUT;
08126       else if (!strncmp(name, "proxy.config.net.sock_packet_mark_out", length))
08127         cnf = TS_CONFIG_NET_SOCK_PACKET_MARK_OUT;
08128       break;
08129     }
08130     break;
08131 
08132   case 38:
08133     switch (name[length-1]) {
08134     case 'd':
08135       if (!strncmp(name, "proxy.config.http.server_tcp_init_cwnd", length))
08136         cnf = TS_CONFIG_HTTP_SERVER_TCP_INIT_CWND;
08137       else if (!strncmp(name, "proxy.config.http.flow_control.enabled", length))
08138         cnf = TS_CONFIG_HTTP_FLOW_CONTROL_ENABLED;
08139       break;
08140       break;
08141     case 's':
08142       if (!strncmp(name, "proxy.config.http.send_http11_requests", length))
08143         cnf = TS_CONFIG_HTTP_SEND_HTTP11_REQUESTS;
08144       break;
08145     }
08146     break;
08147 
08148   case 39:
08149     switch (name[length-1]) {
08150     case 'm':
08151       if (!strncmp(name, "proxy.config.http.anonymize_remove_from", length))
08152         cnf = TS_CONFIG_HTTP_ANONYMIZE_REMOVE_FROM;
08153       break;
08154     case 'n':
08155       if (!strncmp(name, "proxy.config.http.keep_alive_enabled_in", length))
08156         cnf = TS_CONFIG_HTTP_KEEP_ALIVE_ENABLED_IN;
08157       break;
08158     case 's':
08159       if (!strncmp(name, "proxy.config.http.doc_in_cache_skip_dns", length))
08160         cnf = TS_CONFIG_HTTP_DOC_IN_CACHE_SKIP_DNS;
08161       else if (!strncmp(name, "proxy.config.http.share_server_sessions", length))
08162         cnf = TS_CONFIG_HTTP_SHARE_SERVER_SESSIONS;
08163       break;
08164     }
08165     break;
08166 
08167   case 40:
08168     switch (name[length-1]) {
08169     case 'e':
08170       if (!strncmp(name, "proxy.config.http.down_server.cache_time", length))
08171         cnf = TS_CONFIG_HTTP_DOWN_SERVER_CACHE_TIME;
08172       else if (!strncmp(name, "proxy.config.http.insert_age_in_response", length))
08173         cnf = TS_CONFIG_HTTP_INSERT_AGE_IN_RESPONSE;
08174       break;
08175     case 'r':
08176       if (!strncmp(name, "proxy.config.url_remap.pristine_host_hdr", length))
08177         cnf = TS_CONFIG_URL_REMAP_PRISTINE_HOST_HDR;
08178       else if (!strncmp(name, "proxy.config.http.insert_request_via_str", length))
08179         cnf = TS_CONFIG_HTTP_INSERT_REQUEST_VIA_STR;
08180       else if (!strncmp(name, "proxy.config.http.flow_control.low_water", length))
08181         cnf = TS_CONFIG_HTTP_FLOW_CONTROL_LOW_WATER_MARK;
08182       break;
08183     case 's':
08184       if (!strncmp(name, "proxy.config.http.origin_max_connections", length))
08185         cnf = TS_CONFIG_HTTP_ORIGIN_MAX_CONNECTIONS;
08186       else if (!strncmp(name, "proxy.config.http.cache.required_headers", length))
08187         cnf = TS_CONFIG_HTTP_CACHE_REQUIRED_HEADERS;
08188       else if (!strncmp(name, "proxy.config.ssl.hsts_include_subdomains", length))
08189         cnf = TS_CONFIG_SSL_HSTS_INCLUDE_SUBDOMAINS;
08190       break;
08191     case 't':
08192       if (!strncmp(name, "proxy.config.http.keep_alive_enabled_out", length))
08193         cnf = TS_CONFIG_HTTP_KEEP_ALIVE_ENABLED_OUT;
08194       break;
08195     case 'y':
08196       if (!strncmp(name, "proxy.config.http.cache.fuzz.probability", length)) {
08197         typ = TS_RECORDDATATYPE_FLOAT;
08198         cnf = TS_CONFIG_HTTP_CACHE_FUZZ_PROBABILITY;
08199       }
08200       break;
08201     }
08202     break;
08203 
08204   case 41:
08205     switch (name[length-1]) {
08206     case 'd':
08207       if (!strncmp(name, "proxy.config.http.response_server_enabled", length))
08208         cnf = TS_CONFIG_HTTP_RESPONSE_SERVER_ENABLED;
08209       break;
08210     case 'e':
08211       if (!strncmp(name, "proxy.config.http.anonymize_remove_cookie", length))
08212         cnf = TS_CONFIG_HTTP_ANONYMIZE_REMOVE_COOKIE;
08213       else if (!strncmp(name, "proxy.config.http.request_header_max_size", length))
08214         cnf = TS_CONFIG_HTTP_REQUEST_HEADER_MAX_SIZE;
08215       break;
08216     case 'r':
08217       if (!strncmp(name, "proxy.config.http.insert_response_via_str", length))
08218         cnf = TS_CONFIG_HTTP_INSERT_RESPONSE_VIA_STR;
08219       else if (!strncmp(name, "proxy.config.http.flow_control.high_water", length))
08220         cnf = TS_CONFIG_HTTP_FLOW_CONTROL_HIGH_WATER_MARK;
08221       break;
08222     }
08223     break;
08224 
08225   case 42:
08226     switch (name[length-1]) {
08227     case 'd':
08228       if (!strncmp(name, "proxy.config.http.negative_caching_enabled", length))
08229         cnf = TS_CONFIG_HTTP_NEGATIVE_CACHING_ENABLED;
08230       break;
08231     case 'e':
08232       if (!strncmp(name, "proxy.config.http.cache.when_to_revalidate", length))
08233         cnf = TS_CONFIG_HTTP_CACHE_WHEN_TO_REVALIDATE;
08234       else if (!strncmp(name, "proxy.config.http.response_header_max_size", length))
08235         cnf = TS_CONFIG_HTTP_RESPONSE_HEADER_MAX_SIZE;
08236       break;
08237     case 'r':
08238       if (!strncmp(name, "proxy.config.http.anonymize_remove_referer", length))
08239         cnf = TS_CONFIG_HTTP_ANONYMIZE_REMOVE_REFERER;
08240       else if (!strncmp(name, "proxy.config.http.global_user_agent_header", length)) {
08241         cnf = TS_CONFIG_HTTP_GLOBAL_USER_AGENT_HEADER;
08242         typ = TS_RECORDDATATYPE_STRING;
08243       }
08244       break;
08245     case 't':
08246       if (!strncmp(name, "proxy.config.net.sock_recv_buffer_size_out", length))
08247         cnf = TS_CONFIG_NET_SOCK_RECV_BUFFER_SIZE_OUT;
08248       else if (!strncmp(name, "proxy.config.net.sock_send_buffer_size_out", length))
08249         cnf = TS_CONFIG_NET_SOCK_SEND_BUFFER_SIZE_OUT;
08250       else if (!strncmp(name, "proxy.config.http.connect_attempts_timeout", length))
08251         cnf = TS_CONFIG_HTTP_CONNECT_ATTEMPTS_TIMEOUT;
08252       break;
08253     }
08254     break;
08255 
08256   case 43:
08257     switch (name[length-1]) {
08258     case 'e':
08259       if (!strncmp(name, "proxy.config.http.negative_caching_lifetime", length))
08260         cnf = TS_CONFIG_HTTP_NEGATIVE_CACHING_LIFETIME;
08261       break;
08262     case 'k':
08263       if (!strncmp(name, "proxy.config.http.default_buffer_water_mark", length))
08264         cnf = TS_CONFIG_HTTP_DEFAULT_BUFFER_WATER_MARK;
08265       break;
08266     case 'l':
08267       if (!strncmp(name, "proxy.config.http.cache.cluster_cache_local", length))
08268         cnf = TS_CONFIG_HTTP_CACHE_CLUSTER_CACHE_LOCAL;
08269       break;
08270     case 'r':
08271       if (!strncmp(name, "proxy.config.http.cache.heuristic_lm_factor", length)) {
08272         typ = TS_RECORDDATATYPE_FLOAT;
08273         cnf = TS_CONFIG_HTTP_CACHE_HEURISTIC_LM_FACTOR;
08274       }
08275       break;
08276     }
08277     break;
08278 
08279   case 44:
08280     switch (name[length-1]) {
08281     case 'p':
08282       if (!strncmp(name, "proxy.config.http.anonymize_remove_client_ip", length))
08283         cnf = TS_CONFIG_HTTP_ANONYMIZE_REMOVE_CLIENT_IP;
08284       else if (!strncmp(name, "proxy.config.http.anonymize_insert_client_ip", length))
08285         cnf = TS_CONFIG_HTTP_ANONYMIZE_INSERT_CLIENT_IP;
08286       break;
08287     case 'e':
08288       if (!strncmp(name, "proxy.config.http.cache.open_read_retry_time", length))
08289         cnf = TS_CONFIG_HTTP_CACHE_OPEN_READ_RETRY_TIME;
08290       break;
08291     }
08292     break;
08293 
08294   case 45:
08295     switch (name[length-1]) {
08296     case 'd':
08297       if (!strncmp(name, "proxy.config.http.down_server.abort_threshold", length))
08298         cnf = TS_CONFIG_HTTP_DOWN_SERVER_ABORT_THRESHOLD;
08299       break;
08300     case 'n':
08301       if (!strncmp(name, "proxy.config.http.cache.ignore_authentication", length))
08302         cnf = TS_CONFIG_HTTP_CACHE_IGNORE_AUTHENTICATION;
08303       break;
08304     case 't':
08305       if (!strncmp(name, "proxy.config.http.anonymize_remove_user_agent", length))
08306         cnf = TS_CONFIG_HTTP_ANONYMIZE_REMOVE_USER_AGENT;
08307       break;
08308     case 's':
08309       if (!strncmp(name, "proxy.config.http.connect_attempts_rr_retries", length))
08310         cnf = TS_CONFIG_HTTP_CONNECT_ATTEMPTS_RR_RETRIES;
08311       else if (!strncmp(name, "proxy.config.http.cache.max_open_read_retries", length))
08312         cnf = TS_CONFIG_HTTP_CACHE_MAX_OPEN_READ_RETRIES;
08313       break;
08314     case 'l':
08315       if (0 == strncmp(name, "proxy.config.http.server_session_sharing.pool", length))
08316         cnf = TS_CONFIG_HTTP_SERVER_SESSION_SHARING_POOL;
08317       break;
08318     }
08319     break;
08320 
08321   case 46:
08322     switch (name[length-1]) {
08323     case 'e':
08324       if (!strncmp(name, "proxy.config.http.cache.ignore_client_no_cache", length))
08325         cnf = TS_CONFIG_HTTP_CACHE_IGNORE_CLIENT_NO_CACHE;
08326       else if (!strncmp(name, "proxy.config.http.cache.ims_on_client_no_cache", length))
08327         cnf = TS_CONFIG_HTTP_CACHE_IMS_ON_CLIENT_NO_CACHE;
08328       else if (!strncmp(name, "proxy.config.http.cache.ignore_server_no_cache", length))
08329         cnf = TS_CONFIG_HTTP_CACHE_IGNORE_SERVER_NO_CACHE;
08330       else if (!strncmp(name, "proxy.config.http.cache.heuristic_min_lifetime", length))
08331         cnf = TS_CONFIG_HTTP_CACHE_HEURISTIC_MIN_LIFETIME;
08332       else if (!strncmp(name, "proxy.config.http.cache.heuristic_max_lifetime", length))
08333         cnf = TS_CONFIG_HTTP_CACHE_HEURISTIC_MAX_LIFETIME;
08334       break;
08335     case 'r':
08336       if (!strncmp(name, "proxy.config.http.insert_squid_x_forwarded_for", length))
08337         cnf = TS_CONFIG_HTTP_INSERT_SQUID_X_FORWARDED_FOR;
08338       break;
08339     case 's':
08340       if (!strncmp(name, "proxy.config.http.connect_attempts_max_retries", length))
08341         cnf = TS_CONFIG_HTTP_CONNECT_ATTEMPTS_MAX_RETRIES;
08342       break;
08343     case 't':
08344       if (!strncmp(name, "proxy.config.http.forward.proxy_auth_to_parent", length))
08345         cnf = TS_CONFIG_HTTP_FORWARD_PROXY_AUTH_TO_PARENT;
08346       break;
08347     case 'h':
08348       if (0 == strncmp(name, "proxy.config.http.server_session_sharing.match", length))
08349         cnf = TS_CONFIG_HTTP_SERVER_SESSION_SHARING_MATCH;
08350       break;
08351     }
08352     break;
08353 
08354   case 47:
08355     switch (name[length-1]) {
08356     case 'd':
08357       if (!strncmp(name, "proxy.config.http.negative_revalidating_enabled", length))
08358         cnf = TS_CONFIG_HTTP_NEGATIVE_REVALIDATING_ENABLED;
08359       break;
08360     case 'e':
08361       if (!strncmp(name, "proxy.config.http.cache.guaranteed_min_lifetime", length))
08362         cnf = TS_CONFIG_HTTP_CACHE_GUARANTEED_MIN_LIFETIME;
08363       else if (!strncmp(name, "proxy.config.http.cache.guaranteed_max_lifetime", length))
08364         cnf = TS_CONFIG_HTTP_CACHE_GUARANTEED_MAX_LIFETIME;
08365       break;
08366     case 't':
08367       if (!strncmp(name, "proxy.config.http.post_connect_attempts_timeout", length))
08368         cnf = TS_CONFIG_HTTP_POST_CONNECT_ATTEMPTS_TIMEOUT;
08369       break;
08370     }
08371     break;
08372 
08373   case 48:
08374     switch (name[length-1]) {
08375     case 'd':
08376       if (!strncmp(name, "proxy.config.http.accept_encoding_filter_enabled", length))
08377         cnf = TS_CONFIG_HTTP_ACCEPT_ENCODING_FILTER_ENABLED;
08378       break;
08379     case 'e':
08380       if (!strncmp(name, "proxy.config.http.cache.ignore_client_cc_max_age", length))
08381         cnf = TS_CONFIG_HTTP_CACHE_IGNORE_CLIENT_CC_MAX_AGE;
08382       else if (!strncmp(name, "proxy.config.http.negative_revalidating_lifetime", length))
08383         cnf = TS_CONFIG_HTTP_NEGATIVE_REVALIDATING_LIFETIME;
08384       break;
08385     case 't':
08386       switch (name[length-4]) {
08387       case '_':
08388         if (!strncmp(name, "proxy.config.http.transaction_active_timeout_out", length))
08389           cnf = TS_CONFIG_HTTP_TRANSACTION_ACTIVE_TIMEOUT_OUT;
08390         break;
08391       case 'e':
08392           if (!strncmp(name, "proxy.config.http.background_fill_active_timeout", length)) {
08393             cnf = TS_CONFIG_HTTP_BACKGROUND_FILL_ACTIVE_TIMEOUT;
08394           }
08395           break;
08396       }
08397       break;
08398     }
08399     break;
08400 
08401   case 50:
08402     if (!strncmp(name, "proxy.config.http.cache.cache_responses_to_cookies", length))
08403       cnf = TS_CONFIG_HTTP_CACHE_CACHE_RESPONSES_TO_COOKIES;
08404     break;
08405 
08406   case 51:
08407     switch (name[length-1]) {
08408     case 'n':
08409       if (!strncmp(name, "proxy.config.http.keep_alive_no_activity_timeout_in", length))
08410         cnf = TS_CONFIG_HTTP_KEEP_ALIVE_NO_ACTIVITY_TIMEOUT_IN;
08411       break;
08412     case 'd':
08413       if (!strncmp(name, "proxy.config.http.post.check.content_length.enabled", length))
08414         cnf = TS_CONFIG_HTTP_POST_CHECK_CONTENT_LENGTH_ENABLED;
08415       break;
08416     }
08417     break;
08418 
08419   case 52:
08420     switch (name[length-1]) {
08421     case 'c':
08422       if (!strncmp(name, "proxy.config.http.cache.cache_urls_that_look_dynamic", length))
08423         cnf = TS_CONFIG_HTTP_CACHE_CACHE_URLS_THAT_LOOK_DYNAMIC;
08424       break;
08425     case 'n':
08426       if (!strncmp(name, "proxy.config.http.transaction_no_activity_timeout_in", length))
08427         cnf = TS_CONFIG_HTTP_TRANSACTION_NO_ACTIVITY_TIMEOUT_IN;
08428       break;
08429     case 't':
08430       if (!strncmp(name, "proxy.config.http.keep_alive_no_activity_timeout_out", length))
08431         cnf = TS_CONFIG_HTTP_KEEP_ALIVE_NO_ACTIVITY_TIMEOUT_OUT;
08432       break;
08433     }
08434     break;
08435 
08436   case 53:
08437     switch (name[length-1]) {
08438       case 't':
08439       if (!strncmp(name, "proxy.config.http.transaction_no_activity_timeout_out", length))
08440         cnf = TS_CONFIG_HTTP_TRANSACTION_NO_ACTIVITY_TIMEOUT_OUT;
08441       break;
08442       case 'd':
08443         if (!strncmp(name, "proxy.config.http.background_fill_completed_threshold", length)) {
08444           typ = TS_RECORDDATATYPE_FLOAT;
08445           cnf = TS_CONFIG_HTTP_BACKGROUND_FILL_COMPLETED_THRESHOLD;
08446         }
08447       break;
08448     }
08449     break;
08450 
08451   case 58:
08452    if (!strncmp(name, "proxy.config.http.connect_attempts_max_retries_dead_server", length))
08453      cnf = TS_CONFIG_HTTP_CONNECT_ATTEMPTS_MAX_RETRIES_DEAD_SERVER;
08454    break;
08455   }
08456 
08457   *conf = cnf;
08458   if (type)
08459     *type = typ;
08460 
08461   return ((cnf != TS_CONFIG_NULL) ? TS_SUCCESS: TS_ERROR);
08462 }
08463 
08464 TSReturnCode
08465 TSHttpTxnPrivateSessionSet(TSHttpTxn txnp, int private_session)
08466 {
08467   if (sdk_sanity_check_txn(txnp) != TS_SUCCESS) {
08468     return TS_ERROR;
08469   }
08470   HttpSM *sm = (HttpSM *) txnp;
08471   if (sm->set_server_session_private(private_session)) {
08472     return TS_SUCCESS;
08473   }
08474   return TS_ERROR;
08475 }
08476 
08477 // APIs to register new Mgmt (records.config) entries.
08478 TSReturnCode
08479 TSMgmtStringCreate(TSRecordType rec_type, const char *name, const TSMgmtString data_default,
08480                    TSRecordUpdateType update_type, TSRecordCheckType check_type,
08481                    const char *check_regex, TSRecordAccessType access_type)
08482 {
08483   if (check_regex == NULL && check_type != TS_RECORDCHECK_NULL)
08484       return TS_ERROR;
08485   if (REC_ERR_OKAY != RecRegisterConfigString((enum RecT)rec_type, name, data_default, (enum RecUpdateT)update_type,
08486                                               (enum RecCheckT)check_type, check_regex, (enum RecAccessT)access_type))
08487     return TS_ERROR;
08488 
08489   return TS_SUCCESS;
08490 }
08491 
08492 TSReturnCode
08493 TSMgmtIntCreate(TSRecordType rec_type, const char *name, TSMgmtInt data_default,
08494                 TSRecordUpdateType update_type, TSRecordCheckType check_type,
08495                 const char *check_regex, TSRecordAccessType access_type)
08496 {
08497   if (check_regex == NULL && check_type != TS_RECORDCHECK_NULL)
08498       return TS_ERROR;
08499   if (REC_ERR_OKAY != RecRegisterConfigInt((enum RecT)rec_type, name, (RecInt)data_default, (enum RecUpdateT)update_type,
08500                                            (enum RecCheckT)check_type, check_regex, (enum RecAccessT)access_type))
08501     return TS_ERROR;
08502 
08503   return TS_SUCCESS;
08504 }
08505 
08506 TSReturnCode
08507 TSHttpTxnCloseAfterResponse (TSHttpTxn txnp, int should_close)
08508 {
08509     if (sdk_sanity_check_txn(txnp)!=TS_SUCCESS) {
08510            return TS_ERROR;
08511     }
08512 
08513     HttpSM *sm = (HttpSM*)txnp;
08514     if (should_close) {
08515         sm->t_state.client_info.keep_alive = HTTP_NO_KEEPALIVE;
08516         if (sm->ua_session) sm->set_ua_half_close_flag();
08517     }
08518     // Don't change if PIPELINE is set...
08519     else if (sm->t_state.client_info.keep_alive == HTTP_NO_KEEPALIVE) {
08520         sm->t_state.client_info.keep_alive = HTTP_KEEPALIVE;
08521     }
08522 
08523     return TS_SUCCESS;
08524 }
08525 
08526 // Parse a port descriptor for the proxy.config.http.server_ports descriptor format.
08527 TSPortDescriptor
08528 TSPortDescriptorParse(const char * descriptor)
08529 {
08530   HttpProxyPort * port = new HttpProxyPort();
08531 
08532   if (descriptor && port->processOptions(descriptor)) {
08533     return (TSPortDescriptor)port;
08534   }
08535 
08536   delete port;
08537   return NULL;
08538 }
08539 
08540 TSReturnCode
08541 TSPortDescriptorAccept(TSPortDescriptor descp, TSCont contp)
08542 {
08543   Action * action = NULL;
08544   HttpProxyPort * port = (HttpProxyPort *)descp;
08545   NetProcessor::AcceptOptions net(make_net_accept_options(*port, 0 /* nthreads */));
08546 
08547   if (port->isSSL()) {
08548     action = sslNetProcessor.main_accept((INKContInternal *)contp, port->m_fd, net);
08549   } else {
08550     action = netProcessor.main_accept((INKContInternal *)contp, port->m_fd, net);
08551   }
08552 
08553   return action ? TS_SUCCESS : TS_ERROR;
08554 }
08555 
08556 TSReturnCode
08557 TSPluginDescriptorAccept(TSCont contp)
08558 {
08559   Action * action = NULL;
08560 
08561   HttpProxyPort::Group& proxy_ports = HttpProxyPort::global();
08562   for ( int i = 0 , n = proxy_ports.length() ; i < n ; ++i ) {
08563     HttpProxyPort& port = proxy_ports[i];
08564     if (port.isPlugin()) {
08565       NetProcessor::AcceptOptions net(make_net_accept_options(port, 0 /* nthreads */));
08566       action = netProcessor.main_accept((INKContInternal *)contp, port.m_fd, net);
08567     }
08568   }
08569   return action ? TS_SUCCESS : TS_ERROR;
08570 }
08571 
08572 
08573 int
08574 TSHttpTxnBackgroundFillStarted(TSHttpTxn txnp)
08575 {
08576   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
08577   HttpSM *s = (HttpSM*) txnp;
08578 
08579   return (s->background_fill == BACKGROUND_FILL_STARTED);
08580 }
08581 
08582 int
08583 TSHttpTxnIsCacheable(TSHttpTxn txnp, TSMBuffer request, TSMBuffer response)
08584 {
08585   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
08586   HttpSM *sm = (HttpSM *) txnp;
08587   HTTPHdr *req, *resp;
08588 
08589   // We allow for either request or response to be empty (or both), in
08590   // which case we default to the transactions request or response.
08591   if (request) {
08592     sdk_sanity_check_mbuffer(request);
08593     req = reinterpret_cast<HTTPHdr*>(request);
08594   } else {
08595     req = &(sm->t_state.hdr_info.client_request);
08596   }
08597   if (response) {
08598     sdk_sanity_check_mbuffer(response);
08599     resp = reinterpret_cast<HTTPHdr*>(response);
08600   } else {
08601     resp = &(sm->t_state.hdr_info.server_response);
08602   }
08603 
08604   // Make sure these are valid response / requests, then verify if it's cacheable.
08605   return (req->valid() && resp->valid() && HttpTransact::is_response_cacheable(&(sm->t_state), req, resp)) ? 1: 0;
08606 }
08607 
08608 
08609 // Lookup various debug names for common HTTP types.
08610 const char*
08611 TSHttpServerStateNameLookup(TSServerState state)
08612 {
08613   return HttpDebugNames::get_server_state_name(static_cast<HttpTransact::ServerState_t>(state));
08614 }
08615 
08616 const char*
08617 TSHttpHookNameLookup(TSHttpHookID hook)
08618 {
08619   return HttpDebugNames::get_api_hook_name(static_cast<TSHttpHookID>(hook));
08620 }
08621 
08622 const char*
08623 TSHttpEventNameLookup(TSEvent event)
08624 {
08625   return HttpDebugNames::get_event_name(static_cast<int>(event));
08626 }

Generated by  doxygen 1.7.1