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