1 /** @file
2 
3   Implements the Traffic Server C API functions.
4 
5   @section license License
6 
7   Licensed to the Apache Software Foundation (ASF) under one
8   or more contributor license agreements.  See the NOTICE file
9   distributed with this work for additional information
10   regarding copyright ownership.  The ASF licenses this file
11   to you under the Apache License, Version 2.0 (the
12   "License"); you may not use this file except in compliance
13   with the License.  You may obtain a copy of the License at
14 
15       http://www.apache.org/licenses/LICENSE-2.0
16 
17   Unless required by applicable law or agreed to in writing, software
18   distributed under the License is distributed on an "AS IS" BASIS,
19   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20   See the License for the specific language governing permissions and
21   limitations under the License.
22  */
23 
24 #include <cstdio>
25 #include <atomic>
26 #include <string_view>
27 #include <tuple>
28 #include <unordered_map>
29 #include <string_view>
30 
31 #include "tscore/ink_platform.h"
32 #include "tscore/ink_base64.h"
33 #include "tscore/I_Layout.h"
34 #include "tscore/I_Version.h"
35 
36 #include "InkAPIInternal.h"
37 #include "Log.h"
38 #include "URL.h"
39 #include "MIME.h"
40 #include "HTTP.h"
41 #include "ProxySession.h"
42 #include "Http2ClientSession.h"
43 #include "Http1ServerSession.h"
44 #include "HttpSM.h"
45 #include "HttpConfig.h"
46 #include "P_Net.h"
47 #include "P_SSLNextProtocolAccept.h"
48 #include "P_UDPNet.h"
49 #include "P_HostDB.h"
50 #include "P_Cache.h"
51 #include "records/I_RecCore.h"
52 #include "P_SSLConfig.h"
53 #include "P_SSLClientUtils.h"
54 #include "SSLDiags.h"
55 #include "SSLInternal.h"
56 #include "ProxyConfig.h"
57 #include "Plugin.h"
58 #include "LogObject.h"
59 #include "LogConfig.h"
60 #include "PluginVC.h"
61 #include "ts/experimental.h"
62 #include "HttpSessionAccept.h"
63 #include "PluginVC.h"
64 #include "FetchSM.h"
65 #include "HttpDebugNames.h"
66 #include "I_AIO.h"
67 #include "I_Tasks.h"
68 
69 #include "P_OCSPStapling.h"
70 #include "RecordsConfig.h"
71 #include "records/I_RecDefs.h"
72 #include "records/I_RecCore.h"
73 #include "I_Machine.h"
74 #include "HttpProxyServerMain.h"
75 
76 #include "ts/ts.h"
77 
78 /****************************************************************
79  *  IMPORTANT - READ ME
80  * Any plugin using the IO Core must enter
81  *   with a held mutex.  SDK 1.0, 1.1 & 2.0 did not
82  *   have this restriction so we need to add a mutex
83  *   to Plugin's Continuation if it trys to use the IOCore
84  * Not only does the plugin have to have a mutex
85  *   before entering the IO Core.  The mutex needs to be held.
86  *   We now take out the mutex on each call to ensure it is
87  *   held for the entire duration of the IOCore call
88  ***************************************************************/
89 
90 // helper macro for setting HTTPHdr data
91 #define SET_HTTP_HDR(_HDR, _BUF_PTR, _OBJ_PTR)          \
92   _HDR.m_heap = ((HdrHeapSDKHandle *)_BUF_PTR)->m_heap; \
93   _HDR.m_http = (HTTPHdrImpl *)_OBJ_PTR;                \
94   _HDR.m_mime = _HDR.m_http->m_fields_impl;
95 
96 extern AppVersionInfo appVersionInfo;
97 
98 // Globals for new librecords stats
99 static int api_rsb_index;
100 static RecRawStatBlock *api_rsb;
101 
102 /** Reservation for a user arg.
103  */
104 struct UserArg {
105   /// Types of user args.
106   enum Type {
107     TXN,   ///< Transaction based.
108     SSN,   ///< Session based
109     VCONN, ///< VConnection based
110     COUNT  ///< Fake enum, # of valid entries.
111   };
112 
113   std::string name;        ///< Name of reserving plugin.
114   std::string description; ///< Description of use for this arg.
115 };
116 
117 /// Table of reservations, indexed by type and then index.
118 UserArg UserArgTable[UserArg::Type::COUNT][TS_HTTP_MAX_USER_ARG];
119 /// Table of next reserved index.
120 std::atomic<int> UserArgIdx[UserArg::Type::COUNT];
121 
122 /* URL schemes */
123 tsapi const char *TS_URL_SCHEME_FILE;
124 tsapi const char *TS_URL_SCHEME_FTP;
125 tsapi const char *TS_URL_SCHEME_GOPHER;
126 tsapi const char *TS_URL_SCHEME_HTTP;
127 tsapi const char *TS_URL_SCHEME_HTTPS;
128 tsapi const char *TS_URL_SCHEME_MAILTO;
129 tsapi const char *TS_URL_SCHEME_NEWS;
130 tsapi const char *TS_URL_SCHEME_NNTP;
131 tsapi const char *TS_URL_SCHEME_PROSPERO;
132 tsapi const char *TS_URL_SCHEME_TELNET;
133 tsapi const char *TS_URL_SCHEME_TUNNEL;
134 tsapi const char *TS_URL_SCHEME_WAIS;
135 tsapi const char *TS_URL_SCHEME_PNM;
136 tsapi const char *TS_URL_SCHEME_RTSP;
137 tsapi const char *TS_URL_SCHEME_RTSPU;
138 tsapi const char *TS_URL_SCHEME_MMS;
139 tsapi const char *TS_URL_SCHEME_MMSU;
140 tsapi const char *TS_URL_SCHEME_MMST;
141 tsapi const char *TS_URL_SCHEME_WS;
142 tsapi const char *TS_URL_SCHEME_WSS;
143 
144 /* URL schemes string lengths */
145 tsapi int TS_URL_LEN_FILE;
146 tsapi int TS_URL_LEN_FTP;
147 tsapi int TS_URL_LEN_GOPHER;
148 tsapi int TS_URL_LEN_HTTP;
149 tsapi int TS_URL_LEN_HTTPS;
150 tsapi int TS_URL_LEN_MAILTO;
151 tsapi int TS_URL_LEN_NEWS;
152 tsapi int TS_URL_LEN_NNTP;
153 tsapi int TS_URL_LEN_PROSPERO;
154 tsapi int TS_URL_LEN_TELNET;
155 tsapi int TS_URL_LEN_TUNNEL;
156 tsapi int TS_URL_LEN_WAIS;
157 tsapi int TS_URL_LEN_PNM;
158 tsapi int TS_URL_LEN_RTSP;
159 tsapi int TS_URL_LEN_RTSPU;
160 tsapi int TS_URL_LEN_MMS;
161 tsapi int TS_URL_LEN_MMSU;
162 tsapi int TS_URL_LEN_MMST;
163 tsapi int TS_URL_LEN_WS;
164 tsapi int TS_URL_LEN_WSS;
165 
166 /* MIME fields */
167 tsapi const char *TS_MIME_FIELD_ACCEPT;
168 tsapi const char *TS_MIME_FIELD_ACCEPT_CHARSET;
169 tsapi const char *TS_MIME_FIELD_ACCEPT_ENCODING;
170 tsapi const char *TS_MIME_FIELD_ACCEPT_LANGUAGE;
171 tsapi const char *TS_MIME_FIELD_ACCEPT_RANGES;
172 tsapi const char *TS_MIME_FIELD_AGE;
173 tsapi const char *TS_MIME_FIELD_ALLOW;
174 tsapi const char *TS_MIME_FIELD_APPROVED;
175 tsapi const char *TS_MIME_FIELD_AUTHORIZATION;
176 tsapi const char *TS_MIME_FIELD_BYTES;
177 tsapi const char *TS_MIME_FIELD_CACHE_CONTROL;
178 tsapi const char *TS_MIME_FIELD_CLIENT_IP;
179 tsapi const char *TS_MIME_FIELD_CONNECTION;
180 tsapi const char *TS_MIME_FIELD_CONTENT_BASE;
181 tsapi const char *TS_MIME_FIELD_CONTENT_ENCODING;
182 tsapi const char *TS_MIME_FIELD_CONTENT_LANGUAGE;
183 tsapi const char *TS_MIME_FIELD_CONTENT_LENGTH;
184 tsapi const char *TS_MIME_FIELD_CONTENT_LOCATION;
185 tsapi const char *TS_MIME_FIELD_CONTENT_MD5;
186 tsapi const char *TS_MIME_FIELD_CONTENT_RANGE;
187 tsapi const char *TS_MIME_FIELD_CONTENT_TYPE;
188 tsapi const char *TS_MIME_FIELD_CONTROL;
189 tsapi const char *TS_MIME_FIELD_COOKIE;
190 tsapi const char *TS_MIME_FIELD_DATE;
191 tsapi const char *TS_MIME_FIELD_DISTRIBUTION;
192 tsapi const char *TS_MIME_FIELD_ETAG;
193 tsapi const char *TS_MIME_FIELD_EXPECT;
194 tsapi const char *TS_MIME_FIELD_EXPIRES;
195 tsapi const char *TS_MIME_FIELD_FOLLOWUP_TO;
196 tsapi const char *TS_MIME_FIELD_FROM;
197 tsapi const char *TS_MIME_FIELD_HOST;
198 tsapi const char *TS_MIME_FIELD_IF_MATCH;
199 tsapi const char *TS_MIME_FIELD_IF_MODIFIED_SINCE;
200 tsapi const char *TS_MIME_FIELD_IF_NONE_MATCH;
201 tsapi const char *TS_MIME_FIELD_IF_RANGE;
202 tsapi const char *TS_MIME_FIELD_IF_UNMODIFIED_SINCE;
203 tsapi const char *TS_MIME_FIELD_KEEP_ALIVE;
204 tsapi const char *TS_MIME_FIELD_KEYWORDS;
205 tsapi const char *TS_MIME_FIELD_LAST_MODIFIED;
206 tsapi const char *TS_MIME_FIELD_LINES;
207 tsapi const char *TS_MIME_FIELD_LOCATION;
208 tsapi const char *TS_MIME_FIELD_MAX_FORWARDS;
209 tsapi const char *TS_MIME_FIELD_MESSAGE_ID;
210 tsapi const char *TS_MIME_FIELD_NEWSGROUPS;
211 tsapi const char *TS_MIME_FIELD_ORGANIZATION;
212 tsapi const char *TS_MIME_FIELD_PATH;
213 tsapi const char *TS_MIME_FIELD_PRAGMA;
214 tsapi const char *TS_MIME_FIELD_PROXY_AUTHENTICATE;
215 tsapi const char *TS_MIME_FIELD_PROXY_AUTHORIZATION;
216 tsapi const char *TS_MIME_FIELD_PROXY_CONNECTION;
217 tsapi const char *TS_MIME_FIELD_PUBLIC;
218 tsapi const char *TS_MIME_FIELD_RANGE;
219 tsapi const char *TS_MIME_FIELD_REFERENCES;
220 tsapi const char *TS_MIME_FIELD_REFERER;
221 tsapi const char *TS_MIME_FIELD_REPLY_TO;
222 tsapi const char *TS_MIME_FIELD_RETRY_AFTER;
223 tsapi const char *TS_MIME_FIELD_SENDER;
224 tsapi const char *TS_MIME_FIELD_SERVER;
225 tsapi const char *TS_MIME_FIELD_SET_COOKIE;
226 tsapi const char *TS_MIME_FIELD_STRICT_TRANSPORT_SECURITY;
227 tsapi const char *TS_MIME_FIELD_SUBJECT;
228 tsapi const char *TS_MIME_FIELD_SUMMARY;
229 tsapi const char *TS_MIME_FIELD_TE;
230 tsapi const char *TS_MIME_FIELD_TRANSFER_ENCODING;
231 tsapi const char *TS_MIME_FIELD_UPGRADE;
232 tsapi const char *TS_MIME_FIELD_USER_AGENT;
233 tsapi const char *TS_MIME_FIELD_VARY;
234 tsapi const char *TS_MIME_FIELD_VIA;
235 tsapi const char *TS_MIME_FIELD_WARNING;
236 tsapi const char *TS_MIME_FIELD_WWW_AUTHENTICATE;
237 tsapi const char *TS_MIME_FIELD_XREF;
238 tsapi const char *TS_MIME_FIELD_X_FORWARDED_FOR;
239 tsapi const char *TS_MIME_FIELD_FORWARDED;
240 
241 /* MIME fields string lengths */
242 tsapi int TS_MIME_LEN_ACCEPT;
243 tsapi int TS_MIME_LEN_ACCEPT_CHARSET;
244 tsapi int TS_MIME_LEN_ACCEPT_ENCODING;
245 tsapi int TS_MIME_LEN_ACCEPT_LANGUAGE;
246 tsapi int TS_MIME_LEN_ACCEPT_RANGES;
247 tsapi int TS_MIME_LEN_AGE;
248 tsapi int TS_MIME_LEN_ALLOW;
249 tsapi int TS_MIME_LEN_APPROVED;
250 tsapi int TS_MIME_LEN_AUTHORIZATION;
251 tsapi int TS_MIME_LEN_BYTES;
252 tsapi int TS_MIME_LEN_CACHE_CONTROL;
253 tsapi int TS_MIME_LEN_CLIENT_IP;
254 tsapi int TS_MIME_LEN_CONNECTION;
255 tsapi int TS_MIME_LEN_CONTENT_BASE;
256 tsapi int TS_MIME_LEN_CONTENT_ENCODING;
257 tsapi int TS_MIME_LEN_CONTENT_LANGUAGE;
258 tsapi int TS_MIME_LEN_CONTENT_LENGTH;
259 tsapi int TS_MIME_LEN_CONTENT_LOCATION;
260 tsapi int TS_MIME_LEN_CONTENT_MD5;
261 tsapi int TS_MIME_LEN_CONTENT_RANGE;
262 tsapi int TS_MIME_LEN_CONTENT_TYPE;
263 tsapi int TS_MIME_LEN_CONTROL;
264 tsapi int TS_MIME_LEN_COOKIE;
265 tsapi int TS_MIME_LEN_DATE;
266 tsapi int TS_MIME_LEN_DISTRIBUTION;
267 tsapi int TS_MIME_LEN_ETAG;
268 tsapi int TS_MIME_LEN_EXPECT;
269 tsapi int TS_MIME_LEN_EXPIRES;
270 tsapi int TS_MIME_LEN_FOLLOWUP_TO;
271 tsapi int TS_MIME_LEN_FROM;
272 tsapi int TS_MIME_LEN_HOST;
273 tsapi int TS_MIME_LEN_IF_MATCH;
274 tsapi int TS_MIME_LEN_IF_MODIFIED_SINCE;
275 tsapi int TS_MIME_LEN_IF_NONE_MATCH;
276 tsapi int TS_MIME_LEN_IF_RANGE;
277 tsapi int TS_MIME_LEN_IF_UNMODIFIED_SINCE;
278 tsapi int TS_MIME_LEN_KEEP_ALIVE;
279 tsapi int TS_MIME_LEN_KEYWORDS;
280 tsapi int TS_MIME_LEN_LAST_MODIFIED;
281 tsapi int TS_MIME_LEN_LINES;
282 tsapi int TS_MIME_LEN_LOCATION;
283 tsapi int TS_MIME_LEN_MAX_FORWARDS;
284 tsapi int TS_MIME_LEN_MESSAGE_ID;
285 tsapi int TS_MIME_LEN_NEWSGROUPS;
286 tsapi int TS_MIME_LEN_ORGANIZATION;
287 tsapi int TS_MIME_LEN_PATH;
288 tsapi int TS_MIME_LEN_PRAGMA;
289 tsapi int TS_MIME_LEN_PROXY_AUTHENTICATE;
290 tsapi int TS_MIME_LEN_PROXY_AUTHORIZATION;
291 tsapi int TS_MIME_LEN_PROXY_CONNECTION;
292 tsapi int TS_MIME_LEN_PUBLIC;
293 tsapi int TS_MIME_LEN_RANGE;
294 tsapi int TS_MIME_LEN_REFERENCES;
295 tsapi int TS_MIME_LEN_REFERER;
296 tsapi int TS_MIME_LEN_REPLY_TO;
297 tsapi int TS_MIME_LEN_RETRY_AFTER;
298 tsapi int TS_MIME_LEN_SENDER;
299 tsapi int TS_MIME_LEN_SERVER;
300 tsapi int TS_MIME_LEN_SET_COOKIE;
301 tsapi int TS_MIME_LEN_STRICT_TRANSPORT_SECURITY;
302 tsapi int TS_MIME_LEN_SUBJECT;
303 tsapi int TS_MIME_LEN_SUMMARY;
304 tsapi int TS_MIME_LEN_TE;
305 tsapi int TS_MIME_LEN_TRANSFER_ENCODING;
306 tsapi int TS_MIME_LEN_UPGRADE;
307 tsapi int TS_MIME_LEN_USER_AGENT;
308 tsapi int TS_MIME_LEN_VARY;
309 tsapi int TS_MIME_LEN_VIA;
310 tsapi int TS_MIME_LEN_WARNING;
311 tsapi int TS_MIME_LEN_WWW_AUTHENTICATE;
312 tsapi int TS_MIME_LEN_XREF;
313 tsapi int TS_MIME_LEN_X_FORWARDED_FOR;
314 tsapi int TS_MIME_LEN_FORWARDED;
315 
316 /* HTTP miscellaneous values */
317 tsapi const char *TS_HTTP_VALUE_BYTES;
318 tsapi const char *TS_HTTP_VALUE_CHUNKED;
319 tsapi const char *TS_HTTP_VALUE_CLOSE;
320 tsapi const char *TS_HTTP_VALUE_COMPRESS;
321 tsapi const char *TS_HTTP_VALUE_DEFLATE;
322 tsapi const char *TS_HTTP_VALUE_GZIP;
323 tsapi const char *TS_HTTP_VALUE_IDENTITY;
324 tsapi const char *TS_HTTP_VALUE_KEEP_ALIVE;
325 tsapi const char *TS_HTTP_VALUE_MAX_AGE;
326 tsapi const char *TS_HTTP_VALUE_MAX_STALE;
327 tsapi const char *TS_HTTP_VALUE_MIN_FRESH;
328 tsapi const char *TS_HTTP_VALUE_MUST_REVALIDATE;
329 tsapi const char *TS_HTTP_VALUE_NONE;
330 tsapi const char *TS_HTTP_VALUE_NO_CACHE;
331 tsapi const char *TS_HTTP_VALUE_NO_STORE;
332 tsapi const char *TS_HTTP_VALUE_NO_TRANSFORM;
333 tsapi const char *TS_HTTP_VALUE_ONLY_IF_CACHED;
334 tsapi const char *TS_HTTP_VALUE_PRIVATE;
335 tsapi const char *TS_HTTP_VALUE_PROXY_REVALIDATE;
336 tsapi const char *TS_HTTP_VALUE_PUBLIC;
337 tsapi const char *TS_HTTP_VALUE_S_MAXAGE;
338 
339 /* HTTP miscellaneous values string lengths */
340 tsapi int TS_HTTP_LEN_BYTES;
341 tsapi int TS_HTTP_LEN_CHUNKED;
342 tsapi int TS_HTTP_LEN_CLOSE;
343 tsapi int TS_HTTP_LEN_COMPRESS;
344 tsapi int TS_HTTP_LEN_DEFLATE;
345 tsapi int TS_HTTP_LEN_GZIP;
346 tsapi int TS_HTTP_LEN_IDENTITY;
347 tsapi int TS_HTTP_LEN_KEEP_ALIVE;
348 tsapi int TS_HTTP_LEN_MAX_AGE;
349 tsapi int TS_HTTP_LEN_MAX_STALE;
350 tsapi int TS_HTTP_LEN_MIN_FRESH;
351 tsapi int TS_HTTP_LEN_MUST_REVALIDATE;
352 tsapi int TS_HTTP_LEN_NONE;
353 tsapi int TS_HTTP_LEN_NO_CACHE;
354 tsapi int TS_HTTP_LEN_NO_STORE;
355 tsapi int TS_HTTP_LEN_NO_TRANSFORM;
356 tsapi int TS_HTTP_LEN_ONLY_IF_CACHED;
357 tsapi int TS_HTTP_LEN_PRIVATE;
358 tsapi int TS_HTTP_LEN_PROXY_REVALIDATE;
359 tsapi int TS_HTTP_LEN_PUBLIC;
360 tsapi int TS_HTTP_LEN_S_MAXAGE;
361 
362 /* HTTP methods */
363 tsapi const char *TS_HTTP_METHOD_CONNECT;
364 tsapi const char *TS_HTTP_METHOD_DELETE;
365 tsapi const char *TS_HTTP_METHOD_GET;
366 tsapi const char *TS_HTTP_METHOD_HEAD;
367 tsapi const char *TS_HTTP_METHOD_OPTIONS;
368 tsapi const char *TS_HTTP_METHOD_POST;
369 tsapi const char *TS_HTTP_METHOD_PURGE;
370 tsapi const char *TS_HTTP_METHOD_PUT;
371 tsapi const char *TS_HTTP_METHOD_TRACE;
372 tsapi const char *TS_HTTP_METHOD_PUSH;
373 
374 /* HTTP methods string lengths */
375 tsapi int TS_HTTP_LEN_CONNECT;
376 tsapi int TS_HTTP_LEN_DELETE;
377 tsapi int TS_HTTP_LEN_GET;
378 tsapi int TS_HTTP_LEN_HEAD;
379 tsapi int TS_HTTP_LEN_OPTIONS;
380 tsapi int TS_HTTP_LEN_POST;
381 tsapi int TS_HTTP_LEN_PURGE;
382 tsapi int TS_HTTP_LEN_PUT;
383 tsapi int TS_HTTP_LEN_TRACE;
384 tsapi int TS_HTTP_LEN_PUSH;
385 
386 /* MLoc Constants */
387 tsapi const TSMLoc TS_NULL_MLOC = (TSMLoc) nullptr;
388 
389 HttpAPIHooks *http_global_hooks        = nullptr;
390 SslAPIHooks *ssl_hooks                 = nullptr;
391 LifecycleAPIHooks *lifecycle_hooks     = nullptr;
392 ConfigUpdateCbTable *global_config_cbs = nullptr;
393 
394 static char traffic_server_version[128] = "";
395 static int ts_major_version             = 0;
396 static int ts_minor_version             = 0;
397 static int ts_patch_version             = 0;
398 
399 static ClassAllocator<APIHook> apiHookAllocator("apiHookAllocator");
400 static ClassAllocator<INKContInternal> INKContAllocator("INKContAllocator");
401 static ClassAllocator<INKVConnInternal> INKVConnAllocator("INKVConnAllocator");
402 static ClassAllocator<MIMEFieldSDKHandle> mHandleAllocator("MIMEFieldSDKHandle");
403 
404 ////////////////////////////////////////////////////////////////////
405 //
406 // API error logging
407 //
408 ////////////////////////////////////////////////////////////////////
409 void
410 TSError(const char *fmt, ...)
411 {
412   va_list args;
413 
414   va_start(args, fmt);
415   ErrorV(fmt, args);
416   va_end(args);
417 }
418 
419 tsapi void
420 TSEmergency(const char *fmt, ...)
421 {
422   va_list args;
423 
424   va_start(args, fmt);
425   EmergencyV(fmt, args);
426   va_end(args);
427 }
428 
429 tsapi void
430 TSFatal(const char *fmt, ...)
431 {
432   va_list args;
433 
434   va_start(args, fmt);
435   FatalV(fmt, args);
436   va_end(args);
437 }
438 
439 // Assert in debug AND optim
440 void
441 _TSReleaseAssert(const char *text, const char *file, int line)
442 {
443   _ink_assert(text, file, line);
444 }
445 
446 // Assert only in debug
447 int
448 #ifdef DEBUG
449 _TSAssert(const char *text, const char *file, int line)
450 {
451   _ink_assert(text, file, line);
452   return 0;
453 }
454 #else
455 _TSAssert(const char *, const char *, int)
456 {
457   return 0;
458 }
459 #endif
460 
461 // This assert is for internal API use only.
462 #if TS_USE_FAST_SDK
463 #define sdk_assert(EX) (void)(EX)
464 #else
465 #define sdk_assert(EX) ((void)((EX) ? (void)0 : _TSReleaseAssert(#EX, __FILE__, __LINE__)))
466 #endif
467 
468 ////////////////////////////////////////////////////////////////////
469 //
470 // SDK Interoperability Support
471 //
472 // ----------------------------------------------------------------
473 //
474 // Standalone Fields (SDK Version-Interoperability Hack)
475 //
476 //
477 // A "standalone" field is an ugly hack for portability with old
478 // versions of the SDK that mirrored the old header system.  In
479 // the old system, you could create arbitrary tiny little field
480 // objects, distinct from MIME header objects, and link them
481 // together.  In the new header system, all fields are internal
482 // constituents of the MIME header.  To preserve the semantics of
483 // the old SDK, we need to maintain the concept of fields that
484 // are created outside of a MIME header.  Whenever a field is
485 // "attached" to a MIME header, it is copied into the MIME header
486 // field's slot, and the handle to the field is updated to refer
487 // to the new field.
488 //
489 // Hopefully, we can eliminate this old compatibility interface and
490 // migrate users to the newer semantics quickly.
491 //
492 // ----------------------------------------------------------------
493 //
494 // MIMEField SDK Handles (SDK Version-Interoperability Hack)
495 //
496 // MIMEField "handles" are used by the SDK as an indirect reference
497 // to the MIMEField.  Because versions 1 & 2 of the SDK allowed
498 // standalone fields that existed without associated MIME headers,
499 // and because the version 3 SDK requires an associated MIME header
500 // for all field mutation operations (for presence bits, etc.) we
501 // need a data structure that:
502 //
503 //   * identifies standalone fields and stores field name/value
504 //     information for fields that are not yet in a header
505 //   * redirects the field to a real header field when the field
506 //     is inserted into a header
507 //   * maintains the associated MIMEHdrImpl when returning field
508 //     slots from lookup and create functions
509 //
510 // If the MIMEHdrImpl pointer is NULL, then the handle points
511 // to a standalone field, otherwise the handle points to a field
512 // within the MIME header.
513 //
514 ////////////////////////////////////////////////////////////////////
515 
516 /*****************************************************************/
517 /* Handles to headers are impls, but need to handle MIME or HTTP */
518 /*****************************************************************/
519 
520 inline MIMEHdrImpl *
521 _hdr_obj_to_mime_hdr_impl(HdrHeapObjImpl *obj)
522 {
523   MIMEHdrImpl *impl;
524   if (obj->m_type == HDR_HEAP_OBJ_HTTP_HEADER) {
525     impl = ((HTTPHdrImpl *)obj)->m_fields_impl;
526   } else if (obj->m_type == HDR_HEAP_OBJ_MIME_HEADER) {
527     impl = (MIMEHdrImpl *)obj;
528   } else {
529     ink_release_assert(!"mloc not a header type");
530     impl = nullptr; /* gcc does not know about 'ink_release_assert' - make it happy */
531   }
532   return impl;
533 }
534 
535 inline MIMEHdrImpl *
536 _hdr_mloc_to_mime_hdr_impl(TSMLoc mloc)
537 {
538   return _hdr_obj_to_mime_hdr_impl((HdrHeapObjImpl *)mloc);
539 }
540 
541 TSReturnCode
542 sdk_sanity_check_field_handle(TSMLoc field, TSMLoc parent_hdr = nullptr)
543 {
544   if (field == TS_NULL_MLOC) {
545     return TS_ERROR;
546   }
547 
548   MIMEFieldSDKHandle *field_handle = (MIMEFieldSDKHandle *)field;
549   if (field_handle->m_type != HDR_HEAP_OBJ_FIELD_SDK_HANDLE) {
550     return TS_ERROR;
551   }
552 
553   if (parent_hdr != nullptr) {
554     MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(parent_hdr);
555     if (field_handle->mh != mh) {
556       return TS_ERROR;
557     }
558   }
559   return TS_SUCCESS;
560 }
561 
562 TSReturnCode
563 sdk_sanity_check_mbuffer(TSMBuffer bufp)
564 {
565   HdrHeapSDKHandle *handle = (HdrHeapSDKHandle *)bufp;
566   if ((handle == nullptr) || (handle->m_heap == nullptr) || (handle->m_heap->m_magic != HDR_BUF_MAGIC_ALIVE)) {
567     return TS_ERROR;
568   }
569 
570   return TS_SUCCESS;
571 }
572 
573 TSReturnCode
574 sdk_sanity_check_mime_hdr_handle(TSMLoc field)
575 {
576   if (field == TS_NULL_MLOC) {
577     return TS_ERROR;
578   }
579 
580   MIMEFieldSDKHandle *field_handle = (MIMEFieldSDKHandle *)field;
581   if (field_handle->m_type != HDR_HEAP_OBJ_MIME_HEADER) {
582     return TS_ERROR;
583   }
584 
585   return TS_SUCCESS;
586 }
587 
588 TSReturnCode
589 sdk_sanity_check_url_handle(TSMLoc field)
590 {
591   if (field == TS_NULL_MLOC) {
592     return TS_ERROR;
593   }
594 
595   MIMEFieldSDKHandle *field_handle = (MIMEFieldSDKHandle *)field;
596   if (field_handle->m_type != HDR_HEAP_OBJ_URL) {
597     return TS_ERROR;
598   }
599 
600   return TS_SUCCESS;
601 }
602 
603 TSReturnCode
604 sdk_sanity_check_http_hdr_handle(TSMLoc field)
605 {
606   if (field == TS_NULL_MLOC) {
607     return TS_ERROR;
608   }
609 
610   HTTPHdrImpl *field_handle = (HTTPHdrImpl *)field;
611   if (field_handle->m_type != HDR_HEAP_OBJ_HTTP_HEADER) {
612     return TS_ERROR;
613   }
614 
615   return TS_SUCCESS;
616 }
617 
618 TSReturnCode
619 sdk_sanity_check_continuation(TSCont cont)
620 {
621   if ((cont == nullptr) || (((INKContInternal *)cont)->m_free_magic == INKCONT_INTERN_MAGIC_DEAD)) {
622     return TS_ERROR;
623   }
624 
625   return TS_SUCCESS;
626 }
627 
628 TSReturnCode
629 sdk_sanity_check_fetch_sm(TSFetchSM fetch_sm)
630 {
631   if (fetch_sm == nullptr) {
632     return TS_ERROR;
633   }
634 
635   return TS_SUCCESS;
636 }
637 
638 TSReturnCode
639 sdk_sanity_check_http_ssn(TSHttpSsn ssnp)
640 {
641   if (ssnp == nullptr) {
642     return TS_ERROR;
643   }
644 
645   return TS_SUCCESS;
646 }
647 
648 TSReturnCode
649 sdk_sanity_check_txn(TSHttpTxn txnp)
650 {
651   if ((txnp != nullptr) && (((HttpSM *)txnp)->magic == HTTP_SM_MAGIC_ALIVE)) {
652     return TS_SUCCESS;
653   }
654   return TS_ERROR;
655 }
656 
657 TSReturnCode
658 sdk_sanity_check_mime_parser(TSMimeParser parser)
659 {
660   if (parser == nullptr) {
661     return TS_ERROR;
662   }
663   return TS_SUCCESS;
664 }
665 
666 TSReturnCode
667 sdk_sanity_check_http_parser(TSHttpParser parser)
668 {
669   if (parser == nullptr) {
670     return TS_ERROR;
671   }
672   return TS_SUCCESS;
673 }
674 
675 TSReturnCode
676 sdk_sanity_check_alt_info(TSHttpAltInfo info)
677 {
678   if (info == nullptr) {
679     return TS_ERROR;
680   }
681   return TS_SUCCESS;
682 }
683 
684 TSReturnCode
685 sdk_sanity_check_hook_id(TSHttpHookID id)
686 {
687   return HttpAPIHooks::is_valid(id) ? TS_SUCCESS : TS_ERROR;
688 }
689 
690 TSReturnCode
691 sdk_sanity_check_lifecycle_hook_id(TSLifecycleHookID id)
692 {
693   return LifecycleAPIHooks::is_valid(id) ? TS_SUCCESS : TS_ERROR;
694 }
695 
696 TSReturnCode
697 sdk_sanity_check_ssl_hook_id(TSHttpHookID id)
698 {
699   if (id < TS_SSL_FIRST_HOOK || id > TS_SSL_LAST_HOOK) {
700     return TS_ERROR;
701   }
702   return TS_SUCCESS;
703 }
704 
705 TSReturnCode
706 sdk_sanity_check_null_ptr(void const *ptr)
707 {
708   return ptr == nullptr ? TS_ERROR : TS_SUCCESS;
709 }
710 
711 // Plugin metric IDs index the plugin RSB, so bounds check against that.
712 static TSReturnCode
713 sdk_sanity_check_stat_id(int id)
714 {
715   if (id < 0 || id >= api_rsb->max_stats) {
716     return TS_ERROR;
717   }
718 
719   return TS_SUCCESS;
720 }
721 
722 /**
723   The function checks if the buffer is Modifiable and returns true if
724   it is modifiable, else returns false.
725 
726 */
727 bool
728 isWriteable(TSMBuffer bufp)
729 {
730   if (bufp != nullptr) {
731     return ((HdrHeapSDKHandle *)bufp)->m_heap->m_writeable;
732   }
733   return false;
734 }
735 
736 /******************************************************/
737 /* Allocators for field handles and standalone fields */
738 /******************************************************/
739 static MIMEFieldSDKHandle *
740 sdk_alloc_field_handle(TSMBuffer /* bufp ATS_UNUSED */, MIMEHdrImpl *mh)
741 {
742   MIMEFieldSDKHandle *handle = mHandleAllocator.alloc();
743 
744   // TODO: Should remove this when memory allocation can't fail.
745   sdk_assert(sdk_sanity_check_null_ptr((void *)handle) == TS_SUCCESS);
746 
747   obj_init_header(handle, HDR_HEAP_OBJ_FIELD_SDK_HANDLE, sizeof(MIMEFieldSDKHandle), 0);
748   handle->mh = mh;
749 
750   return handle;
751 }
752 
753 static void
754 sdk_free_field_handle(TSMBuffer bufp, MIMEFieldSDKHandle *field_handle)
755 {
756   if (sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS) {
757     mHandleAllocator.free(field_handle);
758   }
759 }
760 
761 ////////////////////////////////////////////////////////////////////
762 //
763 // FileImpl
764 //
765 ////////////////////////////////////////////////////////////////////
766 FileImpl::FileImpl() : m_fd(-1), m_mode(CLOSED), m_buf(nullptr), m_bufsize(0), m_bufpos(0) {}
767 
768 FileImpl::~FileImpl()
769 {
770   fclose();
771 }
772 
773 int
774 FileImpl::fopen(const char *filename, const char *mode)
775 {
776   if (mode[0] == '\0') {
777     return 0;
778   } else if (mode[0] == 'r') {
779     if (mode[1] != '\0') {
780       return 0;
781     }
782     m_mode = READ;
783     m_fd   = open(filename, O_RDONLY);
784   } else if (mode[0] == 'w') {
785     if (mode[1] != '\0') {
786       return 0;
787     }
788     m_mode = WRITE;
789     m_fd   = open(filename, O_WRONLY | O_CREAT, 0644);
790   } else if (mode[0] == 'a') {
791     if (mode[1] != '\0') {
792       return 0;
793     }
794     m_mode = WRITE;
795     m_fd   = open(filename, O_WRONLY | O_CREAT | O_APPEND, 0644);
796   }
797 
798   if (m_fd < 0) {
799     m_mode = CLOSED;
800     return 0;
801   } else {
802     return 1;
803   }
804 }
805 
806 void
807 FileImpl::fclose()
808 {
809   if (m_fd != -1) {
810     fflush();
811 
812     close(m_fd);
813     m_fd   = -1;
814     m_mode = CLOSED;
815   }
816 
817   if (m_buf) {
818     ats_free(m_buf);
819     m_buf     = nullptr;
820     m_bufsize = 0;
821     m_bufpos  = 0;
822   }
823 }
824 
825 ssize_t
826 FileImpl::fread(void *buf, size_t length)
827 {
828   size_t amount;
829   ssize_t err;
830 
831   if ((m_mode != READ) || (m_fd == -1)) {
832     return -1;
833   }
834 
835   if (!m_buf) {
836     m_bufpos  = 0;
837     m_bufsize = 1024;
838     m_buf     = (char *)ats_malloc(m_bufsize);
839   }
840 
841   if (m_bufpos < length) {
842     amount = length;
843     if (amount < 1024) {
844       amount = 1024;
845     }
846     if (amount > (m_bufsize - m_bufpos)) {
847       while (amount > (m_bufsize - m_bufpos)) {
848         m_bufsize *= 2;
849       }
850       m_buf = (char *)ats_realloc(m_buf, m_bufsize);
851     }
852 
853     do {
854       err = read(m_fd, &m_buf[m_bufpos], amount);
855     } while ((err < 0) && (errno == EINTR));
856 
857     if (err < 0) {
858       return -1;
859     }
860 
861     m_bufpos += err;
862   }
863 
864   if (buf) {
865     amount = length;
866     if (amount > m_bufpos) {
867       amount = m_bufpos;
868     }
869     memcpy(buf, m_buf, amount);
870     memmove(m_buf, &m_buf[amount], m_bufpos - amount);
871     m_bufpos -= amount;
872     return amount;
873   } else {
874     return m_bufpos;
875   }
876 }
877 
878 ssize_t
879 FileImpl::fwrite(const void *buf, size_t length)
880 {
881   const char *p, *e;
882   size_t avail;
883 
884   if ((m_mode != WRITE) || (m_fd == -1)) {
885     return -1;
886   }
887 
888   if (!m_buf) {
889     m_bufpos  = 0;
890     m_bufsize = 1024;
891     m_buf     = (char *)ats_malloc(m_bufsize);
892   }
893 
894   p = (const char *)buf;
895   e = p + length;
896 
897   while (p != e) {
898     avail = m_bufsize - m_bufpos;
899     if (avail > length) {
900       avail = length;
901     }
902     memcpy(&m_buf[m_bufpos], p, avail);
903 
904     m_bufpos += avail;
905     p += avail;
906     length -= avail;
907 
908     if ((length > 0) && (m_bufpos > 0)) {
909       if (fflush() <= 0) {
910         break;
911       }
912     }
913   }
914 
915   return (p - (const char *)buf);
916 }
917 
918 ssize_t
919 FileImpl::fflush()
920 {
921   char *p, *e;
922   ssize_t err = 0;
923 
924   if ((m_mode != WRITE) || (m_fd == -1)) {
925     return -1;
926   }
927 
928   if (m_buf) {
929     p = m_buf;
930     e = &m_buf[m_bufpos];
931 
932     while (p != e) {
933       do {
934         err = write(m_fd, p, e - p);
935       } while ((err < 0) && (errno == EINTR));
936 
937       if (err < 0) {
938         break;
939       }
940 
941       p += err;
942     }
943 
944     err = p - m_buf;
945     memmove(m_buf, &m_buf[err], m_bufpos - err);
946     m_bufpos -= err;
947   }
948 
949   return err;
950 }
951 
952 char *
953 FileImpl::fgets(char *buf, size_t length)
954 {
955   char *e;
956   size_t pos;
957 
958   if (length == 0) {
959     return nullptr;
960   }
961 
962   if (!m_buf || (m_bufpos < (length - 1))) {
963     pos = m_bufpos;
964 
965     if (fread(nullptr, length - 1) < 0) {
966       return nullptr;
967     }
968 
969     if (!m_bufpos && (pos == m_bufpos)) {
970       return nullptr;
971     }
972   }
973 
974   e = (char *)memchr(m_buf, '\n', m_bufpos);
975   if (e) {
976     e += 1;
977     if (length > (size_t)(e - m_buf + 1)) {
978       length = e - m_buf + 1;
979     }
980   }
981 
982   ssize_t rlen = fread(buf, length - 1);
983   if (rlen >= 0) {
984     buf[rlen] = '\0';
985   }
986 
987   return buf;
988 }
989 
990 ////////////////////////////////////////////////////////////////////
991 //
992 // INKContInternal
993 //
994 ////////////////////////////////////////////////////////////////////
995 
996 INKContInternal::INKContInternal()
997   : DummyVConnection(nullptr),
998     mdata(nullptr),
999     m_event_func(nullptr),
1000     m_event_count(0),
1001     m_closed(1),
1002     m_deletable(0),
1003     m_deleted(0),
1004     m_context(0),
1005     m_free_magic(INKCONT_INTERN_MAGIC_ALIVE)
1006 {
1007 }
1008 
1009 INKContInternal::INKContInternal(TSEventFunc funcp, TSMutex mutexp)
1010   : DummyVConnection((ProxyMutex *)mutexp),
1011     mdata(nullptr),
1012     m_event_func(funcp),
1013     m_event_count(0),
1014     m_closed(1),
1015     m_deletable(0),
1016     m_deleted(0),
1017     m_context(0),
1018     m_free_magic(INKCONT_INTERN_MAGIC_ALIVE)
1019 {
1020   SET_HANDLER(&INKContInternal::handle_event);
1021 }
1022 
1023 void
1024 INKContInternal::init(TSEventFunc funcp, TSMutex mutexp, void *context)
1025 {
1026   SET_HANDLER(&INKContInternal::handle_event);
1027 
1028   mutex        = (ProxyMutex *)mutexp;
1029   m_event_func = funcp;
1030   m_context    = context;
1031 }
1032 
1033 void
1034 INKContInternal::clear()
1035 {
1036 }
1037 
1038 void
1039 INKContInternal::free()
1040 {
1041   clear();
1042   this->mutex.clear();
1043   m_free_magic = INKCONT_INTERN_MAGIC_DEAD;
1044   INKContAllocator.free(this);
1045 }
1046 
1047 void
1048 INKContInternal::destroy()
1049 {
1050   if (m_free_magic == INKCONT_INTERN_MAGIC_DEAD) {
1051     ink_release_assert(!"Plugin tries to use a continuation which is deleted");
1052   }
1053   m_deleted = 1;
1054   if (m_deletable) {
1055     free();
1056   } else {
1057     // TODO: Should this schedule on some other "thread" ?
1058     // TODO: we don't care about the return action?
1059     if (ink_atomic_increment((int *)&m_event_count, 1) < 0) {
1060       ink_assert(!"not reached");
1061     }
1062     EThread *p = this_ethread();
1063 
1064     // If this_thread() returns null, the EThread object for the current thread has been destroyed (or it never existed).
1065     // Presumably this will only happen during destruction of statically-initialized objects at TS shutdown, so no further
1066     // action is needed.
1067     //
1068     if (p) {
1069       p->schedule_imm(this);
1070     }
1071   }
1072 }
1073 
1074 void
1075 INKContInternal::handle_event_count(int event)
1076 {
1077   if ((event == EVENT_IMMEDIATE) || (event == EVENT_INTERVAL) || event == TS_EVENT_HTTP_TXN_CLOSE) {
1078     int val = ink_atomic_increment((int *)&m_event_count, -1);
1079     if (val <= 0) {
1080       ink_assert(!"not reached");
1081     }
1082 
1083     m_deletable = (m_closed != 0) && (val == 1);
1084   }
1085 }
1086 
1087 int
1088 INKContInternal::handle_event(int event, void *edata)
1089 {
1090   if (m_free_magic == INKCONT_INTERN_MAGIC_DEAD) {
1091     ink_release_assert(!"Plugin tries to use a continuation which is deleted");
1092   }
1093   handle_event_count(event);
1094   if (m_deleted) {
1095     if (m_deletable) {
1096       free();
1097     } else {
1098       Debug("plugin", "INKCont Deletable but not deleted %d", m_event_count);
1099     }
1100   } else {
1101     /* set the plugin context */
1102     auto *previousContext = pluginThreadContext;
1103     pluginThreadContext   = reinterpret_cast<PluginThreadContext *>(m_context);
1104     int retval            = m_event_func((TSCont)this, (TSEvent)event, edata);
1105     pluginThreadContext   = previousContext;
1106     if (edata && event == EVENT_INTERVAL) {
1107       Event *e = reinterpret_cast<Event *>(edata);
1108       if (e->period != 0) {
1109         // In the interval case, we must re-increment the m_event_count for
1110         // the next go around.  Otherwise, our event count will go negative.
1111         ink_release_assert(ink_atomic_increment((int *)&this->m_event_count, 1) >= 0);
1112       }
1113     }
1114     return retval;
1115   }
1116   return EVENT_DONE;
1117 }
1118 
1119 ////////////////////////////////////////////////////////////////////
1120 //
1121 // INKVConnInternal
1122 //
1123 ////////////////////////////////////////////////////////////////////
1124 
1125 INKVConnInternal::INKVConnInternal() : INKContInternal(), m_read_vio(), m_write_vio(), m_output_vc(nullptr)
1126 {
1127   m_closed = 0;
1128 }
1129 
1130 INKVConnInternal::INKVConnInternal(TSEventFunc funcp, TSMutex mutexp)
1131   : INKContInternal(funcp, mutexp), m_read_vio(), m_write_vio(), m_output_vc(nullptr)
1132 {
1133   m_closed = 0;
1134 }
1135 
1136 void
1137 INKVConnInternal::clear()
1138 {
1139   m_read_vio.set_continuation(nullptr);
1140   m_write_vio.set_continuation(nullptr);
1141   INKContInternal::clear();
1142 }
1143 
1144 void
1145 INKVConnInternal::free()
1146 {
1147   clear();
1148   this->mutex.clear();
1149   m_free_magic = INKCONT_INTERN_MAGIC_DEAD;
1150   INKVConnAllocator.free(this);
1151 }
1152 
1153 void
1154 INKVConnInternal::destroy()
1155 {
1156   if (m_free_magic == INKCONT_INTERN_MAGIC_DEAD) {
1157     ink_release_assert(!"Plugin tries to use a vconnection which is deleted");
1158   }
1159 
1160   m_deleted = 1;
1161   if (m_deletable) {
1162     free();
1163   }
1164 }
1165 
1166 VIO *
1167 INKVConnInternal::do_io_read(Continuation *c, int64_t nbytes, MIOBuffer *buf)
1168 {
1169   m_read_vio.buffer.writer_for(buf);
1170   m_read_vio.op = VIO::READ;
1171   m_read_vio.set_continuation(c);
1172   m_read_vio.nbytes    = nbytes;
1173   m_read_vio.ndone     = 0;
1174   m_read_vio.vc_server = this;
1175 
1176   if (ink_atomic_increment((int *)&m_event_count, 1) < 0) {
1177     ink_assert(!"not reached");
1178   }
1179   eventProcessor.schedule_imm(this, ET_NET);
1180 
1181   return &m_read_vio;
1182 }
1183 
1184 VIO *
1185 INKVConnInternal::do_io_write(Continuation *c, int64_t nbytes, IOBufferReader *buf, bool owner)
1186 {
1187   ink_assert(!owner);
1188   m_write_vio.buffer.reader_for(buf);
1189   m_write_vio.op = VIO::WRITE;
1190   m_write_vio.set_continuation(c);
1191   m_write_vio.nbytes    = nbytes;
1192   m_write_vio.ndone     = 0;
1193   m_write_vio.vc_server = this;
1194 
1195   if (m_write_vio.buffer.reader()->read_avail() > 0) {
1196     if (ink_atomic_increment((int *)&m_event_count, 1) < 0) {
1197       ink_assert(!"not reached");
1198     }
1199     eventProcessor.schedule_imm(this, ET_NET);
1200   }
1201 
1202   return &m_write_vio;
1203 }
1204 
1205 void
1206 INKVConnInternal::do_io_transform(VConnection *vc)
1207 {
1208   m_output_vc = vc;
1209 }
1210 
1211 void
1212 INKVConnInternal::do_io_close(int error)
1213 {
1214   if (ink_atomic_increment((int *)&m_event_count, 1) < 0) {
1215     ink_assert(!"not reached");
1216   }
1217 
1218   INK_WRITE_MEMORY_BARRIER;
1219 
1220   if (error != -1) {
1221     lerrno   = error;
1222     m_closed = TS_VC_CLOSE_ABORT;
1223   } else {
1224     m_closed = TS_VC_CLOSE_NORMAL;
1225   }
1226 
1227   m_read_vio.op = VIO::NONE;
1228   m_read_vio.buffer.clear();
1229 
1230   m_write_vio.op = VIO::NONE;
1231   m_write_vio.buffer.clear();
1232 
1233   if (m_output_vc) {
1234     m_output_vc->do_io_close(error);
1235     m_output_vc = nullptr;
1236   }
1237 
1238   eventProcessor.schedule_imm(this, ET_NET);
1239 }
1240 
1241 void
1242 INKVConnInternal::do_io_shutdown(ShutdownHowTo_t howto)
1243 {
1244   if ((howto == IO_SHUTDOWN_READ) || (howto == IO_SHUTDOWN_READWRITE)) {
1245     m_read_vio.op = VIO::NONE;
1246     m_read_vio.buffer.clear();
1247   }
1248 
1249   if ((howto == IO_SHUTDOWN_WRITE) || (howto == IO_SHUTDOWN_READWRITE)) {
1250     m_write_vio.op = VIO::NONE;
1251     m_write_vio.buffer.clear();
1252   }
1253 
1254   if (ink_atomic_increment((int *)&m_event_count, 1) < 0) {
1255     ink_assert(!"not reached");
1256   }
1257   eventProcessor.schedule_imm(this, ET_NET);
1258 }
1259 
1260 void
1261 INKVConnInternal::reenable(VIO * /* vio ATS_UNUSED */)
1262 {
1263   if (ink_atomic_increment((int *)&m_event_count, 1) < 0) {
1264     ink_assert(!"not reached");
1265   }
1266   eventProcessor.schedule_imm(this, ET_NET);
1267 }
1268 
1269 void
1270 INKVConnInternal::retry(unsigned int delay)
1271 {
1272   if (ink_atomic_increment((int *)&m_event_count, 1) < 0) {
1273     ink_assert(!"not reached");
1274   }
1275   mutex->thread_holding->schedule_in(this, HRTIME_MSECONDS(delay));
1276 }
1277 
1278 bool
1279 INKVConnInternal::get_data(int id, void *data)
1280 {
1281   switch (id) {
1282   case TS_API_DATA_READ_VIO:
1283     *((TSVIO *)data) = reinterpret_cast<TSVIO>(&m_read_vio);
1284     return true;
1285   case TS_API_DATA_WRITE_VIO:
1286     *((TSVIO *)data) = reinterpret_cast<TSVIO>(&m_write_vio);
1287     return true;
1288   case TS_API_DATA_OUTPUT_VC:
1289     *((TSVConn *)data) = reinterpret_cast<TSVConn>(m_output_vc);
1290     return true;
1291   case TS_API_DATA_CLOSED:
1292     *((int *)data) = m_closed;
1293     return true;
1294   default:
1295     return INKContInternal::get_data(id, data);
1296   }
1297 }
1298 
1299 bool
1300 INKVConnInternal::set_data(int id, void *data)
1301 {
1302   switch (id) {
1303   case TS_API_DATA_OUTPUT_VC:
1304     m_output_vc = (VConnection *)data;
1305     return true;
1306   default:
1307     return INKContInternal::set_data(id, data);
1308   }
1309 }
1310 
1311 ////////////////////////////////////////////////////////////////////
1312 //
1313 // APIHook, APIHooks, HttpAPIHooks, HttpHookState
1314 //
1315 ////////////////////////////////////////////////////////////////////
1316 APIHook *
1317 APIHook::next() const
1318 {
1319   return m_link.next;
1320 }
1321 
1322 APIHook *
1323 APIHook::prev() const
1324 {
1325   return m_link.prev;
1326 }
1327 
1328 int
1329 APIHook::invoke(int event, void *edata) const
1330 {
1331   if ((event == EVENT_IMMEDIATE) || (event == EVENT_INTERVAL) || event == TS_EVENT_HTTP_TXN_CLOSE) {
1332     if (ink_atomic_increment((int *)&m_cont->m_event_count, 1) < 0) {
1333       ink_assert(!"not reached");
1334     }
1335   }
1336   MUTEX_TRY_LOCK(lock, m_cont->mutex, this_ethread());
1337   if (!lock.is_locked()) {
1338     // If we cannot get the lock, the caller needs to restructure to handle rescheduling
1339     ink_release_assert(0);
1340   }
1341   return m_cont->handleEvent(event, edata);
1342 }
1343 
1344 APIHook *
1345 APIHooks::head() const
1346 {
1347   return m_hooks.head;
1348 }
1349 
1350 void
1351 APIHooks::append(INKContInternal *cont)
1352 {
1353   APIHook *api_hook;
1354 
1355   api_hook         = apiHookAllocator.alloc();
1356   api_hook->m_cont = cont;
1357 
1358   m_hooks.enqueue(api_hook);
1359 }
1360 
1361 void
1362 APIHooks::clear()
1363 {
1364   APIHook *hook;
1365   while (nullptr != (hook = m_hooks.pop())) {
1366     apiHookAllocator.free(hook);
1367   }
1368 }
1369 
1370 HttpHookState::HttpHookState() : _id(TS_HTTP_LAST_HOOK) {}
1371 
1372 void
1373 HttpHookState::init(TSHttpHookID id, HttpAPIHooks const *global, HttpAPIHooks const *ssn, HttpAPIHooks const *txn)
1374 {
1375   _id = id;
1376 
1377   if (global) {
1378     _global.init(global, id);
1379   } else {
1380     _global.clear();
1381   }
1382 
1383   if (ssn) {
1384     _ssn.init(ssn, id);
1385   } else {
1386     _ssn.clear();
1387   }
1388 
1389   if (txn) {
1390     _txn.init(txn, id);
1391   } else {
1392     _txn.clear();
1393   }
1394 }
1395 
1396 APIHook const *
1397 HttpHookState::getNext()
1398 {
1399   APIHook const *zret = nullptr;
1400   do {
1401     APIHook const *hg   = _global.candidate();
1402     APIHook const *hssn = _ssn.candidate();
1403     APIHook const *htxn = _txn.candidate();
1404     zret                = nullptr;
1405 
1406     Debug("plugin", "computing next callback for hook %d", _id);
1407 
1408     if (hg) {
1409       zret = hg;
1410       ++_global;
1411     } else if (hssn) {
1412       zret = hssn;
1413       ++_ssn;
1414     } else if (htxn) {
1415       zret = htxn;
1416       ++_txn;
1417     }
1418   } while (zret != nullptr && !this->is_enabled());
1419 
1420   return zret;
1421 }
1422 
1423 bool
1424 HttpHookState::is_enabled()
1425 {
1426   return true;
1427 }
1428 
1429 void
1430 HttpHookState::Scope::init(HttpAPIHooks const *feature_hooks, TSHttpHookID id)
1431 {
1432   APIHooks const *hooks = (*feature_hooks)[id];
1433 
1434   _p = nullptr;
1435   _c = hooks->head();
1436 }
1437 
1438 APIHook const *
1439 HttpHookState::Scope::candidate()
1440 {
1441   /// Simply returns _c hook for now. Later will do priority checking here
1442   return _c;
1443 }
1444 
1445 void
1446 HttpHookState::Scope::operator++()
1447 {
1448   _p = _c;
1449   _c = _c->next();
1450 }
1451 
1452 void
1453 HttpHookState::Scope::clear()
1454 {
1455   _p = _c = nullptr;
1456 }
1457 
1458 ////////////////////////////////////////////////////////////////////
1459 //
1460 // ConfigUpdateCbTable
1461 //
1462 ////////////////////////////////////////////////////////////////////
1463 
1464 ConfigUpdateCbTable::ConfigUpdateCbTable() {}
1465 
1466 ConfigUpdateCbTable::~ConfigUpdateCbTable() {}
1467 
1468 void
1469 ConfigUpdateCbTable::insert(INKContInternal *contp, const char *name)
1470 {
1471   if (contp && name) {
1472     cb_table.emplace(name, contp);
1473   }
1474 }
1475 
1476 void
1477 ConfigUpdateCbTable::invoke(const char *name)
1478 {
1479   INKContInternal *contp;
1480 
1481   if (name != nullptr) {
1482     if (strcmp(name, "*") == 0) {
1483       for (auto &&it : cb_table) {
1484         contp = it.second;
1485         ink_assert(contp != nullptr);
1486         invoke(contp);
1487       }
1488     } else {
1489       if (auto it = cb_table.find(name); it != cb_table.end()) {
1490         contp = it->second;
1491         ink_assert(contp != nullptr);
1492         invoke(contp);
1493       }
1494     }
1495   }
1496 }
1497 
1498 void
1499 ConfigUpdateCbTable::invoke(INKContInternal *contp)
1500 {
1501   eventProcessor.schedule_imm(new ConfigUpdateCallback(contp), ET_TASK);
1502 }
1503 
1504 ////////////////////////////////////////////////////////////////////
1505 //
1506 // api_init
1507 //
1508 ////////////////////////////////////////////////////////////////////
1509 
1510 void
1511 api_init()
1512 {
1513   // HDR FIX ME
1514 
1515   static int init = 1;
1516 
1517   if (init) {
1518     init = 0;
1519 
1520     /* URL schemes */
1521     TS_URL_SCHEME_FILE     = URL_SCHEME_FILE;
1522     TS_URL_SCHEME_FTP      = URL_SCHEME_FTP;
1523     TS_URL_SCHEME_GOPHER   = URL_SCHEME_GOPHER;
1524     TS_URL_SCHEME_HTTP     = URL_SCHEME_HTTP;
1525     TS_URL_SCHEME_HTTPS    = URL_SCHEME_HTTPS;
1526     TS_URL_SCHEME_MAILTO   = URL_SCHEME_MAILTO;
1527     TS_URL_SCHEME_NEWS     = URL_SCHEME_NEWS;
1528     TS_URL_SCHEME_NNTP     = URL_SCHEME_NNTP;
1529     TS_URL_SCHEME_PROSPERO = URL_SCHEME_PROSPERO;
1530     TS_URL_SCHEME_TELNET   = URL_SCHEME_TELNET;
1531     TS_URL_SCHEME_WAIS     = URL_SCHEME_WAIS;
1532     TS_URL_SCHEME_WS       = URL_SCHEME_WS;
1533     TS_URL_SCHEME_WSS      = URL_SCHEME_WSS;
1534 
1535     TS_URL_LEN_FILE     = URL_LEN_FILE;
1536     TS_URL_LEN_FTP      = URL_LEN_FTP;
1537     TS_URL_LEN_GOPHER   = URL_LEN_GOPHER;
1538     TS_URL_LEN_HTTP     = URL_LEN_HTTP;
1539     TS_URL_LEN_HTTPS    = URL_LEN_HTTPS;
1540     TS_URL_LEN_MAILTO   = URL_LEN_MAILTO;
1541     TS_URL_LEN_NEWS     = URL_LEN_NEWS;
1542     TS_URL_LEN_NNTP     = URL_LEN_NNTP;
1543     TS_URL_LEN_PROSPERO = URL_LEN_PROSPERO;
1544     TS_URL_LEN_TELNET   = URL_LEN_TELNET;
1545     TS_URL_LEN_WAIS     = URL_LEN_WAIS;
1546     TS_URL_LEN_WS       = URL_LEN_WS;
1547     TS_URL_LEN_WSS      = URL_LEN_WSS;
1548 
1549     /* MIME fields */
1550     TS_MIME_FIELD_ACCEPT                    = MIME_FIELD_ACCEPT;
1551     TS_MIME_FIELD_ACCEPT_CHARSET            = MIME_FIELD_ACCEPT_CHARSET;
1552     TS_MIME_FIELD_ACCEPT_ENCODING           = MIME_FIELD_ACCEPT_ENCODING;
1553     TS_MIME_FIELD_ACCEPT_LANGUAGE           = MIME_FIELD_ACCEPT_LANGUAGE;
1554     TS_MIME_FIELD_ACCEPT_RANGES             = MIME_FIELD_ACCEPT_RANGES;
1555     TS_MIME_FIELD_AGE                       = MIME_FIELD_AGE;
1556     TS_MIME_FIELD_ALLOW                     = MIME_FIELD_ALLOW;
1557     TS_MIME_FIELD_APPROVED                  = MIME_FIELD_APPROVED;
1558     TS_MIME_FIELD_AUTHORIZATION             = MIME_FIELD_AUTHORIZATION;
1559     TS_MIME_FIELD_BYTES                     = MIME_FIELD_BYTES;
1560     TS_MIME_FIELD_CACHE_CONTROL             = MIME_FIELD_CACHE_CONTROL;
1561     TS_MIME_FIELD_CLIENT_IP                 = MIME_FIELD_CLIENT_IP;
1562     TS_MIME_FIELD_CONNECTION                = MIME_FIELD_CONNECTION;
1563     TS_MIME_FIELD_CONTENT_BASE              = MIME_FIELD_CONTENT_BASE;
1564     TS_MIME_FIELD_CONTENT_ENCODING          = MIME_FIELD_CONTENT_ENCODING;
1565     TS_MIME_FIELD_CONTENT_LANGUAGE          = MIME_FIELD_CONTENT_LANGUAGE;
1566     TS_MIME_FIELD_CONTENT_LENGTH            = MIME_FIELD_CONTENT_LENGTH;
1567     TS_MIME_FIELD_CONTENT_LOCATION          = MIME_FIELD_CONTENT_LOCATION;
1568     TS_MIME_FIELD_CONTENT_MD5               = MIME_FIELD_CONTENT_MD5;
1569     TS_MIME_FIELD_CONTENT_RANGE             = MIME_FIELD_CONTENT_RANGE;
1570     TS_MIME_FIELD_CONTENT_TYPE              = MIME_FIELD_CONTENT_TYPE;
1571     TS_MIME_FIELD_CONTROL                   = MIME_FIELD_CONTROL;
1572     TS_MIME_FIELD_COOKIE                    = MIME_FIELD_COOKIE;
1573     TS_MIME_FIELD_DATE                      = MIME_FIELD_DATE;
1574     TS_MIME_FIELD_DISTRIBUTION              = MIME_FIELD_DISTRIBUTION;
1575     TS_MIME_FIELD_ETAG                      = MIME_FIELD_ETAG;
1576     TS_MIME_FIELD_EXPECT                    = MIME_FIELD_EXPECT;
1577     TS_MIME_FIELD_EXPIRES                   = MIME_FIELD_EXPIRES;
1578     TS_MIME_FIELD_FOLLOWUP_TO               = MIME_FIELD_FOLLOWUP_TO;
1579     TS_MIME_FIELD_FROM                      = MIME_FIELD_FROM;
1580     TS_MIME_FIELD_HOST                      = MIME_FIELD_HOST;
1581     TS_MIME_FIELD_IF_MATCH                  = MIME_FIELD_IF_MATCH;
1582     TS_MIME_FIELD_IF_MODIFIED_SINCE         = MIME_FIELD_IF_MODIFIED_SINCE;
1583     TS_MIME_FIELD_IF_NONE_MATCH             = MIME_FIELD_IF_NONE_MATCH;
1584     TS_MIME_FIELD_IF_RANGE                  = MIME_FIELD_IF_RANGE;
1585     TS_MIME_FIELD_IF_UNMODIFIED_SINCE       = MIME_FIELD_IF_UNMODIFIED_SINCE;
1586     TS_MIME_FIELD_KEEP_ALIVE                = MIME_FIELD_KEEP_ALIVE;
1587     TS_MIME_FIELD_KEYWORDS                  = MIME_FIELD_KEYWORDS;
1588     TS_MIME_FIELD_LAST_MODIFIED             = MIME_FIELD_LAST_MODIFIED;
1589     TS_MIME_FIELD_LINES                     = MIME_FIELD_LINES;
1590     TS_MIME_FIELD_LOCATION                  = MIME_FIELD_LOCATION;
1591     TS_MIME_FIELD_MAX_FORWARDS              = MIME_FIELD_MAX_FORWARDS;
1592     TS_MIME_FIELD_MESSAGE_ID                = MIME_FIELD_MESSAGE_ID;
1593     TS_MIME_FIELD_NEWSGROUPS                = MIME_FIELD_NEWSGROUPS;
1594     TS_MIME_FIELD_ORGANIZATION              = MIME_FIELD_ORGANIZATION;
1595     TS_MIME_FIELD_PATH                      = MIME_FIELD_PATH;
1596     TS_MIME_FIELD_PRAGMA                    = MIME_FIELD_PRAGMA;
1597     TS_MIME_FIELD_PROXY_AUTHENTICATE        = MIME_FIELD_PROXY_AUTHENTICATE;
1598     TS_MIME_FIELD_PROXY_AUTHORIZATION       = MIME_FIELD_PROXY_AUTHORIZATION;
1599     TS_MIME_FIELD_PROXY_CONNECTION          = MIME_FIELD_PROXY_CONNECTION;
1600     TS_MIME_FIELD_PUBLIC                    = MIME_FIELD_PUBLIC;
1601     TS_MIME_FIELD_RANGE                     = MIME_FIELD_RANGE;
1602     TS_MIME_FIELD_REFERENCES                = MIME_FIELD_REFERENCES;
1603     TS_MIME_FIELD_REFERER                   = MIME_FIELD_REFERER;
1604     TS_MIME_FIELD_REPLY_TO                  = MIME_FIELD_REPLY_TO;
1605     TS_MIME_FIELD_RETRY_AFTER               = MIME_FIELD_RETRY_AFTER;
1606     TS_MIME_FIELD_SENDER                    = MIME_FIELD_SENDER;
1607     TS_MIME_FIELD_SERVER                    = MIME_FIELD_SERVER;
1608     TS_MIME_FIELD_SET_COOKIE                = MIME_FIELD_SET_COOKIE;
1609     TS_MIME_FIELD_STRICT_TRANSPORT_SECURITY = MIME_FIELD_STRICT_TRANSPORT_SECURITY;
1610     TS_MIME_FIELD_SUBJECT                   = MIME_FIELD_SUBJECT;
1611     TS_MIME_FIELD_SUMMARY                   = MIME_FIELD_SUMMARY;
1612     TS_MIME_FIELD_TE                        = MIME_FIELD_TE;
1613     TS_MIME_FIELD_TRANSFER_ENCODING         = MIME_FIELD_TRANSFER_ENCODING;
1614     TS_MIME_FIELD_UPGRADE                   = MIME_FIELD_UPGRADE;
1615     TS_MIME_FIELD_USER_AGENT                = MIME_FIELD_USER_AGENT;
1616     TS_MIME_FIELD_VARY                      = MIME_FIELD_VARY;
1617     TS_MIME_FIELD_VIA                       = MIME_FIELD_VIA;
1618     TS_MIME_FIELD_WARNING                   = MIME_FIELD_WARNING;
1619     TS_MIME_FIELD_WWW_AUTHENTICATE          = MIME_FIELD_WWW_AUTHENTICATE;
1620     TS_MIME_FIELD_XREF                      = MIME_FIELD_XREF;
1621     TS_MIME_FIELD_X_FORWARDED_FOR           = MIME_FIELD_X_FORWARDED_FOR;
1622     TS_MIME_FIELD_FORWARDED                 = MIME_FIELD_FORWARDED;
1623 
1624     TS_MIME_LEN_ACCEPT                    = MIME_LEN_ACCEPT;
1625     TS_MIME_LEN_ACCEPT_CHARSET            = MIME_LEN_ACCEPT_CHARSET;
1626     TS_MIME_LEN_ACCEPT_ENCODING           = MIME_LEN_ACCEPT_ENCODING;
1627     TS_MIME_LEN_ACCEPT_LANGUAGE           = MIME_LEN_ACCEPT_LANGUAGE;
1628     TS_MIME_LEN_ACCEPT_RANGES             = MIME_LEN_ACCEPT_RANGES;
1629     TS_MIME_LEN_AGE                       = MIME_LEN_AGE;
1630     TS_MIME_LEN_ALLOW                     = MIME_LEN_ALLOW;
1631     TS_MIME_LEN_APPROVED                  = MIME_LEN_APPROVED;
1632     TS_MIME_LEN_AUTHORIZATION             = MIME_LEN_AUTHORIZATION;
1633     TS_MIME_LEN_BYTES                     = MIME_LEN_BYTES;
1634     TS_MIME_LEN_CACHE_CONTROL             = MIME_LEN_CACHE_CONTROL;
1635     TS_MIME_LEN_CLIENT_IP                 = MIME_LEN_CLIENT_IP;
1636     TS_MIME_LEN_CONNECTION                = MIME_LEN_CONNECTION;
1637     TS_MIME_LEN_CONTENT_BASE              = MIME_LEN_CONTENT_BASE;
1638     TS_MIME_LEN_CONTENT_ENCODING          = MIME_LEN_CONTENT_ENCODING;
1639     TS_MIME_LEN_CONTENT_LANGUAGE          = MIME_LEN_CONTENT_LANGUAGE;
1640     TS_MIME_LEN_CONTENT_LENGTH            = MIME_LEN_CONTENT_LENGTH;
1641     TS_MIME_LEN_CONTENT_LOCATION          = MIME_LEN_CONTENT_LOCATION;
1642     TS_MIME_LEN_CONTENT_MD5               = MIME_LEN_CONTENT_MD5;
1643     TS_MIME_LEN_CONTENT_RANGE             = MIME_LEN_CONTENT_RANGE;
1644     TS_MIME_LEN_CONTENT_TYPE              = MIME_LEN_CONTENT_TYPE;
1645     TS_MIME_LEN_CONTROL                   = MIME_LEN_CONTROL;
1646     TS_MIME_LEN_COOKIE                    = MIME_LEN_COOKIE;
1647     TS_MIME_LEN_DATE                      = MIME_LEN_DATE;
1648     TS_MIME_LEN_DISTRIBUTION              = MIME_LEN_DISTRIBUTION;
1649     TS_MIME_LEN_ETAG                      = MIME_LEN_ETAG;
1650     TS_MIME_LEN_EXPECT                    = MIME_LEN_EXPECT;
1651     TS_MIME_LEN_EXPIRES                   = MIME_LEN_EXPIRES;
1652     TS_MIME_LEN_FOLLOWUP_TO               = MIME_LEN_FOLLOWUP_TO;
1653     TS_MIME_LEN_FROM                      = MIME_LEN_FROM;
1654     TS_MIME_LEN_HOST                      = MIME_LEN_HOST;
1655     TS_MIME_LEN_IF_MATCH                  = MIME_LEN_IF_MATCH;
1656     TS_MIME_LEN_IF_MODIFIED_SINCE         = MIME_LEN_IF_MODIFIED_SINCE;
1657     TS_MIME_LEN_IF_NONE_MATCH             = MIME_LEN_IF_NONE_MATCH;
1658     TS_MIME_LEN_IF_RANGE                  = MIME_LEN_IF_RANGE;
1659     TS_MIME_LEN_IF_UNMODIFIED_SINCE       = MIME_LEN_IF_UNMODIFIED_SINCE;
1660     TS_MIME_LEN_KEEP_ALIVE                = MIME_LEN_KEEP_ALIVE;
1661     TS_MIME_LEN_KEYWORDS                  = MIME_LEN_KEYWORDS;
1662     TS_MIME_LEN_LAST_MODIFIED             = MIME_LEN_LAST_MODIFIED;
1663     TS_MIME_LEN_LINES                     = MIME_LEN_LINES;
1664     TS_MIME_LEN_LOCATION                  = MIME_LEN_LOCATION;
1665     TS_MIME_LEN_MAX_FORWARDS              = MIME_LEN_MAX_FORWARDS;
1666     TS_MIME_LEN_MESSAGE_ID                = MIME_LEN_MESSAGE_ID;
1667     TS_MIME_LEN_NEWSGROUPS                = MIME_LEN_NEWSGROUPS;
1668     TS_MIME_LEN_ORGANIZATION              = MIME_LEN_ORGANIZATION;
1669     TS_MIME_LEN_PATH                      = MIME_LEN_PATH;
1670     TS_MIME_LEN_PRAGMA                    = MIME_LEN_PRAGMA;
1671     TS_MIME_LEN_PROXY_AUTHENTICATE        = MIME_LEN_PROXY_AUTHENTICATE;
1672     TS_MIME_LEN_PROXY_AUTHORIZATION       = MIME_LEN_PROXY_AUTHORIZATION;
1673     TS_MIME_LEN_PROXY_CONNECTION          = MIME_LEN_PROXY_CONNECTION;
1674     TS_MIME_LEN_PUBLIC                    = MIME_LEN_PUBLIC;
1675     TS_MIME_LEN_RANGE                     = MIME_LEN_RANGE;
1676     TS_MIME_LEN_REFERENCES                = MIME_LEN_REFERENCES;
1677     TS_MIME_LEN_REFERER                   = MIME_LEN_REFERER;
1678     TS_MIME_LEN_REPLY_TO                  = MIME_LEN_REPLY_TO;
1679     TS_MIME_LEN_RETRY_AFTER               = MIME_LEN_RETRY_AFTER;
1680     TS_MIME_LEN_SENDER                    = MIME_LEN_SENDER;
1681     TS_MIME_LEN_SERVER                    = MIME_LEN_SERVER;
1682     TS_MIME_LEN_SET_COOKIE                = MIME_LEN_SET_COOKIE;
1683     TS_MIME_LEN_STRICT_TRANSPORT_SECURITY = MIME_LEN_STRICT_TRANSPORT_SECURITY;
1684     TS_MIME_LEN_SUBJECT                   = MIME_LEN_SUBJECT;
1685     TS_MIME_LEN_SUMMARY                   = MIME_LEN_SUMMARY;
1686     TS_MIME_LEN_TE                        = MIME_LEN_TE;
1687     TS_MIME_LEN_TRANSFER_ENCODING         = MIME_LEN_TRANSFER_ENCODING;
1688     TS_MIME_LEN_UPGRADE                   = MIME_LEN_UPGRADE;
1689     TS_MIME_LEN_USER_AGENT                = MIME_LEN_USER_AGENT;
1690     TS_MIME_LEN_VARY                      = MIME_LEN_VARY;
1691     TS_MIME_LEN_VIA                       = MIME_LEN_VIA;
1692     TS_MIME_LEN_WARNING                   = MIME_LEN_WARNING;
1693     TS_MIME_LEN_WWW_AUTHENTICATE          = MIME_LEN_WWW_AUTHENTICATE;
1694     TS_MIME_LEN_XREF                      = MIME_LEN_XREF;
1695     TS_MIME_LEN_X_FORWARDED_FOR           = MIME_LEN_X_FORWARDED_FOR;
1696     TS_MIME_LEN_FORWARDED                 = MIME_LEN_FORWARDED;
1697 
1698     /* HTTP methods */
1699     TS_HTTP_METHOD_CONNECT = HTTP_METHOD_CONNECT;
1700     TS_HTTP_METHOD_DELETE  = HTTP_METHOD_DELETE;
1701     TS_HTTP_METHOD_GET     = HTTP_METHOD_GET;
1702     TS_HTTP_METHOD_HEAD    = HTTP_METHOD_HEAD;
1703     TS_HTTP_METHOD_OPTIONS = HTTP_METHOD_OPTIONS;
1704     TS_HTTP_METHOD_POST    = HTTP_METHOD_POST;
1705     TS_HTTP_METHOD_PURGE   = HTTP_METHOD_PURGE;
1706     TS_HTTP_METHOD_PUT     = HTTP_METHOD_PUT;
1707     TS_HTTP_METHOD_TRACE   = HTTP_METHOD_TRACE;
1708     TS_HTTP_METHOD_PUSH    = HTTP_METHOD_PUSH;
1709 
1710     TS_HTTP_LEN_CONNECT = HTTP_LEN_CONNECT;
1711     TS_HTTP_LEN_DELETE  = HTTP_LEN_DELETE;
1712     TS_HTTP_LEN_GET     = HTTP_LEN_GET;
1713     TS_HTTP_LEN_HEAD    = HTTP_LEN_HEAD;
1714     TS_HTTP_LEN_OPTIONS = HTTP_LEN_OPTIONS;
1715     TS_HTTP_LEN_POST    = HTTP_LEN_POST;
1716     TS_HTTP_LEN_PURGE   = HTTP_LEN_PURGE;
1717     TS_HTTP_LEN_PUT     = HTTP_LEN_PUT;
1718     TS_HTTP_LEN_TRACE   = HTTP_LEN_TRACE;
1719     TS_HTTP_LEN_PUSH    = HTTP_LEN_PUSH;
1720 
1721     /* HTTP miscellaneous values */
1722     TS_HTTP_VALUE_BYTES            = HTTP_VALUE_BYTES;
1723     TS_HTTP_VALUE_CHUNKED          = HTTP_VALUE_CHUNKED;
1724     TS_HTTP_VALUE_CLOSE            = HTTP_VALUE_CLOSE;
1725     TS_HTTP_VALUE_COMPRESS         = HTTP_VALUE_COMPRESS;
1726     TS_HTTP_VALUE_DEFLATE          = HTTP_VALUE_DEFLATE;
1727     TS_HTTP_VALUE_GZIP             = HTTP_VALUE_GZIP;
1728     TS_HTTP_VALUE_IDENTITY         = HTTP_VALUE_IDENTITY;
1729     TS_HTTP_VALUE_KEEP_ALIVE       = HTTP_VALUE_KEEP_ALIVE;
1730     TS_HTTP_VALUE_MAX_AGE          = HTTP_VALUE_MAX_AGE;
1731     TS_HTTP_VALUE_MAX_STALE        = HTTP_VALUE_MAX_STALE;
1732     TS_HTTP_VALUE_MIN_FRESH        = HTTP_VALUE_MIN_FRESH;
1733     TS_HTTP_VALUE_MUST_REVALIDATE  = HTTP_VALUE_MUST_REVALIDATE;
1734     TS_HTTP_VALUE_NONE             = HTTP_VALUE_NONE;
1735     TS_HTTP_VALUE_NO_CACHE         = HTTP_VALUE_NO_CACHE;
1736     TS_HTTP_VALUE_NO_STORE         = HTTP_VALUE_NO_STORE;
1737     TS_HTTP_VALUE_NO_TRANSFORM     = HTTP_VALUE_NO_TRANSFORM;
1738     TS_HTTP_VALUE_ONLY_IF_CACHED   = HTTP_VALUE_ONLY_IF_CACHED;
1739     TS_HTTP_VALUE_PRIVATE          = HTTP_VALUE_PRIVATE;
1740     TS_HTTP_VALUE_PROXY_REVALIDATE = HTTP_VALUE_PROXY_REVALIDATE;
1741     TS_HTTP_VALUE_PUBLIC           = HTTP_VALUE_PUBLIC;
1742     TS_HTTP_VALUE_S_MAXAGE         = HTTP_VALUE_S_MAXAGE;
1743 
1744     TS_HTTP_LEN_BYTES            = HTTP_LEN_BYTES;
1745     TS_HTTP_LEN_CHUNKED          = HTTP_LEN_CHUNKED;
1746     TS_HTTP_LEN_CLOSE            = HTTP_LEN_CLOSE;
1747     TS_HTTP_LEN_COMPRESS         = HTTP_LEN_COMPRESS;
1748     TS_HTTP_LEN_DEFLATE          = HTTP_LEN_DEFLATE;
1749     TS_HTTP_LEN_GZIP             = HTTP_LEN_GZIP;
1750     TS_HTTP_LEN_IDENTITY         = HTTP_LEN_IDENTITY;
1751     TS_HTTP_LEN_KEEP_ALIVE       = HTTP_LEN_KEEP_ALIVE;
1752     TS_HTTP_LEN_MAX_AGE          = HTTP_LEN_MAX_AGE;
1753     TS_HTTP_LEN_MAX_STALE        = HTTP_LEN_MAX_STALE;
1754     TS_HTTP_LEN_MIN_FRESH        = HTTP_LEN_MIN_FRESH;
1755     TS_HTTP_LEN_MUST_REVALIDATE  = HTTP_LEN_MUST_REVALIDATE;
1756     TS_HTTP_LEN_NONE             = HTTP_LEN_NONE;
1757     TS_HTTP_LEN_NO_CACHE         = HTTP_LEN_NO_CACHE;
1758     TS_HTTP_LEN_NO_STORE         = HTTP_LEN_NO_STORE;
1759     TS_HTTP_LEN_NO_TRANSFORM     = HTTP_LEN_NO_TRANSFORM;
1760     TS_HTTP_LEN_ONLY_IF_CACHED   = HTTP_LEN_ONLY_IF_CACHED;
1761     TS_HTTP_LEN_PRIVATE          = HTTP_LEN_PRIVATE;
1762     TS_HTTP_LEN_PROXY_REVALIDATE = HTTP_LEN_PROXY_REVALIDATE;
1763     TS_HTTP_LEN_PUBLIC           = HTTP_LEN_PUBLIC;
1764     TS_HTTP_LEN_S_MAXAGE         = HTTP_LEN_S_MAXAGE;
1765 
1766     http_global_hooks = new HttpAPIHooks;
1767     ssl_hooks         = new SslAPIHooks;
1768     lifecycle_hooks   = new LifecycleAPIHooks;
1769     global_config_cbs = new ConfigUpdateCbTable;
1770 
1771     int api_metrics = max_records_entries - REC_INTERNAL_RECORDS;
1772     if (api_metrics > 0) {
1773       api_rsb = RecAllocateRawStatBlock(api_metrics);
1774       if (nullptr == api_rsb) {
1775         Warning("Can't allocate API stats block");
1776       } else {
1777         Debug("sdk", "initialized SDK stats APIs with %d slots", api_metrics);
1778       }
1779     } else {
1780       api_rsb = nullptr;
1781     }
1782 
1783     // Setup the version string for returning to plugins
1784     ink_strlcpy(traffic_server_version, appVersionInfo.VersionStr, sizeof(traffic_server_version));
1785     // Extract the elements.
1786     // coverity[secure_coding]
1787     if (sscanf(traffic_server_version, "%d.%d.%d", &ts_major_version, &ts_minor_version, &ts_patch_version) != 3) {
1788       Warning("Unable to parse traffic server version string '%s'\n", traffic_server_version);
1789     }
1790   }
1791 }
1792 
1793 ////////////////////////////////////////////////////////////////////
1794 //
1795 // API memory management
1796 //
1797 ////////////////////////////////////////////////////////////////////
1798 
1799 void *
1800 _TSmalloc(size_t size, const char * /* path ATS_UNUSED */)
1801 {
1802   return ats_malloc(size);
1803 }
1804 
1805 void *
1806 _TSrealloc(void *ptr, size_t size, const char * /* path ATS_UNUSED */)
1807 {
1808   return ats_realloc(ptr, size);
1809 }
1810 
1811 // length has to be int64_t and not size_t, since -1 means to call strlen() to get length
1812 char *
1813 _TSstrdup(const char *str, int64_t length, const char *path)
1814 {
1815   return _xstrdup(str, length, path);
1816 }
1817 
1818 size_t
1819 _TSstrlcpy(char *dst, const char *str, size_t siz)
1820 {
1821   return ink_strlcpy(dst, str, siz);
1822 }
1823 
1824 size_t
1825 _TSstrlcat(char *dst, const char *str, size_t siz)
1826 {
1827   return ink_strlcat(dst, str, siz);
1828 }
1829 
1830 void
1831 _TSfree(void *ptr)
1832 {
1833   ats_free(ptr);
1834 }
1835 
1836 ////////////////////////////////////////////////////////////////////
1837 //
1838 // Encoding utility
1839 //
1840 ////////////////////////////////////////////////////////////////////
1841 TSReturnCode
1842 TSBase64Decode(const char *str, size_t str_len, unsigned char *dst, size_t dst_size, size_t *length)
1843 {
1844   sdk_assert(sdk_sanity_check_null_ptr((void *)str) == TS_SUCCESS);
1845   sdk_assert(sdk_sanity_check_null_ptr((void *)dst) == TS_SUCCESS);
1846 
1847   return ats_base64_decode(str, str_len, dst, dst_size, length) ? TS_SUCCESS : TS_ERROR;
1848 }
1849 
1850 TSReturnCode
1851 TSBase64Encode(const char *str, size_t str_len, char *dst, size_t dst_size, size_t *length)
1852 {
1853   sdk_assert(sdk_sanity_check_null_ptr((void *)str) == TS_SUCCESS);
1854   sdk_assert(sdk_sanity_check_null_ptr((void *)dst) == TS_SUCCESS);
1855 
1856   return ats_base64_encode(str, str_len, dst, dst_size, length) ? TS_SUCCESS : TS_ERROR;
1857 }
1858 
1859 ////////////////////////////////////////////////////////////////////
1860 //
1861 // API utility routines
1862 //
1863 ////////////////////////////////////////////////////////////////////
1864 
1865 unsigned int
1866 TSrandom()
1867 {
1868   return this_ethread()->generator.random();
1869 }
1870 
1871 double
1872 TSdrandom()
1873 {
1874   return this_ethread()->generator.drandom();
1875 }
1876 
1877 ink_hrtime
1878 TShrtime()
1879 {
1880   return Thread::get_hrtime();
1881 }
1882 
1883 ////////////////////////////////////////////////////////////////////
1884 //
1885 // API install and plugin locations
1886 //
1887 ////////////////////////////////////////////////////////////////////
1888 
1889 const char *
1890 TSInstallDirGet()
1891 {
1892   static std::string prefix = Layout::get()->prefix;
1893   return prefix.c_str();
1894 }
1895 
1896 const char *
1897 TSConfigDirGet()
1898 {
1899   static std::string sysconfdir = RecConfigReadConfigDir();
1900   return sysconfdir.c_str();
1901 }
1902 
1903 const char *
1904 TSRuntimeDirGet()
1905 {
1906   static std::string runtimedir = RecConfigReadRuntimeDir();
1907   return runtimedir.c_str();
1908 }
1909 
1910 const char *
1911 TSTrafficServerVersionGet()
1912 {
1913   return traffic_server_version;
1914 }
1915 
1916 int
1917 TSTrafficServerVersionGetMajor()
1918 {
1919   return ts_major_version;
1920 }
1921 int
1922 TSTrafficServerVersionGetMinor()
1923 {
1924   return ts_minor_version;
1925 }
1926 int
1927 TSTrafficServerVersionGetPatch()
1928 {
1929   return ts_patch_version;
1930 }
1931 
1932 const char *
1933 TSPluginDirGet()
1934 {
1935   static std::string path = RecConfigReadPluginDir();
1936   return path.c_str();
1937 }
1938 
1939 ////////////////////////////////////////////////////////////////////
1940 //
1941 // Plugin registration
1942 //
1943 ////////////////////////////////////////////////////////////////////
1944 
1945 TSReturnCode
1946 TSPluginRegister(const TSPluginRegistrationInfo *plugin_info)
1947 {
1948   sdk_assert(sdk_sanity_check_null_ptr((void *)plugin_info) == TS_SUCCESS);
1949 
1950   if (!plugin_reg_current) {
1951     return TS_ERROR;
1952   }
1953 
1954   plugin_reg_current->plugin_registered = true;
1955 
1956   if (plugin_info->plugin_name) {
1957     plugin_reg_current->plugin_name = ats_strdup(plugin_info->plugin_name);
1958   }
1959 
1960   if (plugin_info->vendor_name) {
1961     plugin_reg_current->vendor_name = ats_strdup(plugin_info->vendor_name);
1962   }
1963 
1964   if (plugin_info->support_email) {
1965     plugin_reg_current->support_email = ats_strdup(plugin_info->support_email);
1966   }
1967 
1968   return TS_SUCCESS;
1969 }
1970 
1971 ////////////////////////////////////////////////////////////////////
1972 //
1973 // API file management
1974 //
1975 ////////////////////////////////////////////////////////////////////
1976 
1977 TSFile
1978 TSfopen(const char *filename, const char *mode)
1979 {
1980   FileImpl *file;
1981 
1982   file = new FileImpl;
1983   if (!file->fopen(filename, mode)) {
1984     delete file;
1985     return nullptr;
1986   }
1987 
1988   return (TSFile)file;
1989 }
1990 
1991 void
1992 TSfclose(TSFile filep)
1993 {
1994   FileImpl *file = (FileImpl *)filep;
1995   file->fclose();
1996   delete file;
1997 }
1998 
1999 ssize_t
2000 TSfread(TSFile filep, void *buf, size_t length)
2001 {
2002   FileImpl *file = (FileImpl *)filep;
2003   return file->fread(buf, length);
2004 }
2005 
2006 ssize_t
2007 TSfwrite(TSFile filep, const void *buf, size_t length)
2008 {
2009   FileImpl *file = (FileImpl *)filep;
2010   return file->fwrite(buf, length);
2011 }
2012 
2013 void
2014 TSfflush(TSFile filep)
2015 {
2016   FileImpl *file = (FileImpl *)filep;
2017   file->fflush();
2018 }
2019 
2020 char *
2021 TSfgets(TSFile filep, char *buf, size_t length)
2022 {
2023   FileImpl *file = (FileImpl *)filep;
2024   return file->fgets(buf, length);
2025 }
2026 
2027 ////////////////////////////////////////////////////////////////////
2028 //
2029 // Header component object handles
2030 //
2031 ////////////////////////////////////////////////////////////////////
2032 
2033 TSReturnCode
2034 TSHandleMLocRelease(TSMBuffer bufp, TSMLoc parent, TSMLoc mloc)
2035 {
2036   MIMEFieldSDKHandle *field_handle;
2037   HdrHeapObjImpl *obj = (HdrHeapObjImpl *)mloc;
2038 
2039   if (mloc == TS_NULL_MLOC) {
2040     return TS_SUCCESS;
2041   }
2042 
2043   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2044 
2045   switch (obj->m_type) {
2046   case HDR_HEAP_OBJ_URL:
2047   case HDR_HEAP_OBJ_HTTP_HEADER:
2048   case HDR_HEAP_OBJ_MIME_HEADER:
2049     return TS_SUCCESS;
2050 
2051   case HDR_HEAP_OBJ_FIELD_SDK_HANDLE:
2052     field_handle = (MIMEFieldSDKHandle *)obj;
2053     if (sdk_sanity_check_field_handle(mloc, parent) != TS_SUCCESS) {
2054       return TS_ERROR;
2055     }
2056 
2057     sdk_free_field_handle(bufp, field_handle);
2058     return TS_SUCCESS;
2059 
2060   default:
2061     ink_release_assert(!"invalid mloc");
2062     return TS_ERROR;
2063   }
2064 }
2065 
2066 ////////////////////////////////////////////////////////////////////
2067 //
2068 // HdrHeaps (previously known as "Marshal Buffers")
2069 //
2070 ////////////////////////////////////////////////////////////////////
2071 
2072 // TSMBuffer: pointers to HdrHeapSDKHandle objects
2073 
2074 TSMBuffer
2075 TSMBufferCreate()
2076 {
2077   TSMBuffer bufp;
2078   HdrHeapSDKHandle *new_heap = new HdrHeapSDKHandle;
2079 
2080   new_heap->m_heap = new_HdrHeap();
2081   bufp             = (TSMBuffer)new_heap;
2082   // TODO: Should remove this when memory allocation is guaranteed to fail.
2083   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2084   return bufp;
2085 }
2086 
2087 TSReturnCode
2088 TSMBufferDestroy(TSMBuffer bufp)
2089 {
2090   // Allow to modify the buffer only
2091   // if bufp is modifiable. If bufp is not modifiable return
2092   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
2093   // return value of function from void to TSReturnCode.
2094   if (!isWriteable(bufp)) {
2095     return TS_ERROR;
2096   }
2097 
2098   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2099   HdrHeapSDKHandle *sdk_heap = (HdrHeapSDKHandle *)bufp;
2100   sdk_heap->m_heap->destroy();
2101   delete sdk_heap;
2102   return TS_SUCCESS;
2103 }
2104 
2105 ////////////////////////////////////////////////////////////////////
2106 //
2107 // URLs
2108 //
2109 ////////////////////////////////////////////////////////////////////
2110 
2111 // TSMBuffer: pointers to HdrHeapSDKHandle objects
2112 // TSMLoc:    pointers to URLImpl objects
2113 TSReturnCode
2114 TSUrlCreate(TSMBuffer bufp, TSMLoc *locp)
2115 {
2116   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2117   sdk_assert(sdk_sanity_check_null_ptr(locp) == TS_SUCCESS);
2118 
2119   if (isWriteable(bufp)) {
2120     HdrHeap *heap = ((HdrHeapSDKHandle *)bufp)->m_heap;
2121     *locp         = (TSMLoc)url_create(heap);
2122     return TS_SUCCESS;
2123   }
2124   return TS_ERROR;
2125 }
2126 
2127 TSReturnCode
2128 TSUrlClone(TSMBuffer dest_bufp, TSMBuffer src_bufp, TSMLoc src_url, TSMLoc *locp)
2129 {
2130   sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
2131   sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
2132   sdk_assert(sdk_sanity_check_url_handle(src_url) == TS_SUCCESS);
2133   sdk_assert(sdk_sanity_check_null_ptr(locp) == TS_SUCCESS);
2134 
2135   if (!isWriteable(dest_bufp)) {
2136     return TS_ERROR;
2137   }
2138 
2139   HdrHeap *s_heap, *d_heap;
2140   URLImpl *s_url, *d_url;
2141 
2142   s_heap = ((HdrHeapSDKHandle *)src_bufp)->m_heap;
2143   d_heap = ((HdrHeapSDKHandle *)dest_bufp)->m_heap;
2144   s_url  = (URLImpl *)src_url;
2145 
2146   d_url = url_copy(s_url, s_heap, d_heap, (s_heap != d_heap));
2147   *locp = (TSMLoc)d_url;
2148   return TS_SUCCESS;
2149 }
2150 
2151 TSReturnCode
2152 TSUrlCopy(TSMBuffer dest_bufp, TSMLoc dest_obj, TSMBuffer src_bufp, TSMLoc src_obj)
2153 {
2154   sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
2155   sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
2156   sdk_assert(sdk_sanity_check_url_handle(src_obj) == TS_SUCCESS);
2157   sdk_assert(sdk_sanity_check_url_handle(dest_obj) == TS_SUCCESS);
2158 
2159   if (!isWriteable(dest_bufp)) {
2160     return TS_ERROR;
2161   }
2162 
2163   HdrHeap *s_heap, *d_heap;
2164   URLImpl *s_url, *d_url;
2165 
2166   s_heap = ((HdrHeapSDKHandle *)src_bufp)->m_heap;
2167   d_heap = ((HdrHeapSDKHandle *)dest_bufp)->m_heap;
2168   s_url  = (URLImpl *)src_obj;
2169   d_url  = (URLImpl *)dest_obj;
2170 
2171   url_copy_onto(s_url, s_heap, d_url, d_heap, (s_heap != d_heap));
2172   return TS_SUCCESS;
2173 }
2174 
2175 void
2176 TSUrlPrint(TSMBuffer bufp, TSMLoc obj, TSIOBuffer iobufp)
2177 {
2178   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2179   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
2180   sdk_assert(sdk_sanity_check_iocore_structure(iobufp) == TS_SUCCESS);
2181 
2182   MIOBuffer *b = (MIOBuffer *)iobufp;
2183   IOBufferBlock *blk;
2184   int bufindex;
2185   int tmp, dumpoffset;
2186   int done;
2187   URL u;
2188 
2189   u.m_heap     = ((HdrHeapSDKHandle *)bufp)->m_heap;
2190   u.m_url_impl = (URLImpl *)obj;
2191   dumpoffset   = 0;
2192 
2193   do {
2194     blk = b->get_current_block();
2195     if (!blk || blk->write_avail() == 0) {
2196       b->add_block();
2197       blk = b->get_current_block();
2198     }
2199 
2200     bufindex = 0;
2201     tmp      = dumpoffset;
2202 
2203     done = u.print(blk->end(), blk->write_avail(), &bufindex, &tmp);
2204 
2205     dumpoffset += bufindex;
2206     b->fill(bufindex);
2207   } while (!done);
2208 }
2209 
2210 TSParseResult
2211 TSUrlParse(TSMBuffer bufp, TSMLoc obj, const char **start, const char *end)
2212 {
2213   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2214   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
2215   sdk_assert(sdk_sanity_check_null_ptr((void *)start) == TS_SUCCESS);
2216   sdk_assert(sdk_sanity_check_null_ptr((void *)*start) == TS_SUCCESS);
2217   sdk_assert(sdk_sanity_check_null_ptr((void *)end) == TS_SUCCESS);
2218 
2219   if (!isWriteable(bufp)) {
2220     return TS_PARSE_ERROR;
2221   }
2222 
2223   URL u;
2224   u.m_heap     = ((HdrHeapSDKHandle *)bufp)->m_heap;
2225   u.m_url_impl = (URLImpl *)obj;
2226   url_clear(u.m_url_impl);
2227   return (TSParseResult)u.parse(start, end);
2228 }
2229 
2230 int
2231 TSUrlLengthGet(TSMBuffer bufp, TSMLoc obj)
2232 {
2233   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2234   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
2235 
2236   URLImpl *url_impl = (URLImpl *)obj;
2237   return url_length_get(url_impl);
2238 }
2239 
2240 char *
2241 TSUrlStringGet(TSMBuffer bufp, TSMLoc obj, int *length)
2242 {
2243   // bufp is not actually used anymore, so it can be null.
2244   if (bufp) {
2245     sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2246   }
2247   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
2248   sdk_assert(sdk_sanity_check_null_ptr((void *)length) == TS_SUCCESS);
2249 
2250   URLImpl *url_impl = (URLImpl *)obj;
2251   return url_string_get(url_impl, nullptr, length, nullptr);
2252 }
2253 
2254 using URLPartGetF = const char *(URL::*)(int *);
2255 using URLPartSetF = void (URL::*)(const char *, int);
2256 
2257 static const char *
2258 URLPartGet(TSMBuffer bufp, TSMLoc obj, int *length, URLPartGetF url_f)
2259 {
2260   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2261   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
2262   sdk_assert(sdk_sanity_check_null_ptr((void *)length) == TS_SUCCESS);
2263 
2264   URL u;
2265 
2266   u.m_heap     = ((HdrHeapSDKHandle *)bufp)->m_heap;
2267   u.m_url_impl = (URLImpl *)obj;
2268 
2269   return (u.*url_f)(length);
2270 }
2271 
2272 static TSReturnCode
2273 URLPartSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length, URLPartSetF url_f)
2274 {
2275   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2276   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
2277 
2278   if (!isWriteable(bufp)) {
2279     return TS_ERROR;
2280   }
2281 
2282   URL u;
2283   u.m_heap     = ((HdrHeapSDKHandle *)bufp)->m_heap;
2284   u.m_url_impl = (URLImpl *)obj;
2285 
2286   if (!value) {
2287     length = 0;
2288   } else if (length < 0) {
2289     length = strlen(value);
2290   }
2291   (u.*url_f)(value, length);
2292 
2293   return TS_SUCCESS;
2294 }
2295 
2296 const char *
2297 TSUrlSchemeGet(TSMBuffer bufp, TSMLoc obj, int *length)
2298 {
2299   return URLPartGet(bufp, obj, length, &URL::scheme_get);
2300 }
2301 
2302 TSReturnCode
2303 TSUrlSchemeSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
2304 {
2305   return URLPartSet(bufp, obj, value, length, &URL::scheme_set);
2306 }
2307 
2308 /* Internet specific URLs */
2309 
2310 const char *
2311 TSUrlUserGet(TSMBuffer bufp, TSMLoc obj, int *length)
2312 {
2313   return URLPartGet(bufp, obj, length, &URL::user_get);
2314 }
2315 
2316 TSReturnCode
2317 TSUrlUserSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
2318 {
2319   return URLPartSet(bufp, obj, value, length, &URL::user_set);
2320 }
2321 
2322 const char *
2323 TSUrlPasswordGet(TSMBuffer bufp, TSMLoc obj, int *length)
2324 {
2325   return URLPartGet(bufp, obj, length, &URL::password_get);
2326 }
2327 
2328 TSReturnCode
2329 TSUrlPasswordSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
2330 {
2331   return URLPartSet(bufp, obj, value, length, &URL::password_set);
2332 }
2333 
2334 const char *
2335 TSUrlHostGet(TSMBuffer bufp, TSMLoc obj, int *length)
2336 {
2337   return URLPartGet(bufp, obj, length, &URL::host_get);
2338 }
2339 
2340 TSReturnCode
2341 TSUrlHostSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
2342 {
2343   return URLPartSet(bufp, obj, value, length, &URL::host_set);
2344 }
2345 
2346 int
2347 TSUrlPortGet(TSMBuffer bufp, TSMLoc obj)
2348 {
2349   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2350   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
2351 
2352   URL u;
2353   u.m_heap     = ((HdrHeapSDKHandle *)bufp)->m_heap;
2354   u.m_url_impl = (URLImpl *)obj;
2355 
2356   return u.port_get();
2357 }
2358 
2359 TSReturnCode
2360 TSUrlPortSet(TSMBuffer bufp, TSMLoc obj, int port)
2361 {
2362   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2363   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
2364 
2365   if (!isWriteable(bufp) || (port < 0)) {
2366     return TS_ERROR;
2367   }
2368 
2369   URL u;
2370 
2371   u.m_heap     = ((HdrHeapSDKHandle *)bufp)->m_heap;
2372   u.m_url_impl = (URLImpl *)obj;
2373   u.port_set(port);
2374   return TS_SUCCESS;
2375 }
2376 
2377 /* FTP and HTTP specific URLs  */
2378 
2379 const char *
2380 TSUrlPathGet(TSMBuffer bufp, TSMLoc obj, int *length)
2381 {
2382   return URLPartGet(bufp, obj, length, &URL::path_get);
2383 }
2384 
2385 TSReturnCode
2386 TSUrlPathSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
2387 {
2388   return URLPartSet(bufp, obj, value, length, &URL::path_set);
2389 }
2390 
2391 /* FTP specific URLs */
2392 
2393 int
2394 TSUrlFtpTypeGet(TSMBuffer bufp, TSMLoc obj)
2395 {
2396   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2397   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
2398 
2399   URL u;
2400   u.m_heap     = ((HdrHeapSDKHandle *)bufp)->m_heap;
2401   u.m_url_impl = (URLImpl *)obj;
2402   return u.type_get();
2403 }
2404 
2405 TSReturnCode
2406 TSUrlFtpTypeSet(TSMBuffer bufp, TSMLoc obj, int type)
2407 {
2408   // The valid values are : 0, 65('A'), 97('a'),
2409   // 69('E'), 101('e'), 73 ('I') and 105('i').
2410   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2411   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
2412 
2413   if ((type == 0 || type == 'A' || type == 'E' || type == 'I' || type == 'a' || type == 'i' || type == 'e') && isWriteable(bufp)) {
2414     URL u;
2415 
2416     u.m_heap     = ((HdrHeapSDKHandle *)bufp)->m_heap;
2417     u.m_url_impl = (URLImpl *)obj;
2418     u.type_set(type);
2419     return TS_SUCCESS;
2420   }
2421 
2422   return TS_ERROR;
2423 }
2424 
2425 /* HTTP specific URLs */
2426 
2427 const char *
2428 TSUrlHttpParamsGet(TSMBuffer bufp, TSMLoc obj, int *length)
2429 {
2430   return URLPartGet(bufp, obj, length, &URL::params_get);
2431 }
2432 
2433 TSReturnCode
2434 TSUrlHttpParamsSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
2435 {
2436   return URLPartSet(bufp, obj, value, length, &URL::params_set);
2437 }
2438 
2439 const char *
2440 TSUrlHttpQueryGet(TSMBuffer bufp, TSMLoc obj, int *length)
2441 {
2442   return URLPartGet(bufp, obj, length, &URL::query_get);
2443 }
2444 
2445 TSReturnCode
2446 TSUrlHttpQuerySet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
2447 {
2448   return URLPartSet(bufp, obj, value, length, &URL::query_set);
2449 }
2450 
2451 const char *
2452 TSUrlHttpFragmentGet(TSMBuffer bufp, TSMLoc obj, int *length)
2453 {
2454   return URLPartGet(bufp, obj, length, &URL::fragment_get);
2455 }
2456 
2457 TSReturnCode
2458 TSUrlHttpFragmentSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
2459 {
2460   return URLPartSet(bufp, obj, value, length, &URL::fragment_set);
2461 }
2462 
2463 // URL percent encoding
2464 TSReturnCode
2465 TSStringPercentEncode(const char *str, int str_len, char *dst, size_t dst_size, size_t *length, const unsigned char *map)
2466 {
2467   sdk_assert(sdk_sanity_check_null_ptr((void *)str) == TS_SUCCESS);
2468   sdk_assert(sdk_sanity_check_null_ptr((void *)dst) == TS_SUCCESS);
2469 
2470   int new_len; // Unfortunately, a lot of the core uses "int" for length's internally...
2471 
2472   if (str_len < 0) {
2473     str_len = strlen(str);
2474   }
2475 
2476   sdk_assert(str_len < static_cast<int>(dst_size));
2477 
2478   // TODO: Perhaps we should make escapify_url() deal with const properly...
2479   // You would think making escapify_url const correct for the source argument would be easy, but in the case where
2480   // No escaping is needed, the source argument is returned.  If there is a destination argument, the source is copied over
2481   // However, if there is no destination argument, none is allocated.  I don't understand the full possibility of calling cases.
2482   // It seems like we might want to review how this is being called and perhaps create a number of smaller accessor methods that
2483   // can be set up correctly.
2484   if (nullptr == LogUtils::pure_escapify_url(nullptr, const_cast<char *>(str), str_len, &new_len, dst, dst_size, map)) {
2485     if (length) {
2486       *length = 0;
2487     }
2488     return TS_ERROR;
2489   }
2490 
2491   if (length) {
2492     *length = new_len;
2493   }
2494 
2495   return TS_SUCCESS;
2496 }
2497 
2498 TSReturnCode
2499 TSStringPercentDecode(const char *str, size_t str_len, char *dst, size_t dst_size, size_t *length)
2500 {
2501   sdk_assert(sdk_sanity_check_null_ptr((void *)str) == TS_SUCCESS);
2502   sdk_assert(sdk_sanity_check_null_ptr((void *)dst) == TS_SUCCESS);
2503 
2504   if (0 == str_len) {
2505     str_len = strlen(str);
2506   }
2507 
2508   // return unescapifyStr(str);
2509   char *buffer    = dst;
2510   const char *src = str;
2511   int s           = 0; // State, which we don't really use
2512 
2513   // TODO: We should check for "failures" here?
2514   unescape_str(buffer, buffer + dst_size, src, src + str_len, s);
2515 
2516   size_t data_written   = std::min<size_t>(buffer - dst, dst_size - 1);
2517   *(dst + data_written) = '\0';
2518 
2519   if (length) {
2520     *length = (data_written);
2521   }
2522 
2523   return TS_SUCCESS;
2524 }
2525 
2526 TSReturnCode
2527 TSUrlPercentEncode(TSMBuffer bufp, TSMLoc obj, char *dst, size_t dst_size, size_t *length, const unsigned char *map)
2528 {
2529   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2530   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
2531 
2532   char *url;
2533   int url_len;
2534   TSReturnCode ret;
2535   URLImpl *url_impl = (URLImpl *)obj;
2536 
2537   // TODO: at some point, it might be nice to allow this to write to a pre-allocated buffer
2538   url = url_string_get(url_impl, nullptr, &url_len, nullptr);
2539   ret = TSStringPercentEncode(url, url_len, dst, dst_size, length, map);
2540   ats_free(url);
2541 
2542   return ret;
2543 }
2544 
2545 // pton
2546 TSReturnCode
2547 TSIpStringToAddr(const char *str, size_t str_len, sockaddr *addr)
2548 {
2549   sdk_assert(sdk_sanity_check_null_ptr((void *)str) == TS_SUCCESS);
2550 
2551   if (0 != ats_ip_pton(std::string_view(str, str_len), addr)) {
2552     return TS_ERROR;
2553   }
2554 
2555   return TS_SUCCESS;
2556 }
2557 
2558 ////////////////////////////////////////////////////////////////////
2559 //
2560 // MIME Headers
2561 //
2562 ////////////////////////////////////////////////////////////////////
2563 
2564 /**************/
2565 /* MimeParser */
2566 /**************/
2567 
2568 TSMimeParser
2569 TSMimeParserCreate()
2570 {
2571   TSMimeParser parser = reinterpret_cast<TSMimeParser>(ats_malloc(sizeof(MIMEParser)));
2572 
2573   mime_parser_init((MIMEParser *)parser);
2574   return parser;
2575 }
2576 
2577 void
2578 TSMimeParserClear(TSMimeParser parser)
2579 {
2580   sdk_assert(sdk_sanity_check_mime_parser(parser) == TS_SUCCESS);
2581 
2582   mime_parser_clear((MIMEParser *)parser);
2583 }
2584 
2585 void
2586 TSMimeParserDestroy(TSMimeParser parser)
2587 {
2588   sdk_assert(sdk_sanity_check_mime_parser(parser) == TS_SUCCESS);
2589 
2590   mime_parser_clear((MIMEParser *)parser);
2591   ats_free(parser);
2592 }
2593 
2594 /***********/
2595 /* MimeHdr */
2596 /***********/
2597 
2598 // TSMBuffer: pointers to HdrHeapSDKHandle objects
2599 // TSMLoc:    pointers to MIMEFieldSDKHandle objects
2600 
2601 TSReturnCode
2602 TSMimeHdrCreate(TSMBuffer bufp, TSMLoc *locp)
2603 {
2604   // Allow to modify the buffer only
2605   // if bufp is modifiable. If bufp is not modifiable return
2606   // TS_ERROR. If not allowed, return NULL.
2607   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2608   sdk_assert(sdk_sanity_check_null_ptr((void *)locp) == TS_SUCCESS);
2609 
2610   if (!isWriteable(bufp)) {
2611     return TS_ERROR;
2612   }
2613 
2614   *locp = reinterpret_cast<TSMLoc>(mime_hdr_create(((HdrHeapSDKHandle *)bufp)->m_heap));
2615   return TS_SUCCESS;
2616 }
2617 
2618 TSReturnCode
2619 TSMimeHdrDestroy(TSMBuffer bufp, TSMLoc obj)
2620 {
2621   // Allow to modify the buffer only
2622   // if bufp is modifiable. If bufp is not modifiable return
2623   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
2624   // return value of function from void to TSReturnCode.
2625   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2626   sdk_assert((sdk_sanity_check_mime_hdr_handle(obj) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS));
2627 
2628   if (!isWriteable(bufp)) {
2629     return TS_ERROR;
2630   }
2631 
2632   MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(obj);
2633 
2634   mime_hdr_destroy(((HdrHeapSDKHandle *)bufp)->m_heap, mh);
2635   return TS_SUCCESS;
2636 }
2637 
2638 TSReturnCode
2639 TSMimeHdrClone(TSMBuffer dest_bufp, TSMBuffer src_bufp, TSMLoc src_hdr, TSMLoc *locp)
2640 {
2641   // Allow to modify the buffer only
2642   // if bufp is modifiable. If bufp is not modifiable return
2643   // TS_ERROR. If not allowed, return NULL.
2644   sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
2645   sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
2646   sdk_assert(sdk_sanity_check_mime_hdr_handle(src_hdr) == TS_SUCCESS);
2647   sdk_assert(sdk_sanity_check_http_hdr_handle(src_hdr) == TS_SUCCESS);
2648   sdk_assert(sdk_sanity_check_null_ptr((void *)locp) == TS_SUCCESS);
2649 
2650   if (!isWriteable(dest_bufp)) {
2651     return TS_ERROR;
2652   }
2653 
2654   HdrHeap *s_heap, *d_heap;
2655   MIMEHdrImpl *s_mh, *d_mh;
2656 
2657   s_heap = ((HdrHeapSDKHandle *)src_bufp)->m_heap;
2658   d_heap = ((HdrHeapSDKHandle *)dest_bufp)->m_heap;
2659   s_mh   = _hdr_mloc_to_mime_hdr_impl(src_hdr);
2660 
2661   d_mh  = mime_hdr_clone(s_mh, s_heap, d_heap, (s_heap != d_heap));
2662   *locp = (TSMLoc)d_mh;
2663 
2664   return TS_SUCCESS;
2665 }
2666 
2667 TSReturnCode
2668 TSMimeHdrCopy(TSMBuffer dest_bufp, TSMLoc dest_obj, TSMBuffer src_bufp, TSMLoc src_obj)
2669 {
2670   // Allow to modify the buffer only
2671   // if bufp is modifiable. If bufp is not modifiable return
2672   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
2673   // return value of function from void to TSReturnCode.
2674   sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
2675   sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
2676   sdk_assert((sdk_sanity_check_mime_hdr_handle(src_obj) == TS_SUCCESS) ||
2677              (sdk_sanity_check_http_hdr_handle(src_obj) == TS_SUCCESS));
2678   sdk_assert((sdk_sanity_check_mime_hdr_handle(dest_obj) == TS_SUCCESS) ||
2679              (sdk_sanity_check_http_hdr_handle(dest_obj) == TS_SUCCESS));
2680 
2681   if (!isWriteable(dest_bufp)) {
2682     return TS_ERROR;
2683   }
2684 
2685   HdrHeap *s_heap, *d_heap;
2686   MIMEHdrImpl *s_mh, *d_mh;
2687 
2688   s_heap = ((HdrHeapSDKHandle *)src_bufp)->m_heap;
2689   d_heap = ((HdrHeapSDKHandle *)dest_bufp)->m_heap;
2690   s_mh   = _hdr_mloc_to_mime_hdr_impl(src_obj);
2691   d_mh   = _hdr_mloc_to_mime_hdr_impl(dest_obj);
2692 
2693   mime_hdr_fields_clear(d_heap, d_mh);
2694   mime_hdr_copy_onto(s_mh, s_heap, d_mh, d_heap, (s_heap != d_heap));
2695   return TS_SUCCESS;
2696 }
2697 
2698 void
2699 TSMimeHdrPrint(TSMBuffer bufp, TSMLoc obj, TSIOBuffer iobufp)
2700 {
2701   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2702   sdk_assert((sdk_sanity_check_mime_hdr_handle(obj) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS));
2703   sdk_assert(sdk_sanity_check_iocore_structure(iobufp) == TS_SUCCESS);
2704 
2705   HdrHeap *heap   = ((HdrHeapSDKHandle *)bufp)->m_heap;
2706   MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(obj);
2707   MIOBuffer *b    = (MIOBuffer *)iobufp;
2708   IOBufferBlock *blk;
2709   int bufindex;
2710   int tmp, dumpoffset = 0;
2711   int done;
2712 
2713   do {
2714     blk = b->get_current_block();
2715     if (!blk || blk->write_avail() == 0) {
2716       b->add_block();
2717       blk = b->get_current_block();
2718     }
2719 
2720     bufindex = 0;
2721     tmp      = dumpoffset;
2722     done     = mime_hdr_print(heap, mh, blk->end(), blk->write_avail(), &bufindex, &tmp);
2723 
2724     dumpoffset += bufindex;
2725     b->fill(bufindex);
2726   } while (!done);
2727 }
2728 
2729 TSParseResult
2730 TSMimeHdrParse(TSMimeParser parser, TSMBuffer bufp, TSMLoc obj, const char **start, const char *end)
2731 {
2732   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2733   sdk_assert((sdk_sanity_check_mime_hdr_handle(obj) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS));
2734   sdk_assert(sdk_sanity_check_null_ptr((void *)start) == TS_SUCCESS);
2735   sdk_assert(sdk_sanity_check_null_ptr((void *)*start) == TS_SUCCESS);
2736   sdk_assert(sdk_sanity_check_null_ptr((void *)end) == TS_SUCCESS);
2737 
2738   if (!isWriteable(bufp)) {
2739     return TS_PARSE_ERROR;
2740   }
2741 
2742   MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(obj);
2743 
2744   return (TSParseResult)mime_parser_parse((MIMEParser *)parser, ((HdrHeapSDKHandle *)bufp)->m_heap, mh, start, end, false, false);
2745 }
2746 
2747 int
2748 TSMimeHdrLengthGet(TSMBuffer bufp, TSMLoc obj)
2749 {
2750   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2751   sdk_assert((sdk_sanity_check_mime_hdr_handle(obj) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS));
2752 
2753   MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(obj);
2754   return mime_hdr_length_get(mh);
2755 }
2756 
2757 TSReturnCode
2758 TSMimeHdrFieldsClear(TSMBuffer bufp, TSMLoc obj)
2759 {
2760   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2761   sdk_assert((sdk_sanity_check_mime_hdr_handle(obj) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS));
2762 
2763   if (!isWriteable(bufp)) {
2764     return TS_ERROR;
2765   }
2766 
2767   MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(obj);
2768 
2769   mime_hdr_fields_clear(((HdrHeapSDKHandle *)bufp)->m_heap, mh);
2770   return TS_SUCCESS;
2771 }
2772 
2773 int
2774 TSMimeHdrFieldsCount(TSMBuffer bufp, TSMLoc obj)
2775 {
2776   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2777   sdk_assert((sdk_sanity_check_mime_hdr_handle(obj) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS));
2778 
2779   MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(obj);
2780   return mime_hdr_fields_count(mh);
2781 }
2782 
2783 // The following three helper functions should not be used in plugins! Since they are not used
2784 // by plugins, there's no need to validate the input.
2785 const char *
2786 TSMimeFieldValueGet(TSMBuffer /* bufp ATS_UNUSED */, TSMLoc field_obj, int idx, int *value_len_ptr)
2787 {
2788   MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *)field_obj;
2789 
2790   if (idx >= 0) {
2791     return mime_field_value_get_comma_val(handle->field_ptr, value_len_ptr, idx);
2792   } else {
2793     return handle->field_ptr->value_get(value_len_ptr);
2794   }
2795 }
2796 
2797 void
2798 TSMimeFieldValueSet(TSMBuffer bufp, TSMLoc field_obj, int idx, const char *value, int length)
2799 {
2800   MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *)field_obj;
2801   HdrHeap *heap              = ((HdrHeapSDKHandle *)bufp)->m_heap;
2802 
2803   if (length == -1) {
2804     length = strlen(value);
2805   }
2806 
2807   if (idx >= 0) {
2808     mime_field_value_set_comma_val(heap, handle->mh, handle->field_ptr, idx, value, length);
2809   } else {
2810     mime_field_value_set(heap, handle->mh, handle->field_ptr, value, length, true);
2811   }
2812 }
2813 
2814 void
2815 TSMimeFieldValueInsert(TSMBuffer bufp, TSMLoc field_obj, const char *value, int length, int idx)
2816 {
2817   MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *)field_obj;
2818   HdrHeap *heap              = ((HdrHeapSDKHandle *)bufp)->m_heap;
2819 
2820   if (length == -1) {
2821     length = strlen(value);
2822   }
2823 
2824   mime_field_value_insert_comma_val(heap, handle->mh, handle->field_ptr, idx, value, length);
2825 }
2826 
2827 /****************/
2828 /* MimeHdrField */
2829 /****************/
2830 
2831 // TSMBuffer: pointers to HdrHeapSDKHandle objects
2832 // TSMLoc:    pointers to MIMEFieldSDKHandle objects
2833 
2834 int
2835 TSMimeHdrFieldEqual(TSMBuffer bufp, TSMLoc hdr_obj, TSMLoc field1_obj, TSMLoc field2_obj)
2836 {
2837   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2838   sdk_assert(sdk_sanity_check_field_handle(field1_obj, hdr_obj) == TS_SUCCESS);
2839   sdk_assert(sdk_sanity_check_field_handle(field2_obj, hdr_obj) == TS_SUCCESS);
2840 
2841   MIMEFieldSDKHandle *field1_handle = (MIMEFieldSDKHandle *)field1_obj;
2842   MIMEFieldSDKHandle *field2_handle = (MIMEFieldSDKHandle *)field2_obj;
2843 
2844   if ((field1_handle == nullptr) || (field2_handle == nullptr)) {
2845     return (field1_handle == field2_handle);
2846   }
2847   return (field1_handle->field_ptr == field2_handle->field_ptr);
2848 }
2849 
2850 TSMLoc
2851 TSMimeHdrFieldGet(TSMBuffer bufp, TSMLoc hdr_obj, int idx)
2852 {
2853   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2854   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr_obj) == TS_SUCCESS) ||
2855              (sdk_sanity_check_http_hdr_handle(hdr_obj) == TS_SUCCESS));
2856   sdk_assert(idx >= 0);
2857 
2858   MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(hdr_obj);
2859   MIMEField *f    = mime_hdr_field_get(mh, idx);
2860 
2861   if (f == nullptr) {
2862     return TS_NULL_MLOC;
2863   }
2864 
2865   MIMEFieldSDKHandle *h = sdk_alloc_field_handle(bufp, mh);
2866 
2867   h->field_ptr = f;
2868   return reinterpret_cast<TSMLoc>(h);
2869 }
2870 
2871 TSMLoc
2872 TSMimeHdrFieldFind(TSMBuffer bufp, TSMLoc hdr_obj, const char *name, int length)
2873 {
2874   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2875   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr_obj) == TS_SUCCESS) ||
2876              (sdk_sanity_check_http_hdr_handle(hdr_obj) == TS_SUCCESS));
2877   sdk_assert(sdk_sanity_check_null_ptr((void *)name) == TS_SUCCESS);
2878 
2879   if (length == -1) {
2880     length = strlen(name);
2881   }
2882 
2883   MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(hdr_obj);
2884   MIMEField *f    = mime_hdr_field_find(mh, name, length);
2885 
2886   if (f == nullptr) {
2887     return TS_NULL_MLOC;
2888   }
2889 
2890   MIMEFieldSDKHandle *h = sdk_alloc_field_handle(bufp, mh);
2891 
2892   h->field_ptr = f;
2893   return reinterpret_cast<TSMLoc>(h);
2894 }
2895 
2896 TSReturnCode
2897 TSMimeHdrFieldAppend(TSMBuffer bufp, TSMLoc mh_mloc, TSMLoc field_mloc)
2898 {
2899   // Allow to modify the buffer only
2900   // if bufp is modifiable. If bufp is not modifiable return
2901   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
2902   // return value of function from void to TSReturnCode.
2903   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2904   sdk_assert((sdk_sanity_check_mime_hdr_handle(mh_mloc) == TS_SUCCESS) ||
2905              (sdk_sanity_check_http_hdr_handle(mh_mloc) == TS_SUCCESS));
2906   sdk_assert(sdk_sanity_check_field_handle(field_mloc) == TS_SUCCESS);
2907 
2908   if (!isWriteable(bufp)) {
2909     return TS_ERROR;
2910   }
2911 
2912   MIMEField *mh_field;
2913   MIMEHdrImpl *mh                  = _hdr_mloc_to_mime_hdr_impl(mh_mloc);
2914   MIMEFieldSDKHandle *field_handle = (MIMEFieldSDKHandle *)field_mloc;
2915 
2916   //////////////////////////////////////////////////////////////////////
2917   // The field passed in field_mloc might have been allocated from    //
2918   // inside a MIME header (the correct way), or it might have been    //
2919   // created in isolation as a "standalone field" (the old way).      //
2920   //                                                                  //
2921   // If it's a standalone field (the associated mime header is NULL), //
2922   // then we need to now allocate a real field inside the header,     //
2923   // copy over the data, and convert the standalone field into a      //
2924   // forwarding pointer to the real field, in case it's used again    //
2925   //////////////////////////////////////////////////////////////////////
2926   if (field_handle->mh == nullptr) {
2927     HdrHeap *heap = (HdrHeap *)(((HdrHeapSDKHandle *)bufp)->m_heap);
2928 
2929     // allocate a new hdr field and copy any pre-set info
2930     mh_field = mime_field_create(heap, mh);
2931 
2932     // FIX: is it safe to copy everything over?
2933     memcpy(mh_field, field_handle->field_ptr, sizeof(MIMEField));
2934 
2935     // now set up the forwarding ptr from standalone field to hdr field
2936     field_handle->mh        = mh;
2937     field_handle->field_ptr = mh_field;
2938   }
2939 
2940   ink_assert(field_handle->mh == mh);
2941   ink_assert(field_handle->field_ptr->m_ptr_name);
2942 
2943   mime_hdr_field_attach(mh, field_handle->field_ptr, 1, nullptr);
2944   return TS_SUCCESS;
2945 }
2946 
2947 TSReturnCode
2948 TSMimeHdrFieldRemove(TSMBuffer bufp, TSMLoc mh_mloc, TSMLoc field_mloc)
2949 {
2950   // Allow to modify the buffer only
2951   // if bufp is modifiable. If bufp is not modifiable return
2952   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
2953   // return value of function from void to TSReturnCode.
2954   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2955   sdk_assert((sdk_sanity_check_mime_hdr_handle(mh_mloc) == TS_SUCCESS) ||
2956              (sdk_sanity_check_http_hdr_handle(mh_mloc) == TS_SUCCESS));
2957   sdk_assert(sdk_sanity_check_field_handle(field_mloc, mh_mloc) == TS_SUCCESS);
2958 
2959   if (!isWriteable(bufp)) {
2960     return TS_ERROR;
2961   }
2962 
2963   MIMEFieldSDKHandle *field_handle = (MIMEFieldSDKHandle *)field_mloc;
2964 
2965   if (field_handle->mh != nullptr) {
2966     MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(mh_mloc);
2967     ink_assert(mh == field_handle->mh);
2968     sdk_sanity_check_field_handle(field_mloc, mh_mloc);
2969     mime_hdr_field_detach(mh, field_handle->field_ptr, false); // only detach this dup
2970   }
2971   return TS_SUCCESS;
2972 }
2973 
2974 TSReturnCode
2975 TSMimeHdrFieldDestroy(TSMBuffer bufp, TSMLoc mh_mloc, TSMLoc field_mloc)
2976 {
2977   // Allow to modify the buffer only
2978   // if bufp is modifiable. If bufp is not modifiable return
2979   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
2980   // return value of function from void to TSReturnCode.
2981   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2982   sdk_assert((sdk_sanity_check_mime_hdr_handle(mh_mloc) == TS_SUCCESS) ||
2983              (sdk_sanity_check_http_hdr_handle(mh_mloc) == TS_SUCCESS));
2984   sdk_assert(sdk_sanity_check_field_handle(field_mloc, mh_mloc) == TS_SUCCESS);
2985 
2986   if (!isWriteable(bufp)) {
2987     return TS_ERROR;
2988   }
2989 
2990   MIMEFieldSDKHandle *field_handle = (MIMEFieldSDKHandle *)field_mloc;
2991 
2992   if (field_handle->mh == nullptr) { // NOT SUPPORTED!!
2993     ink_release_assert(!"Failed MH");
2994   } else {
2995     MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(mh_mloc);
2996     HdrHeap *heap   = (HdrHeap *)(((HdrHeapSDKHandle *)bufp)->m_heap);
2997 
2998     ink_assert(mh == field_handle->mh);
2999     if (sdk_sanity_check_field_handle(field_mloc, mh_mloc) != TS_SUCCESS) {
3000       return TS_ERROR;
3001     }
3002 
3003     // detach and delete this field, but not all dups
3004     mime_hdr_field_delete(heap, mh, field_handle->field_ptr, false);
3005   }
3006   // for consistence, the handle will not be released here.
3007   // users will be required to do it.
3008   return TS_SUCCESS;
3009 }
3010 
3011 TSReturnCode
3012 TSMimeHdrFieldCreate(TSMBuffer bufp, TSMLoc mh_mloc, TSMLoc *locp)
3013 {
3014   // Allow to modify the buffer only
3015   // if bufp is modifiable. If bufp is not modifiable return
3016   // TS_ERROR. If not allowed, return NULL.
3017   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3018   sdk_assert((sdk_sanity_check_mime_hdr_handle(mh_mloc) == TS_SUCCESS) ||
3019              (sdk_sanity_check_http_hdr_handle(mh_mloc) == TS_SUCCESS));
3020   sdk_assert(sdk_sanity_check_null_ptr((void *)locp) == TS_SUCCESS);
3021 
3022   if (!isWriteable(bufp)) {
3023     return TS_ERROR;
3024   }
3025 
3026   MIMEHdrImpl *mh       = _hdr_mloc_to_mime_hdr_impl(mh_mloc);
3027   HdrHeap *heap         = (HdrHeap *)(((HdrHeapSDKHandle *)bufp)->m_heap);
3028   MIMEFieldSDKHandle *h = sdk_alloc_field_handle(bufp, mh);
3029 
3030   h->field_ptr = mime_field_create(heap, mh);
3031   *locp        = reinterpret_cast<TSMLoc>(h);
3032   return TS_SUCCESS;
3033 }
3034 
3035 TSReturnCode
3036 TSMimeHdrFieldCreateNamed(TSMBuffer bufp, TSMLoc mh_mloc, const char *name, int name_len, TSMLoc *locp)
3037 {
3038   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3039   sdk_assert((sdk_sanity_check_mime_hdr_handle(mh_mloc) == TS_SUCCESS) ||
3040              (sdk_sanity_check_http_hdr_handle(mh_mloc) == TS_SUCCESS));
3041   sdk_assert(sdk_sanity_check_null_ptr((void *)name) == TS_SUCCESS);
3042   sdk_assert(sdk_sanity_check_null_ptr((void *)locp) == TS_SUCCESS);
3043 
3044   if (!isWriteable(bufp)) {
3045     return TS_ERROR;
3046   }
3047 
3048   if (name_len == -1) {
3049     name_len = strlen(name);
3050   }
3051 
3052   MIMEHdrImpl *mh       = _hdr_mloc_to_mime_hdr_impl(mh_mloc);
3053   HdrHeap *heap         = (HdrHeap *)(((HdrHeapSDKHandle *)bufp)->m_heap);
3054   MIMEFieldSDKHandle *h = sdk_alloc_field_handle(bufp, mh);
3055   h->field_ptr          = mime_field_create_named(heap, mh, name, name_len);
3056   *locp                 = reinterpret_cast<TSMLoc>(h);
3057   return TS_SUCCESS;
3058 }
3059 
3060 TSReturnCode
3061 TSMimeHdrFieldCopy(TSMBuffer dest_bufp, TSMLoc dest_hdr, TSMLoc dest_field, TSMBuffer src_bufp, TSMLoc src_hdr, TSMLoc src_field)
3062 {
3063   // Allow to modify the buffer only
3064   // if bufp is modifiable. If bufp is not modifiable return
3065   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
3066   // return value of function from void to TSReturnCode.
3067   sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
3068   sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
3069   sdk_assert((sdk_sanity_check_mime_hdr_handle(src_hdr) == TS_SUCCESS) ||
3070              (sdk_sanity_check_http_hdr_handle(src_hdr) == TS_SUCCESS));
3071   sdk_assert((sdk_sanity_check_mime_hdr_handle(dest_hdr) == TS_SUCCESS) ||
3072              (sdk_sanity_check_http_hdr_handle(dest_hdr) == TS_SUCCESS));
3073   sdk_assert(sdk_sanity_check_field_handle(src_field, src_hdr) == TS_SUCCESS);
3074   sdk_assert(sdk_sanity_check_field_handle(dest_field, dest_hdr) == TS_SUCCESS);
3075 
3076   if (!isWriteable(dest_bufp)) {
3077     return TS_ERROR;
3078   }
3079 
3080   bool dest_attached;
3081   MIMEFieldSDKHandle *s_handle = (MIMEFieldSDKHandle *)src_field;
3082   MIMEFieldSDKHandle *d_handle = (MIMEFieldSDKHandle *)dest_field;
3083   HdrHeap *d_heap              = ((HdrHeapSDKHandle *)dest_bufp)->m_heap;
3084 
3085   // FIX: This tortuous detach/change/attach algorithm is due to the
3086   //      fact that we can't change the name of an attached header (assertion)
3087 
3088   // TODO: This is never used ... is_live() has no side effects, so this should be ok
3089   // to not call, so commented out
3090   // src_attached = (s_handle->mh && s_handle->field_ptr->is_live());
3091   dest_attached = (d_handle->mh && d_handle->field_ptr->is_live());
3092 
3093   if (dest_attached) {
3094     mime_hdr_field_detach(d_handle->mh, d_handle->field_ptr, false);
3095   }
3096 
3097   mime_field_name_value_set(d_heap, d_handle->mh, d_handle->field_ptr, s_handle->field_ptr->m_wks_idx,
3098                             s_handle->field_ptr->m_ptr_name, s_handle->field_ptr->m_len_name, s_handle->field_ptr->m_ptr_value,
3099                             s_handle->field_ptr->m_len_value, 0, 0, true);
3100 
3101   if (dest_attached) {
3102     mime_hdr_field_attach(d_handle->mh, d_handle->field_ptr, 1, nullptr);
3103   }
3104   return TS_SUCCESS;
3105 }
3106 
3107 TSReturnCode
3108 TSMimeHdrFieldClone(TSMBuffer dest_bufp, TSMLoc dest_hdr, TSMBuffer src_bufp, TSMLoc src_hdr, TSMLoc src_field, TSMLoc *locp)
3109 {
3110   // Allow to modify the buffer only
3111   // if bufp is modifiable. If bufp is not modifiable return
3112   // TS_ERROR. If not allowed, return NULL.
3113   sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
3114   sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
3115   sdk_assert((sdk_sanity_check_mime_hdr_handle(dest_hdr) == TS_SUCCESS) ||
3116              (sdk_sanity_check_http_hdr_handle(dest_hdr) == TS_SUCCESS));
3117   sdk_assert((sdk_sanity_check_mime_hdr_handle(src_hdr) == TS_SUCCESS) ||
3118              (sdk_sanity_check_http_hdr_handle(src_hdr) == TS_SUCCESS));
3119   sdk_assert(sdk_sanity_check_field_handle(src_field, src_hdr) == TS_SUCCESS);
3120   sdk_assert(sdk_sanity_check_null_ptr((void *)locp) == TS_SUCCESS);
3121 
3122   if (!isWriteable(dest_bufp)) {
3123     return TS_ERROR;
3124   }
3125 
3126   // This is sort of sub-optimal, since we'll check the args again. TODO.
3127   if (TSMimeHdrFieldCreate(dest_bufp, dest_hdr, locp) == TS_SUCCESS) {
3128     TSMimeHdrFieldCopy(dest_bufp, dest_hdr, *locp, src_bufp, src_hdr, src_field);
3129     return TS_SUCCESS;
3130   }
3131   // TSMimeHdrFieldCreate() failed for some reason.
3132   return TS_ERROR;
3133 }
3134 
3135 TSReturnCode
3136 TSMimeHdrFieldCopyValues(TSMBuffer dest_bufp, TSMLoc dest_hdr, TSMLoc dest_field, TSMBuffer src_bufp, TSMLoc src_hdr,
3137                          TSMLoc src_field)
3138 {
3139   // Allow to modify the buffer only
3140   // if bufp is modifiable. If bufp is not modifiable return
3141   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
3142   // return value of function from void to TSReturnCode.
3143   sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
3144   sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
3145   sdk_assert((sdk_sanity_check_mime_hdr_handle(src_hdr) == TS_SUCCESS) ||
3146              (sdk_sanity_check_http_hdr_handle(src_hdr) == TS_SUCCESS));
3147   sdk_assert((sdk_sanity_check_mime_hdr_handle(dest_hdr) == TS_SUCCESS) ||
3148              (sdk_sanity_check_http_hdr_handle(dest_hdr) == TS_SUCCESS));
3149   sdk_assert(sdk_sanity_check_field_handle(src_field, src_hdr) == TS_SUCCESS);
3150   sdk_assert(sdk_sanity_check_field_handle(dest_field, dest_hdr) == TS_SUCCESS);
3151 
3152   if (!isWriteable(dest_bufp)) {
3153     return TS_ERROR;
3154   }
3155 
3156   MIMEFieldSDKHandle *s_handle = (MIMEFieldSDKHandle *)src_field;
3157   MIMEFieldSDKHandle *d_handle = (MIMEFieldSDKHandle *)dest_field;
3158   HdrHeap *d_heap              = ((HdrHeapSDKHandle *)dest_bufp)->m_heap;
3159   MIMEField *s_field, *d_field;
3160 
3161   s_field = s_handle->field_ptr;
3162   d_field = d_handle->field_ptr;
3163   mime_field_value_set(d_heap, d_handle->mh, d_field, s_field->m_ptr_value, s_field->m_len_value, true);
3164   return TS_SUCCESS;
3165 }
3166 
3167 // TODO: This is implemented horribly slowly, but who's using it anyway?
3168 //       If we threaded all the MIMEFields, this function could be easier,
3169 //       but we'd have to print dups in order and we'd need a flag saying
3170 //       end of dup list or dup follows.
3171 TSMLoc
3172 TSMimeHdrFieldNext(TSMBuffer bufp, TSMLoc hdr, TSMLoc