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