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