1 /** @file
2 
3   Implements the Traffic Server C API functions.
4 
5   @section license License
6 
7   Licensed to the Apache Software Foundation (ASF) under one
8   or more contributor license agreements.  See the NOTICE file
9   distributed with this work for additional information
10   regarding copyright ownership.  The ASF licenses this file
11   to you under the Apache License, Version 2.0 (the
12   "License"); you may not use this file except in compliance
13   with the License.  You may obtain a copy of the License at
14 
15       http://www.apache.org/licenses/LICENSE-2.0
16 
17   Unless required by applicable law or agreed to in writing, software
18   distributed under the License is distributed on an "AS IS" BASIS,
19   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20   See the License for the specific language governing permissions and
21   limitations under the License.
22  */
23 
24 #include <cstdio>
25 #include <atomic>
26 #include <string_view>
27 #include <tuple>
28 #include <unordered_map>
29 #include <string_view>
30 
31 #include "tscore/ink_platform.h"
32 #include "tscore/ink_base64.h"
33 #include "tscore/PluginUserArgs.h"
34 #include "tscore/I_Layout.h"
35 #include "tscore/I_Version.h"
36 
37 #include "InkAPIInternal.h"
38 #include "Log.h"
39 #include "URL.h"
40 #include "MIME.h"
41 #include "HTTP.h"
42 #include "ProxySession.h"
43 #include "Http2ClientSession.h"
44 #include "Http1ServerSession.h"
45 #include "HttpSM.h"
46 #include "HttpConfig.h"
47 #include "P_Net.h"
48 #include "P_SSLNextProtocolAccept.h"
49 #include "P_UDPNet.h"
50 #include "P_HostDB.h"
51 #include "P_Cache.h"
52 #include "records/I_RecCore.h"
53 #include "P_SSLConfig.h"
54 #include "P_SSLClientUtils.h"
55 #include "SSLDiags.h"
56 #include "SSLInternal.h"
57 #include "ProxyConfig.h"
58 #include "Plugin.h"
59 #include "LogObject.h"
60 #include "LogConfig.h"
61 #include "PluginVC.h"
62 #include "ts/experimental.h"
63 #include "HttpSessionAccept.h"
64 #include "PluginVC.h"
65 #include "FetchSM.h"
66 #include "HttpDebugNames.h"
67 #include "I_AIO.h"
68 #include "I_Tasks.h"
69 
70 #include "P_OCSPStapling.h"
71 #include "RecordsConfig.h"
72 #include "records/I_RecDefs.h"
73 #include "records/I_RecCore.h"
74 #include "I_Machine.h"
75 #include "HttpProxyServerMain.h"
76 #include "shared/overridable_txn_vars.h"
77 
78 #include "ts/ts.h"
79 
80 /****************************************************************
81  *  IMPORTANT - READ ME
82  * Any plugin using the IO Core must enter
83  *   with a held mutex.  SDK 1.0, 1.1 & 2.0 did not
84  *   have this restriction so we need to add a mutex
85  *   to Plugin's Continuation if it tries to use the IOCore
86  * Not only does the plugin have to have a mutex
87  *   before entering the IO Core.  The mutex needs to be held.
88  *   We now take out the mutex on each call to ensure it is
89  *   held for the entire duration of the IOCore call
90  ***************************************************************/
91 
92 // helper macro for setting HTTPHdr data
93 #define SET_HTTP_HDR(_HDR, _BUF_PTR, _OBJ_PTR)          \
94   _HDR.m_heap = ((HdrHeapSDKHandle *)_BUF_PTR)->m_heap; \
95   _HDR.m_http = (HTTPHdrImpl *)_OBJ_PTR;                \
96   _HDR.m_mime = _HDR.m_http->m_fields_impl;
97 
98 extern AppVersionInfo appVersionInfo;
99 
100 // Globals for new librecords stats
101 static int api_rsb_index;
102 static RecRawStatBlock *api_rsb;
103 
104 /** Reservation for a user arg.
105  */
106 struct UserArg {
107   TSUserArgType type;
108   std::string name;        ///< Name of reserving plugin.
109   std::string description; ///< Description of use for this arg.
110 };
111 
112 // Managing the user args tables, and the global storage (which is assumed to be the biggest, by far).
113 UserArg UserArgTable[TS_USER_ARGS_COUNT][MAX_USER_ARGS[TS_USER_ARGS_GLB]];
114 static PluginUserArgs<TS_USER_ARGS_GLB> global_user_args;
115 std::atomic<int> UserArgIdx[TS_USER_ARGS_COUNT]; // Table of next reserved index.
116 
117 /* URL schemes */
118 tsapi const char *TS_URL_SCHEME_FILE;
119 tsapi const char *TS_URL_SCHEME_FTP;
120 tsapi const char *TS_URL_SCHEME_GOPHER;
121 tsapi const char *TS_URL_SCHEME_HTTP;
122 tsapi const char *TS_URL_SCHEME_HTTPS;
123 tsapi const char *TS_URL_SCHEME_MAILTO;
124 tsapi const char *TS_URL_SCHEME_NEWS;
125 tsapi const char *TS_URL_SCHEME_NNTP;
126 tsapi const char *TS_URL_SCHEME_PROSPERO;
127 tsapi const char *TS_URL_SCHEME_TELNET;
128 tsapi const char *TS_URL_SCHEME_TUNNEL;
129 tsapi const char *TS_URL_SCHEME_WAIS;
130 tsapi const char *TS_URL_SCHEME_PNM;
131 tsapi const char *TS_URL_SCHEME_RTSP;
132 tsapi const char *TS_URL_SCHEME_RTSPU;
133 tsapi const char *TS_URL_SCHEME_MMS;
134 tsapi const char *TS_URL_SCHEME_MMSU;
135 tsapi const char *TS_URL_SCHEME_MMST;
136 tsapi const char *TS_URL_SCHEME_WS;
137 tsapi const char *TS_URL_SCHEME_WSS;
138 
139 /* URL schemes string lengths */
140 tsapi int TS_URL_LEN_FILE;
141 tsapi int TS_URL_LEN_FTP;
142 tsapi int TS_URL_LEN_GOPHER;
143 tsapi int TS_URL_LEN_HTTP;
144 tsapi int TS_URL_LEN_HTTPS;
145 tsapi int TS_URL_LEN_MAILTO;
146 tsapi int TS_URL_LEN_NEWS;
147 tsapi int TS_URL_LEN_NNTP;
148 tsapi int TS_URL_LEN_PROSPERO;
149 tsapi int TS_URL_LEN_TELNET;
150 tsapi int TS_URL_LEN_TUNNEL;
151 tsapi int TS_URL_LEN_WAIS;
152 tsapi int TS_URL_LEN_PNM;
153 tsapi int TS_URL_LEN_RTSP;
154 tsapi int TS_URL_LEN_RTSPU;
155 tsapi int TS_URL_LEN_MMS;
156 tsapi int TS_URL_LEN_MMSU;
157 tsapi int TS_URL_LEN_MMST;
158 tsapi int TS_URL_LEN_WS;
159 tsapi int TS_URL_LEN_WSS;
160 
161 /* MIME fields */
162 tsapi const char *TS_MIME_FIELD_ACCEPT;
163 tsapi const char *TS_MIME_FIELD_ACCEPT_CHARSET;
164 tsapi const char *TS_MIME_FIELD_ACCEPT_ENCODING;
165 tsapi const char *TS_MIME_FIELD_ACCEPT_LANGUAGE;
166 tsapi const char *TS_MIME_FIELD_ACCEPT_RANGES;
167 tsapi const char *TS_MIME_FIELD_AGE;
168 tsapi const char *TS_MIME_FIELD_ALLOW;
169 tsapi const char *TS_MIME_FIELD_APPROVED;
170 tsapi const char *TS_MIME_FIELD_AUTHORIZATION;
171 tsapi const char *TS_MIME_FIELD_BYTES;
172 tsapi const char *TS_MIME_FIELD_CACHE_CONTROL;
173 tsapi const char *TS_MIME_FIELD_CLIENT_IP;
174 tsapi const char *TS_MIME_FIELD_CONNECTION;
175 tsapi const char *TS_MIME_FIELD_CONTENT_BASE;
176 tsapi const char *TS_MIME_FIELD_CONTENT_ENCODING;
177 tsapi const char *TS_MIME_FIELD_CONTENT_LANGUAGE;
178 tsapi const char *TS_MIME_FIELD_CONTENT_LENGTH;
179 tsapi const char *TS_MIME_FIELD_CONTENT_LOCATION;
180 tsapi const char *TS_MIME_FIELD_CONTENT_MD5;
181 tsapi const char *TS_MIME_FIELD_CONTENT_RANGE;
182 tsapi const char *TS_MIME_FIELD_CONTENT_TYPE;
183 tsapi const char *TS_MIME_FIELD_CONTROL;
184 tsapi const char *TS_MIME_FIELD_COOKIE;
185 tsapi const char *TS_MIME_FIELD_DATE;
186 tsapi const char *TS_MIME_FIELD_DISTRIBUTION;
187 tsapi const char *TS_MIME_FIELD_ETAG;
188 tsapi const char *TS_MIME_FIELD_EXPECT;
189 tsapi const char *TS_MIME_FIELD_EXPIRES;
190 tsapi const char *TS_MIME_FIELD_FOLLOWUP_TO;
191 tsapi const char *TS_MIME_FIELD_FROM;
192 tsapi const char *TS_MIME_FIELD_HOST;
193 tsapi const char *TS_MIME_FIELD_IF_MATCH;
194 tsapi const char *TS_MIME_FIELD_IF_MODIFIED_SINCE;
195 tsapi const char *TS_MIME_FIELD_IF_NONE_MATCH;
196 tsapi const char *TS_MIME_FIELD_IF_RANGE;
197 tsapi const char *TS_MIME_FIELD_IF_UNMODIFIED_SINCE;
198 tsapi const char *TS_MIME_FIELD_KEEP_ALIVE;
199 tsapi const char *TS_MIME_FIELD_KEYWORDS;
200 tsapi const char *TS_MIME_FIELD_LAST_MODIFIED;
201 tsapi const char *TS_MIME_FIELD_LINES;
202 tsapi const char *TS_MIME_FIELD_LOCATION;
203 tsapi const char *TS_MIME_FIELD_MAX_FORWARDS;
204 tsapi const char *TS_MIME_FIELD_MESSAGE_ID;
205 tsapi const char *TS_MIME_FIELD_NEWSGROUPS;
206 tsapi const char *TS_MIME_FIELD_ORGANIZATION;
207 tsapi const char *TS_MIME_FIELD_PATH;
208 tsapi const char *TS_MIME_FIELD_PRAGMA;
209 tsapi const char *TS_MIME_FIELD_PROXY_AUTHENTICATE;
210 tsapi const char *TS_MIME_FIELD_PROXY_AUTHORIZATION;
211 tsapi const char *TS_MIME_FIELD_PROXY_CONNECTION;
212 tsapi const char *TS_MIME_FIELD_PUBLIC;
213 tsapi const char *TS_MIME_FIELD_RANGE;
214 tsapi const char *TS_MIME_FIELD_REFERENCES;
215 tsapi const char *TS_MIME_FIELD_REFERER;
216 tsapi const char *TS_MIME_FIELD_REPLY_TO;
217 tsapi const char *TS_MIME_FIELD_RETRY_AFTER;
218 tsapi const char *TS_MIME_FIELD_SENDER;
219 tsapi const char *TS_MIME_FIELD_SERVER;
220 tsapi const char *TS_MIME_FIELD_SET_COOKIE;
221 tsapi const char *TS_MIME_FIELD_STRICT_TRANSPORT_SECURITY;
222 tsapi const char *TS_MIME_FIELD_SUBJECT;
223 tsapi const char *TS_MIME_FIELD_SUMMARY;
224 tsapi const char *TS_MIME_FIELD_TE;
225 tsapi const char *TS_MIME_FIELD_TRANSFER_ENCODING;
226 tsapi const char *TS_MIME_FIELD_UPGRADE;
227 tsapi const char *TS_MIME_FIELD_USER_AGENT;
228 tsapi const char *TS_MIME_FIELD_VARY;
229 tsapi const char *TS_MIME_FIELD_VIA;
230 tsapi const char *TS_MIME_FIELD_WARNING;
231 tsapi const char *TS_MIME_FIELD_WWW_AUTHENTICATE;
232 tsapi const char *TS_MIME_FIELD_XREF;
233 tsapi const char *TS_MIME_FIELD_X_FORWARDED_FOR;
234 tsapi const char *TS_MIME_FIELD_FORWARDED;
235 
236 /* MIME fields string lengths */
237 tsapi int TS_MIME_LEN_ACCEPT;
238 tsapi int TS_MIME_LEN_ACCEPT_CHARSET;
239 tsapi int TS_MIME_LEN_ACCEPT_ENCODING;
240 tsapi int TS_MIME_LEN_ACCEPT_LANGUAGE;
241 tsapi int TS_MIME_LEN_ACCEPT_RANGES;
242 tsapi int TS_MIME_LEN_AGE;
243 tsapi int TS_MIME_LEN_ALLOW;
244 tsapi int TS_MIME_LEN_APPROVED;
245 tsapi int TS_MIME_LEN_AUTHORIZATION;
246 tsapi int TS_MIME_LEN_BYTES;
247 tsapi int TS_MIME_LEN_CACHE_CONTROL;
248 tsapi int TS_MIME_LEN_CLIENT_IP;
249 tsapi int TS_MIME_LEN_CONNECTION;
250 tsapi int TS_MIME_LEN_CONTENT_BASE;
251 tsapi int TS_MIME_LEN_CONTENT_ENCODING;
252 tsapi int TS_MIME_LEN_CONTENT_LANGUAGE;
253 tsapi int TS_MIME_LEN_CONTENT_LENGTH;
254 tsapi int TS_MIME_LEN_CONTENT_LOCATION;
255 tsapi int TS_MIME_LEN_CONTENT_MD5;
256 tsapi int TS_MIME_LEN_CONTENT_RANGE;
257 tsapi int TS_MIME_LEN_CONTENT_TYPE;
258 tsapi int TS_MIME_LEN_CONTROL;
259 tsapi int TS_MIME_LEN_COOKIE;
260 tsapi int TS_MIME_LEN_DATE;
261 tsapi int TS_MIME_LEN_DISTRIBUTION;
262 tsapi int TS_MIME_LEN_ETAG;
263 tsapi int TS_MIME_LEN_EXPECT;
264 tsapi int TS_MIME_LEN_EXPIRES;
265 tsapi int TS_MIME_LEN_FOLLOWUP_TO;
266 tsapi int TS_MIME_LEN_FROM;
267 tsapi int TS_MIME_LEN_HOST;
268 tsapi int TS_MIME_LEN_IF_MATCH;
269 tsapi int TS_MIME_LEN_IF_MODIFIED_SINCE;
270 tsapi int TS_MIME_LEN_IF_NONE_MATCH;
271 tsapi int TS_MIME_LEN_IF_RANGE;
272 tsapi int TS_MIME_LEN_IF_UNMODIFIED_SINCE;
273 tsapi int TS_MIME_LEN_KEEP_ALIVE;
274 tsapi int TS_MIME_LEN_KEYWORDS;
275 tsapi int TS_MIME_LEN_LAST_MODIFIED;
276 tsapi int TS_MIME_LEN_LINES;
277 tsapi int TS_MIME_LEN_LOCATION;
278 tsapi int TS_MIME_LEN_MAX_FORWARDS;
279 tsapi int TS_MIME_LEN_MESSAGE_ID;
280 tsapi int TS_MIME_LEN_NEWSGROUPS;
281 tsapi int TS_MIME_LEN_ORGANIZATION;
282 tsapi int TS_MIME_LEN_PATH;
283 tsapi int TS_MIME_LEN_PRAGMA;
284 tsapi int TS_MIME_LEN_PROXY_AUTHENTICATE;
285 tsapi int TS_MIME_LEN_PROXY_AUTHORIZATION;
286 tsapi int TS_MIME_LEN_PROXY_CONNECTION;
287 tsapi int TS_MIME_LEN_PUBLIC;
288 tsapi int TS_MIME_LEN_RANGE;
289 tsapi int TS_MIME_LEN_REFERENCES;
290 tsapi int TS_MIME_LEN_REFERER;
291 tsapi int TS_MIME_LEN_REPLY_TO;
292 tsapi int TS_MIME_LEN_RETRY_AFTER;
293 tsapi int TS_MIME_LEN_SENDER;
294 tsapi int TS_MIME_LEN_SERVER;
295 tsapi int TS_MIME_LEN_SET_COOKIE;
296 tsapi int TS_MIME_LEN_STRICT_TRANSPORT_SECURITY;
297 tsapi int TS_MIME_LEN_SUBJECT;
298 tsapi int TS_MIME_LEN_SUMMARY;
299 tsapi int TS_MIME_LEN_TE;
300 tsapi int TS_MIME_LEN_TRANSFER_ENCODING;
301 tsapi int TS_MIME_LEN_UPGRADE;
302 tsapi int TS_MIME_LEN_USER_AGENT;
303 tsapi int TS_MIME_LEN_VARY;
304 tsapi int TS_MIME_LEN_VIA;
305 tsapi int TS_MIME_LEN_WARNING;
306 tsapi int TS_MIME_LEN_WWW_AUTHENTICATE;
307 tsapi int TS_MIME_LEN_XREF;
308 tsapi int TS_MIME_LEN_X_FORWARDED_FOR;
309 tsapi int TS_MIME_LEN_FORWARDED;
310 
311 /* HTTP miscellaneous values */
312 tsapi const char *TS_HTTP_VALUE_BYTES;
313 tsapi const char *TS_HTTP_VALUE_CHUNKED;
314 tsapi const char *TS_HTTP_VALUE_CLOSE;
315 tsapi const char *TS_HTTP_VALUE_COMPRESS;
316 tsapi const char *TS_HTTP_VALUE_DEFLATE;
317 tsapi const char *TS_HTTP_VALUE_GZIP;
318 tsapi const char *TS_HTTP_VALUE_IDENTITY;
319 tsapi const char *TS_HTTP_VALUE_KEEP_ALIVE;
320 tsapi const char *TS_HTTP_VALUE_MAX_AGE;
321 tsapi const char *TS_HTTP_VALUE_MAX_STALE;
322 tsapi const char *TS_HTTP_VALUE_MIN_FRESH;
323 tsapi const char *TS_HTTP_VALUE_MUST_REVALIDATE;
324 tsapi const char *TS_HTTP_VALUE_NONE;
325 tsapi const char *TS_HTTP_VALUE_NO_CACHE;
326 tsapi const char *TS_HTTP_VALUE_NO_STORE;
327 tsapi const char *TS_HTTP_VALUE_NO_TRANSFORM;
328 tsapi const char *TS_HTTP_VALUE_ONLY_IF_CACHED;
329 tsapi const char *TS_HTTP_VALUE_PRIVATE;
330 tsapi const char *TS_HTTP_VALUE_PROXY_REVALIDATE;
331 tsapi const char *TS_HTTP_VALUE_PUBLIC;
332 tsapi const char *TS_HTTP_VALUE_S_MAXAGE;
333 
334 /* HTTP miscellaneous values string lengths */
335 tsapi int TS_HTTP_LEN_BYTES;
336 tsapi int TS_HTTP_LEN_CHUNKED;
337 tsapi int TS_HTTP_LEN_CLOSE;
338 tsapi int TS_HTTP_LEN_COMPRESS;
339 tsapi int TS_HTTP_LEN_DEFLATE;
340 tsapi int TS_HTTP_LEN_GZIP;
341 tsapi int TS_HTTP_LEN_IDENTITY;
342 tsapi int TS_HTTP_LEN_KEEP_ALIVE;
343 tsapi int TS_HTTP_LEN_MAX_AGE;
344 tsapi int TS_HTTP_LEN_MAX_STALE;
345 tsapi int TS_HTTP_LEN_MIN_FRESH;
346 tsapi int TS_HTTP_LEN_MUST_REVALIDATE;
347 tsapi int TS_HTTP_LEN_NONE;
348 tsapi int TS_HTTP_LEN_NO_CACHE;
349 tsapi int TS_HTTP_LEN_NO_STORE;
350 tsapi int TS_HTTP_LEN_NO_TRANSFORM;
351 tsapi int TS_HTTP_LEN_ONLY_IF_CACHED;
352 tsapi int TS_HTTP_LEN_PRIVATE;
353 tsapi int TS_HTTP_LEN_PROXY_REVALIDATE;
354 tsapi int TS_HTTP_LEN_PUBLIC;
355 tsapi int TS_HTTP_LEN_S_MAXAGE;
356 
357 /* HTTP methods */
358 tsapi const char *TS_HTTP_METHOD_CONNECT;
359 tsapi const char *TS_HTTP_METHOD_DELETE;
360 tsapi const char *TS_HTTP_METHOD_GET;
361 tsapi const char *TS_HTTP_METHOD_HEAD;
362 tsapi const char *TS_HTTP_METHOD_OPTIONS;
363 tsapi const char *TS_HTTP_METHOD_POST;
364 tsapi const char *TS_HTTP_METHOD_PURGE;
365 tsapi const char *TS_HTTP_METHOD_PUT;
366 tsapi const char *TS_HTTP_METHOD_TRACE;
367 tsapi const char *TS_HTTP_METHOD_PUSH;
368 
369 /* HTTP methods string lengths */
370 tsapi int TS_HTTP_LEN_CONNECT;
371 tsapi int TS_HTTP_LEN_DELETE;
372 tsapi int TS_HTTP_LEN_GET;
373 tsapi int TS_HTTP_LEN_HEAD;
374 tsapi int TS_HTTP_LEN_OPTIONS;
375 tsapi int TS_HTTP_LEN_POST;
376 tsapi int TS_HTTP_LEN_PURGE;
377 tsapi int TS_HTTP_LEN_PUT;
378 tsapi int TS_HTTP_LEN_TRACE;
379 tsapi int TS_HTTP_LEN_PUSH;
380 
381 HttpAPIHooks *http_global_hooks        = nullptr;
382 SslAPIHooks *ssl_hooks                 = nullptr;
383 LifecycleAPIHooks *lifecycle_hooks     = nullptr;
384 ConfigUpdateCbTable *global_config_cbs = nullptr;
385 
386 static char traffic_server_version[128] = "";
387 static int ts_major_version             = 0;
388 static int ts_minor_version             = 0;
389 static int ts_patch_version             = 0;
390 
391 static ClassAllocator<APIHook> apiHookAllocator("apiHookAllocator");
392 static ClassAllocator<INKContInternal> INKContAllocator("INKContAllocator");
393 static ClassAllocator<INKVConnInternal> INKVConnAllocator("INKVConnAllocator");
394 static ClassAllocator<MIMEFieldSDKHandle> mHandleAllocator("MIMEFieldSDKHandle");
395 
396 ////////////////////////////////////////////////////////////////////
397 //
398 // API error logging
399 //
400 ////////////////////////////////////////////////////////////////////
401 
402 void
TSStatus(const char * fmt,...)403 TSStatus(const char *fmt, ...)
404 {
405   va_list args;
406 
407   va_start(args, fmt);
408   StatusV(fmt, args);
409   va_end(args);
410 }
411 
412 void
TSNote(const char * fmt,...)413 TSNote(const char *fmt, ...)
414 {
415   va_list args;
416 
417   va_start(args, fmt);
418   NoteV(fmt, args);
419   va_end(args);
420 }
421 
422 void
TSWarning(const char * fmt,...)423 TSWarning(const char *fmt, ...)
424 {
425   va_list args;
426 
427   va_start(args, fmt);
428   WarningV(fmt, args);
429   va_end(args);
430 }
431 
432 void
TSError(const char * fmt,...)433 TSError(const char *fmt, ...)
434 {
435   va_list args;
436 
437   va_start(args, fmt);
438   ErrorV(fmt, args);
439   va_end(args);
440 }
441 
442 void
TSFatal(const char * fmt,...)443 TSFatal(const char *fmt, ...)
444 {
445   va_list args;
446 
447   va_start(args, fmt);
448   FatalV(fmt, args);
449   va_end(args);
450 }
451 
452 void
TSAlert(const char * fmt,...)453 TSAlert(const char *fmt, ...)
454 {
455   va_list args;
456 
457   va_start(args, fmt);
458   AlertV(fmt, args);
459   va_end(args);
460 }
461 
462 void
TSEmergency(const char * fmt,...)463 TSEmergency(const char *fmt, ...)
464 {
465   va_list args;
466 
467   va_start(args, fmt);
468   EmergencyV(fmt, args);
469   va_end(args);
470 }
471 
472 // Assert in debug AND optim
473 void
_TSReleaseAssert(const char * text,const char * file,int line)474 _TSReleaseAssert(const char *text, const char *file, int line)
475 {
476   _ink_assert(text, file, line);
477 }
478 
479 // Assert only in debug
480 int
481 #ifdef DEBUG
_TSAssert(const char * text,const char * file,int line)482 _TSAssert(const char *text, const char *file, int line)
483 {
484   _ink_assert(text, file, line);
485   return 0;
486 }
487 #else
488 _TSAssert(const char *, const char *, int)
489 {
490   return 0;
491 }
492 #endif
493 
494 // This assert is for internal API use only.
495 #if TS_USE_FAST_SDK
496 #define sdk_assert(EX) (void)(EX)
497 #else
498 #define sdk_assert(EX) ((void)((EX) ? (void)0 : _TSReleaseAssert(#EX, __FILE__, __LINE__)))
499 #endif
500 
501 ////////////////////////////////////////////////////////////////////
502 //
503 // SDK Interoperability Support
504 //
505 // ----------------------------------------------------------------
506 //
507 // Standalone Fields (SDK Version-Interoperability Hack)
508 //
509 //
510 // A "standalone" field is an ugly hack for portability with old
511 // versions of the SDK that mirrored the old header system.  In
512 // the old system, you could create arbitrary tiny little field
513 // objects, distinct from MIME header objects, and link them
514 // together.  In the new header system, all fields are internal
515 // constituents of the MIME header.  To preserve the semantics of
516 // the old SDK, we need to maintain the concept of fields that
517 // are created outside of a MIME header.  Whenever a field is
518 // "attached" to a MIME header, it is copied into the MIME header
519 // field's slot, and the handle to the field is updated to refer
520 // to the new field.
521 //
522 // Hopefully, we can eliminate this old compatibility interface and
523 // migrate users to the newer semantics quickly.
524 //
525 // ----------------------------------------------------------------
526 //
527 // MIMEField SDK Handles (SDK Version-Interoperability Hack)
528 //
529 // MIMEField "handles" are used by the SDK as an indirect reference
530 // to the MIMEField.  Because versions 1 & 2 of the SDK allowed
531 // standalone fields that existed without associated MIME headers,
532 // and because the version 3 SDK requires an associated MIME header
533 // for all field mutation operations (for presence bits, etc.) we
534 // need a data structure that:
535 //
536 //   * identifies standalone fields and stores field name/value
537 //     information for fields that are not yet in a header
538 //   * redirects the field to a real header field when the field
539 //     is inserted into a header
540 //   * maintains the associated MIMEHdrImpl when returning field
541 //     slots from lookup and create functions
542 //
543 // If the MIMEHdrImpl pointer is NULL, then the handle points
544 // to a standalone field, otherwise the handle points to a field
545 // within the MIME header.
546 //
547 ////////////////////////////////////////////////////////////////////
548 
549 /*****************************************************************/
550 /* Handles to headers are impls, but need to handle MIME or HTTP */
551 /*****************************************************************/
552 
553 inline MIMEHdrImpl *
_hdr_obj_to_mime_hdr_impl(HdrHeapObjImpl * obj)554 _hdr_obj_to_mime_hdr_impl(HdrHeapObjImpl *obj)
555 {
556   MIMEHdrImpl *impl;
557   if (obj->m_type == HDR_HEAP_OBJ_HTTP_HEADER) {
558     impl = ((HTTPHdrImpl *)obj)->m_fields_impl;
559   } else if (obj->m_type == HDR_HEAP_OBJ_MIME_HEADER) {
560     impl = (MIMEHdrImpl *)obj;
561   } else {
562     ink_release_assert(!"mloc not a header type");
563     impl = nullptr; /* gcc does not know about 'ink_release_assert' - make it happy */
564   }
565   return impl;
566 }
567 
568 inline MIMEHdrImpl *
_hdr_mloc_to_mime_hdr_impl(TSMLoc mloc)569 _hdr_mloc_to_mime_hdr_impl(TSMLoc mloc)
570 {
571   return _hdr_obj_to_mime_hdr_impl((HdrHeapObjImpl *)mloc);
572 }
573 
574 TSReturnCode
sdk_sanity_check_field_handle(TSMLoc field,TSMLoc parent_hdr=nullptr)575 sdk_sanity_check_field_handle(TSMLoc field, TSMLoc parent_hdr = nullptr)
576 {
577   if (field == TS_NULL_MLOC) {
578     return TS_ERROR;
579   }
580 
581   MIMEFieldSDKHandle *field_handle = (MIMEFieldSDKHandle *)field;
582   if (field_handle->m_type != HDR_HEAP_OBJ_FIELD_SDK_HANDLE) {
583     return TS_ERROR;
584   }
585 
586   if (parent_hdr != nullptr) {
587     MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(parent_hdr);
588     if (field_handle->mh != mh) {
589       return TS_ERROR;
590     }
591   }
592   return TS_SUCCESS;
593 }
594 
595 TSReturnCode
sdk_sanity_check_mbuffer(TSMBuffer bufp)596 sdk_sanity_check_mbuffer(TSMBuffer bufp)
597 {
598   HdrHeapSDKHandle *handle = (HdrHeapSDKHandle *)bufp;
599   if ((handle == nullptr) || (handle->m_heap == nullptr) || (handle->m_heap->m_magic != HDR_BUF_MAGIC_ALIVE)) {
600     return TS_ERROR;
601   }
602 
603   return TS_SUCCESS;
604 }
605 
606 TSReturnCode
sdk_sanity_check_mime_hdr_handle(TSMLoc field)607 sdk_sanity_check_mime_hdr_handle(TSMLoc field)
608 {
609   if (field == TS_NULL_MLOC) {
610     return TS_ERROR;
611   }
612 
613   MIMEFieldSDKHandle *field_handle = (MIMEFieldSDKHandle *)field;
614   if (field_handle->m_type != HDR_HEAP_OBJ_MIME_HEADER) {
615     return TS_ERROR;
616   }
617 
618   return TS_SUCCESS;
619 }
620 
621 TSReturnCode
sdk_sanity_check_url_handle(TSMLoc field)622 sdk_sanity_check_url_handle(TSMLoc field)
623 {
624   if (field == TS_NULL_MLOC) {
625     return TS_ERROR;
626   }
627 
628   MIMEFieldSDKHandle *field_handle = (MIMEFieldSDKHandle *)field;
629   if (field_handle->m_type != HDR_HEAP_OBJ_URL) {
630     return TS_ERROR;
631   }
632 
633   return TS_SUCCESS;
634 }
635 
636 TSReturnCode
sdk_sanity_check_http_hdr_handle(TSMLoc field)637 sdk_sanity_check_http_hdr_handle(TSMLoc field)
638 {
639   if (field == TS_NULL_MLOC) {
640     return TS_ERROR;
641   }
642 
643   HTTPHdrImpl *field_handle = (HTTPHdrImpl *)field;
644   if (field_handle->m_type != HDR_HEAP_OBJ_HTTP_HEADER) {
645     return TS_ERROR;
646   }
647 
648   return TS_SUCCESS;
649 }
650 
651 TSReturnCode
sdk_sanity_check_continuation(TSCont cont)652 sdk_sanity_check_continuation(TSCont cont)
653 {
654   if ((cont == nullptr) || (((INKContInternal *)cont)->m_free_magic == INKCONT_INTERN_MAGIC_DEAD)) {
655     return TS_ERROR;
656   }
657 
658   return TS_SUCCESS;
659 }
660 
661 TSReturnCode
sdk_sanity_check_fetch_sm(TSFetchSM fetch_sm)662 sdk_sanity_check_fetch_sm(TSFetchSM fetch_sm)
663 {
664   if (fetch_sm == nullptr) {
665     return TS_ERROR;
666   }
667 
668   return TS_SUCCESS;
669 }
670 
671 TSReturnCode
sdk_sanity_check_http_ssn(TSHttpSsn ssnp)672 sdk_sanity_check_http_ssn(TSHttpSsn ssnp)
673 {
674   if (ssnp == nullptr) {
675     return TS_ERROR;
676   }
677 
678   return TS_SUCCESS;
679 }
680 
681 TSReturnCode
sdk_sanity_check_txn(TSHttpTxn txnp)682 sdk_sanity_check_txn(TSHttpTxn txnp)
683 {
684   if ((txnp != nullptr) && (((HttpSM *)txnp)->magic == HTTP_SM_MAGIC_ALIVE)) {
685     return TS_SUCCESS;
686   }
687   return TS_ERROR;
688 }
689 
690 TSReturnCode
sdk_sanity_check_mime_parser(TSMimeParser parser)691 sdk_sanity_check_mime_parser(TSMimeParser parser)
692 {
693   if (parser == nullptr) {
694     return TS_ERROR;
695   }
696   return TS_SUCCESS;
697 }
698 
699 TSReturnCode
sdk_sanity_check_http_parser(TSHttpParser parser)700 sdk_sanity_check_http_parser(TSHttpParser parser)
701 {
702   if (parser == nullptr) {
703     return TS_ERROR;
704   }
705   return TS_SUCCESS;
706 }
707 
708 TSReturnCode
sdk_sanity_check_alt_info(TSHttpAltInfo info)709 sdk_sanity_check_alt_info(TSHttpAltInfo info)
710 {
711   if (info == nullptr) {
712     return TS_ERROR;
713   }
714   return TS_SUCCESS;
715 }
716 
717 TSReturnCode
sdk_sanity_check_hook_id(TSHttpHookID id)718 sdk_sanity_check_hook_id(TSHttpHookID id)
719 {
720   return HttpAPIHooks::is_valid(id) ? TS_SUCCESS : TS_ERROR;
721 }
722 
723 TSReturnCode
sdk_sanity_check_lifecycle_hook_id(TSLifecycleHookID id)724 sdk_sanity_check_lifecycle_hook_id(TSLifecycleHookID id)
725 {
726   return LifecycleAPIHooks::is_valid(id) ? TS_SUCCESS : TS_ERROR;
727 }
728 
729 TSReturnCode
sdk_sanity_check_ssl_hook_id(TSHttpHookID id)730 sdk_sanity_check_ssl_hook_id(TSHttpHookID id)
731 {
732   if (id < TS_SSL_FIRST_HOOK || id > TS_SSL_LAST_HOOK) {
733     return TS_ERROR;
734   }
735   return TS_SUCCESS;
736 }
737 
738 TSReturnCode
sdk_sanity_check_null_ptr(void const * ptr)739 sdk_sanity_check_null_ptr(void const *ptr)
740 {
741   return ptr == nullptr ? TS_ERROR : TS_SUCCESS;
742 }
743 
744 // Plugin metric IDs index the plugin RSB, so bounds check against that.
745 static TSReturnCode
sdk_sanity_check_stat_id(int id)746 sdk_sanity_check_stat_id(int id)
747 {
748   if (id < 0 || id >= api_rsb->max_stats) {
749     return TS_ERROR;
750   }
751 
752   return TS_SUCCESS;
753 }
754 
755 /**
756   The function checks if the buffer is Modifiable and returns true if
757   it is modifiable, else returns false.
758 
759 */
760 bool
isWriteable(TSMBuffer bufp)761 isWriteable(TSMBuffer bufp)
762 {
763   if (bufp != nullptr) {
764     return ((HdrHeapSDKHandle *)bufp)->m_heap->m_writeable;
765   }
766   return false;
767 }
768 
769 /******************************************************/
770 /* Allocators for field handles and standalone fields */
771 /******************************************************/
772 static MIMEFieldSDKHandle *
sdk_alloc_field_handle(TSMBuffer,MIMEHdrImpl * mh)773 sdk_alloc_field_handle(TSMBuffer /* bufp ATS_UNUSED */, MIMEHdrImpl *mh)
774 {
775   MIMEFieldSDKHandle *handle = THREAD_ALLOC(mHandleAllocator, this_thread());
776 
777   // TODO: Should remove this when memory allocation can't fail.
778   sdk_assert(sdk_sanity_check_null_ptr((void *)handle) == TS_SUCCESS);
779 
780   obj_init_header(handle, HDR_HEAP_OBJ_FIELD_SDK_HANDLE, sizeof(MIMEFieldSDKHandle), 0);
781   handle->mh = mh;
782 
783   return handle;
784 }
785 
786 static void
sdk_free_field_handle(TSMBuffer bufp,MIMEFieldSDKHandle * field_handle)787 sdk_free_field_handle(TSMBuffer bufp, MIMEFieldSDKHandle *field_handle)
788 {
789   if (sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS) {
790     THREAD_FREE(field_handle, mHandleAllocator, this_thread());
791   }
792 }
793 
794 ////////////////////////////////////////////////////////////////////
795 //
796 // FileImpl
797 //
798 ////////////////////////////////////////////////////////////////////
FileImpl()799 FileImpl::FileImpl() : m_fd(-1), m_mode(CLOSED), m_buf(nullptr), m_bufsize(0), m_bufpos(0) {}
800 
~FileImpl()801 FileImpl::~FileImpl()
802 {
803   fclose();
804 }
805 
806 int
fopen(const char * filename,const char * mode)807 FileImpl::fopen(const char *filename, const char *mode)
808 {
809   if (mode[0] == '\0') {
810     return 0;
811   } else if (mode[0] == 'r') {
812     if (mode[1] != '\0') {
813       return 0;
814     }
815     m_mode = READ;
816     m_fd   = open(filename, O_RDONLY);
817   } else if (mode[0] == 'w') {
818     if (mode[1] != '\0') {
819       return 0;
820     }
821     m_mode = WRITE;
822     m_fd   = open(filename, O_WRONLY | O_CREAT, 0644);
823   } else if (mode[0] == 'a') {
824     if (mode[1] != '\0') {
825       return 0;
826     }
827     m_mode = WRITE;
828     m_fd   = open(filename, O_WRONLY | O_CREAT | O_APPEND, 0644);
829   }
830 
831   if (m_fd < 0) {
832     m_mode = CLOSED;
833     return 0;
834   } else {
835     return 1;
836   }
837 }
838 
839 void
fclose()840 FileImpl::fclose()
841 {
842   if (m_fd != -1) {
843     fflush();
844 
845     close(m_fd);
846     m_fd   = -1;
847     m_mode = CLOSED;
848   }
849 
850   if (m_buf) {
851     ats_free(m_buf);
852     m_buf     = nullptr;
853     m_bufsize = 0;
854     m_bufpos  = 0;
855   }
856 }
857 
858 ssize_t
fread(void * buf,size_t length)859 FileImpl::fread(void *buf, size_t length)
860 {
861   size_t amount;
862   ssize_t err;
863 
864   if ((m_mode != READ) || (m_fd == -1)) {
865     return -1;
866   }
867 
868   if (!m_buf) {
869     m_bufpos  = 0;
870     m_bufsize = 1024;
871     m_buf     = (char *)ats_malloc(m_bufsize);
872   }
873 
874   if (m_bufpos < length) {
875     amount = length;
876     if (amount < 1024) {
877       amount = 1024;
878     }
879     if (amount > (m_bufsize - m_bufpos)) {
880       while (amount > (m_bufsize - m_bufpos)) {
881         m_bufsize *= 2;
882       }
883       m_buf = (char *)ats_realloc(m_buf, m_bufsize);
884     }
885 
886     do {
887       err = read(m_fd, &m_buf[m_bufpos], amount);
888     } while ((err < 0) && (errno == EINTR));
889 
890     if (err < 0) {
891       return -1;
892     }
893 
894     m_bufpos += err;
895   }
896 
897   if (buf) {
898     amount = length;
899     if (amount > m_bufpos) {
900       amount = m_bufpos;
901     }
902     memcpy(buf, m_buf, amount);
903     memmove(m_buf, &m_buf[amount], m_bufpos - amount);
904     m_bufpos -= amount;
905     return amount;
906   } else {
907     return m_bufpos;
908   }
909 }
910 
911 ssize_t
fwrite(const void * buf,size_t length)912 FileImpl::fwrite(const void *buf, size_t length)
913 {
914   const char *p, *e;
915   size_t avail;
916 
917   if ((m_mode != WRITE) || (m_fd == -1)) {
918     return -1;
919   }
920 
921   if (!m_buf) {
922     m_bufpos  = 0;
923     m_bufsize = 1024;
924     m_buf     = (char *)ats_malloc(m_bufsize);
925   }
926 
927   p = (const char *)buf;
928   e = p + length;
929 
930   while (p != e) {
931     avail = m_bufsize - m_bufpos;
932     if (avail > length) {
933       avail = length;
934     }
935     memcpy(&m_buf[m_bufpos], p, avail);
936 
937     m_bufpos += avail;
938     p += avail;
939     length -= avail;
940 
941     if ((length > 0) && (m_bufpos > 0)) {
942       if (fflush() <= 0) {
943         break;
944       }
945     }
946   }
947 
948   return (p - (const char *)buf);
949 }
950 
951 ssize_t
fflush()952 FileImpl::fflush()
953 {
954   char *p, *e;
955   ssize_t err = 0;
956 
957   if ((m_mode != WRITE) || (m_fd == -1)) {
958     return -1;
959   }
960 
961   if (m_buf) {
962     p = m_buf;
963     e = &m_buf[m_bufpos];
964 
965     while (p != e) {
966       do {
967         err = write(m_fd, p, e - p);
968       } while ((err < 0) && (errno == EINTR));
969 
970       if (err < 0) {
971         break;
972       }
973 
974       p += err;
975     }
976 
977     err = p - m_buf;
978     memmove(m_buf, &m_buf[err], m_bufpos - err);
979     m_bufpos -= err;
980   }
981 
982   return err;
983 }
984 
985 char *
fgets(char * buf,size_t length)986 FileImpl::fgets(char *buf, size_t length)
987 {
988   char *e;
989   size_t pos;
990 
991   if (length == 0) {
992     return nullptr;
993   }
994 
995   if (!m_buf || (m_bufpos < (length - 1))) {
996     pos = m_bufpos;
997 
998     if (fread(nullptr, length - 1) < 0) {
999       return nullptr;
1000     }
1001 
1002     if (!m_bufpos && (pos == m_bufpos)) {
1003       return nullptr;
1004     }
1005   }
1006 
1007   e = (char *)memchr(m_buf, '\n', m_bufpos);
1008   if (e) {
1009     e += 1;
1010     if (length > (size_t)(e - m_buf + 1)) {
1011       length = e - m_buf + 1;
1012     }
1013   }
1014 
1015   ssize_t rlen = fread(buf, length - 1);
1016   if (rlen >= 0) {
1017     buf[rlen] = '\0';
1018   }
1019 
1020   return buf;
1021 }
1022 
1023 ////////////////////////////////////////////////////////////////////
1024 //
1025 // INKContInternal
1026 //
1027 ////////////////////////////////////////////////////////////////////
1028 
INKContInternal()1029 INKContInternal::INKContInternal()
1030   : DummyVConnection(nullptr),
1031     mdata(nullptr),
1032     m_event_func(nullptr),
1033     m_event_count(0),
1034     m_closed(1),
1035     m_deletable(0),
1036     m_deleted(0),
1037     m_context(0),
1038     m_free_magic(INKCONT_INTERN_MAGIC_ALIVE)
1039 {
1040 }
1041 
INKContInternal(TSEventFunc funcp,TSMutex mutexp)1042 INKContInternal::INKContInternal(TSEventFunc funcp, TSMutex mutexp)
1043   : DummyVConnection((ProxyMutex *)mutexp),
1044     mdata(nullptr),
1045     m_event_func(funcp),
1046     m_event_count(0),
1047     m_closed(1),
1048     m_deletable(0),
1049     m_deleted(0),
1050     m_context(0),
1051     m_free_magic(INKCONT_INTERN_MAGIC_ALIVE)
1052 {
1053   SET_HANDLER(&INKContInternal::handle_event);
1054 }
1055 
1056 void
init(TSEventFunc funcp,TSMutex mutexp,void * context)1057 INKContInternal::init(TSEventFunc funcp, TSMutex mutexp, void *context)
1058 {
1059   SET_HANDLER(&INKContInternal::handle_event);
1060 
1061   mutex        = (ProxyMutex *)mutexp;
1062   m_event_func = funcp;
1063   m_context    = context;
1064 }
1065 
1066 void
clear()1067 INKContInternal::clear()
1068 {
1069 }
1070 
1071 void
free()1072 INKContInternal::free()
1073 {
1074   clear();
1075   this->mutex.clear();
1076   m_free_magic = INKCONT_INTERN_MAGIC_DEAD;
1077   THREAD_FREE(this, INKContAllocator, this_thread());
1078 }
1079 
1080 void
destroy()1081 INKContInternal::destroy()
1082 {
1083   if (m_free_magic == INKCONT_INTERN_MAGIC_DEAD) {
1084     ink_release_assert(!"Plugin tries to use a continuation which is deleted");
1085   }
1086   m_deleted = 1;
1087   if (m_deletable) {
1088     free();
1089   } else {
1090     // TODO: Should this schedule on some other "thread" ?
1091     // TODO: we don't care about the return action?
1092     if (ink_atomic_increment((int *)&m_event_count, 1) < 0) {
1093       ink_assert(!"not reached");
1094     }
1095     EThread *p = this_ethread();
1096 
1097     // If this_thread() returns null, the EThread object for the current thread has been destroyed (or it never existed).
1098     // Presumably this will only happen during destruction of statically-initialized objects at TS shutdown, so no further
1099     // action is needed.
1100     //
1101     if (p) {
1102       p->schedule_imm(this);
1103     }
1104   }
1105 }
1106 
1107 void
handle_event_count(int event)1108 INKContInternal::handle_event_count(int event)
1109 {
1110   if ((event == EVENT_IMMEDIATE) || (event == EVENT_INTERVAL) || event == TS_EVENT_HTTP_TXN_CLOSE) {
1111     int val = ink_atomic_increment((int *)&m_event_count, -1);
1112     if (val <= 0) {
1113       ink_assert(!"not reached");
1114     }
1115 
1116     m_deletable = (m_closed != 0) && (val == 1);
1117   }
1118 }
1119 
1120 int
handle_event(int event,void * edata)1121 INKContInternal::handle_event(int event, void *edata)
1122 {
1123   if (m_free_magic == INKCONT_INTERN_MAGIC_DEAD) {
1124     ink_release_assert(!"Plugin tries to use a continuation which is deleted");
1125   }
1126   handle_event_count(event);
1127   if (m_deleted) {
1128     if (m_deletable) {
1129       free();
1130     } else {
1131       Debug("plugin", "INKCont Deletable but not deleted %d", m_event_count);
1132     }
1133   } else {
1134     /* set the plugin context */
1135     auto *previousContext = pluginThreadContext;
1136     pluginThreadContext   = reinterpret_cast<PluginThreadContext *>(m_context);
1137     int retval            = m_event_func((TSCont)this, (TSEvent)event, edata);
1138     pluginThreadContext   = previousContext;
1139     if (edata && event == EVENT_INTERVAL) {
1140       Event *e = reinterpret_cast<Event *>(edata);
1141       if (e->period != 0) {
1142         // In the interval case, we must re-increment the m_event_count for
1143         // the next go around.  Otherwise, our event count will go negative.
1144         ink_release_assert(ink_atomic_increment((int *)&this->m_event_count, 1) >= 0);
1145       }
1146     }
1147     return retval;
1148   }
1149   return EVENT_DONE;
1150 }
1151 
1152 ////////////////////////////////////////////////////////////////////
1153 //
1154 // INKVConnInternal
1155 //
1156 ////////////////////////////////////////////////////////////////////
1157 
INKVConnInternal()1158 INKVConnInternal::INKVConnInternal() : INKContInternal(), m_read_vio(), m_write_vio(), m_output_vc(nullptr)
1159 {
1160   m_closed = 0;
1161 }
1162 
INKVConnInternal(TSEventFunc funcp,TSMutex mutexp)1163 INKVConnInternal::INKVConnInternal(TSEventFunc funcp, TSMutex mutexp)
1164   : INKContInternal(funcp, mutexp), m_read_vio(), m_write_vio(), m_output_vc(nullptr)
1165 {
1166   m_closed = 0;
1167 }
1168 
1169 void
clear()1170 INKVConnInternal::clear()
1171 {
1172   m_read_vio.set_continuation(nullptr);
1173   m_write_vio.set_continuation(nullptr);
1174   INKContInternal::clear();
1175 }
1176 
1177 void
free()1178 INKVConnInternal::free()
1179 {
1180   clear();
1181   this->mutex.clear();
1182   m_free_magic = INKCONT_INTERN_MAGIC_DEAD;
1183   THREAD_FREE(this, INKVConnAllocator, this_thread());
1184 }
1185 
1186 void
destroy()1187 INKVConnInternal::destroy()
1188 {
1189   if (m_free_magic == INKCONT_INTERN_MAGIC_DEAD) {
1190     ink_release_assert(!"Plugin tries to use a vconnection which is deleted");
1191   }
1192 
1193   m_deleted = 1;
1194   if (m_deletable) {
1195     free();
1196   }
1197 }
1198 
1199 VIO *
do_io_read(Continuation * c,int64_t nbytes,MIOBuffer * buf)1200 INKVConnInternal::do_io_read(Continuation *c, int64_t nbytes, MIOBuffer *buf)
1201 {
1202   m_read_vio.buffer.writer_for(buf);
1203   m_read_vio.op = VIO::READ;
1204   m_read_vio.set_continuation(c);
1205   m_read_vio.nbytes    = nbytes;
1206   m_read_vio.ndone     = 0;
1207   m_read_vio.vc_server = this;
1208 
1209   if (ink_atomic_increment((int *)&m_event_count, 1) < 0) {
1210     ink_assert(!"not reached");
1211   }
1212   eventProcessor.schedule_imm(this, ET_NET);
1213 
1214   return &m_read_vio;
1215 }
1216 
1217 VIO *
do_io_write(Continuation * c,int64_t nbytes,IOBufferReader * buf,bool owner)1218 INKVConnInternal::do_io_write(Continuation *c, int64_t nbytes, IOBufferReader *buf, bool owner)
1219 {
1220   ink_assert(!owner);
1221   m_write_vio.buffer.reader_for(buf);
1222   m_write_vio.op = VIO::WRITE;
1223   m_write_vio.set_continuation(c);
1224   m_write_vio.nbytes    = nbytes;
1225   m_write_vio.ndone     = 0;
1226   m_write_vio.vc_server = this;
1227 
1228   if (m_write_vio.buffer.reader()->read_avail() > 0) {
1229     if (ink_atomic_increment((int *)&m_event_count, 1) < 0) {
1230       ink_assert(!"not reached");
1231     }
1232     eventProcessor.schedule_imm(this, ET_NET);
1233   }
1234 
1235   return &m_write_vio;
1236 }
1237 
1238 void
do_io_transform(VConnection * vc)1239 INKVConnInternal::do_io_transform(VConnection *vc)
1240 {
1241   m_output_vc = vc;
1242 }
1243 
1244 void
do_io_close(int error)1245 INKVConnInternal::do_io_close(int error)
1246 {
1247   if (ink_atomic_increment((int *)&m_event_count, 1) < 0) {
1248     ink_assert(!"not reached");
1249   }
1250 
1251   INK_WRITE_MEMORY_BARRIER;
1252 
1253   if (error != -1) {
1254     lerrno   = error;
1255     m_closed = TS_VC_CLOSE_ABORT;
1256   } else {
1257     m_closed = TS_VC_CLOSE_NORMAL;
1258   }
1259 
1260   m_read_vio.op = VIO::NONE;
1261   m_read_vio.buffer.clear();
1262 
1263   m_write_vio.op = VIO::NONE;
1264   m_write_vio.buffer.clear();
1265 
1266   if (m_output_vc) {
1267     m_output_vc->do_io_close(error);
1268     m_output_vc = nullptr;
1269   }
1270 
1271   eventProcessor.schedule_imm(this, ET_NET);
1272 }
1273 
1274 void
do_io_shutdown(ShutdownHowTo_t howto)1275 INKVConnInternal::do_io_shutdown(ShutdownHowTo_t howto)
1276 {
1277   if ((howto == IO_SHUTDOWN_READ) || (howto == IO_SHUTDOWN_READWRITE)) {
1278     m_read_vio.op = VIO::NONE;
1279     m_read_vio.buffer.clear();
1280   }
1281 
1282   if ((howto == IO_SHUTDOWN_WRITE) || (howto == IO_SHUTDOWN_READWRITE)) {
1283     m_write_vio.op = VIO::NONE;
1284     m_write_vio.buffer.clear();
1285   }
1286 
1287   if (ink_atomic_increment((int *)&m_event_count, 1) < 0) {
1288     ink_assert(!"not reached");
1289   }
1290   eventProcessor.schedule_imm(this, ET_NET);
1291 }
1292 
1293 void
reenable(VIO *)1294 INKVConnInternal::reenable(VIO * /* vio ATS_UNUSED */)
1295 {
1296   if (ink_atomic_increment((int *)&m_event_count, 1) < 0) {
1297     ink_assert(!"not reached");
1298   }
1299   eventProcessor.schedule_imm(this, ET_NET);
1300 }
1301 
1302 void
retry(unsigned int delay)1303 INKVConnInternal::retry(unsigned int delay)
1304 {
1305   if (ink_atomic_increment((int *)&m_event_count, 1) < 0) {
1306     ink_assert(!"not reached");
1307   }
1308   mutex->thread_holding->schedule_in(this, HRTIME_MSECONDS(delay));
1309 }
1310 
1311 bool
get_data(int id,void * data)1312 INKVConnInternal::get_data(int id, void *data)
1313 {
1314   switch (id) {
1315   case TS_API_DATA_READ_VIO:
1316     *((TSVIO *)data) = reinterpret_cast<TSVIO>(&m_read_vio);
1317     return true;
1318   case TS_API_DATA_WRITE_VIO:
1319     *((TSVIO *)data) = reinterpret_cast<TSVIO>(&m_write_vio);
1320     return true;
1321   case TS_API_DATA_OUTPUT_VC:
1322     *((TSVConn *)data) = reinterpret_cast<TSVConn>(m_output_vc);
1323     return true;
1324   case TS_API_DATA_CLOSED:
1325     *((int *)data) = m_closed;
1326     return true;
1327   default:
1328     return INKContInternal::get_data(id, data);
1329   }
1330 }
1331 
1332 bool
set_data(int id,void * data)1333 INKVConnInternal::set_data(int id, void *data)
1334 {
1335   switch (id) {
1336   case TS_API_DATA_OUTPUT_VC:
1337     m_output_vc = (VConnection *)data;
1338     return true;
1339   default:
1340     return INKContInternal::set_data(id, data);
1341   }
1342 }
1343 
1344 ////////////////////////////////////////////////////////////////////
1345 //
1346 // APIHook, APIHooks, HttpAPIHooks, HttpHookState
1347 //
1348 ////////////////////////////////////////////////////////////////////
1349 APIHook *
next() const1350 APIHook::next() const
1351 {
1352   return m_link.next;
1353 }
1354 
1355 APIHook *
prev() const1356 APIHook::prev() const
1357 {
1358   return m_link.prev;
1359 }
1360 
1361 int
invoke(int event,void * edata) const1362 APIHook::invoke(int event, void *edata) const
1363 {
1364   if ((event == EVENT_IMMEDIATE) || (event == EVENT_INTERVAL) || event == TS_EVENT_HTTP_TXN_CLOSE) {
1365     if (ink_atomic_increment((int *)&m_cont->m_event_count, 1) < 0) {
1366       ink_assert(!"not reached");
1367     }
1368   }
1369   WEAK_MUTEX_TRY_LOCK(lock, m_cont->mutex, this_ethread());
1370   if (!lock.is_locked()) {
1371     // If we cannot get the lock, the caller needs to restructure to handle rescheduling
1372     ink_release_assert(0);
1373   }
1374   return m_cont->handleEvent(event, edata);
1375 }
1376 
1377 APIHook *
head() const1378 APIHooks::head() const
1379 {
1380   return m_hooks.head;
1381 }
1382 
1383 void
append(INKContInternal * cont)1384 APIHooks::append(INKContInternal *cont)
1385 {
1386   APIHook *api_hook;
1387 
1388   api_hook         = THREAD_ALLOC(apiHookAllocator, this_thread());
1389   api_hook->m_cont = cont;
1390 
1391   m_hooks.enqueue(api_hook);
1392 }
1393 
1394 void
clear()1395 APIHooks::clear()
1396 {
1397   APIHook *hook;
1398   while (nullptr != (hook = m_hooks.pop())) {
1399     THREAD_FREE(hook, apiHookAllocator, this_thread());
1400   }
1401 }
1402 
HttpHookState()1403 HttpHookState::HttpHookState() : _id(TS_HTTP_LAST_HOOK) {}
1404 
1405 void
init(TSHttpHookID id,HttpAPIHooks const * global,HttpAPIHooks const * ssn,HttpAPIHooks const * txn)1406 HttpHookState::init(TSHttpHookID id, HttpAPIHooks const *global, HttpAPIHooks const *ssn, HttpAPIHooks const *txn)
1407 {
1408   _id = id;
1409 
1410   if (global) {
1411     _global.init(global, id);
1412   } else {
1413     _global.clear();
1414   }
1415 
1416   if (ssn) {
1417     _ssn.init(ssn, id);
1418   } else {
1419     _ssn.clear();
1420   }
1421 
1422   if (txn) {
1423     _txn.init(txn, id);
1424   } else {
1425     _txn.clear();
1426   }
1427 }
1428 
1429 APIHook const *
getNext()1430 HttpHookState::getNext()
1431 {
1432   APIHook const *zret = nullptr;
1433   do {
1434     APIHook const *hg   = _global.candidate();
1435     APIHook const *hssn = _ssn.candidate();
1436     APIHook const *htxn = _txn.candidate();
1437     zret                = nullptr;
1438 
1439     Debug("plugin", "computing next callback for hook %d", _id);
1440 
1441     if (hg) {
1442       zret = hg;
1443       ++_global;
1444     } else if (hssn) {
1445       zret = hssn;
1446       ++_ssn;
1447     } else if (htxn) {
1448       zret = htxn;
1449       ++_txn;
1450     }
1451   } while (zret != nullptr && !this->is_enabled());
1452 
1453   return zret;
1454 }
1455 
1456 bool
is_enabled()1457 HttpHookState::is_enabled()
1458 {
1459   return true;
1460 }
1461 
1462 void
init(HttpAPIHooks const * feature_hooks,TSHttpHookID id)1463 HttpHookState::Scope::init(HttpAPIHooks const *feature_hooks, TSHttpHookID id)
1464 {
1465   _hooks = (*feature_hooks)[id];
1466 
1467   _p = nullptr;
1468   _c = _hooks->head();
1469 }
1470 
1471 APIHook const *
candidate()1472 HttpHookState::Scope::candidate()
1473 {
1474   /// Simply returns _c hook for now. Later will do priority checking here
1475 
1476   // Check to see if a hook has been added since this was initialized empty
1477   if (nullptr == _c && nullptr == _p && _hooks != nullptr) {
1478     _c = _hooks->head();
1479   }
1480   return _c;
1481 }
1482 
1483 void
operator ++()1484 HttpHookState::Scope::operator++()
1485 {
1486   _p = _c;
1487   _c = _c->next();
1488 }
1489 
1490 void
clear()1491 HttpHookState::Scope::clear()
1492 {
1493   _hooks = nullptr;
1494   _p = _c = nullptr;
1495 }
1496 
1497 ////////////////////////////////////////////////////////////////////
1498 //
1499 // ConfigUpdateCbTable
1500 //
1501 ////////////////////////////////////////////////////////////////////
1502 
ConfigUpdateCbTable()1503 ConfigUpdateCbTable::ConfigUpdateCbTable() {}
1504 
~ConfigUpdateCbTable()1505 ConfigUpdateCbTable::~ConfigUpdateCbTable() {}
1506 
1507 void
insert(INKContInternal * contp,const char * name)1508 ConfigUpdateCbTable::insert(INKContInternal *contp, const char *name)
1509 {
1510   if (contp && name) {
1511     cb_table.emplace(name, contp);
1512   }
1513 }
1514 
1515 void
invoke(const char * name)1516 ConfigUpdateCbTable::invoke(const char *name)
1517 {
1518   INKContInternal *contp;
1519 
1520   if (name != nullptr) {
1521     if (strcmp(name, "*") == 0) {
1522       for (auto &&it : cb_table) {
1523         contp = it.second;
1524         ink_assert(contp != nullptr);
1525         invoke(contp);
1526       }
1527     } else {
1528       if (auto it = cb_table.find(name); it != cb_table.end()) {
1529         contp = it->second;
1530         ink_assert(contp != nullptr);
1531         invoke(contp);
1532       }
1533     }
1534   }
1535 }
1536 
1537 void
invoke(INKContInternal * contp)1538 ConfigUpdateCbTable::invoke(INKContInternal *contp)
1539 {
1540   eventProcessor.schedule_imm(new ConfigUpdateCallback(contp), ET_TASK);
1541 }
1542 
1543 ////////////////////////////////////////////////////////////////////
1544 //
1545 // api_init
1546 //
1547 ////////////////////////////////////////////////////////////////////
1548 
1549 void
api_init()1550 api_init()
1551 {
1552   // HDR FIX ME
1553 
1554   static int init = 1;
1555 
1556   if (init) {
1557     init = 0;
1558 
1559     /* URL schemes */
1560     TS_URL_SCHEME_FILE     = URL_SCHEME_FILE;
1561     TS_URL_SCHEME_FTP      = URL_SCHEME_FTP;
1562     TS_URL_SCHEME_GOPHER   = URL_SCHEME_GOPHER;
1563     TS_URL_SCHEME_HTTP     = URL_SCHEME_HTTP;
1564     TS_URL_SCHEME_HTTPS    = URL_SCHEME_HTTPS;
1565     TS_URL_SCHEME_MAILTO   = URL_SCHEME_MAILTO;
1566     TS_URL_SCHEME_NEWS     = URL_SCHEME_NEWS;
1567     TS_URL_SCHEME_NNTP     = URL_SCHEME_NNTP;
1568     TS_URL_SCHEME_PROSPERO = URL_SCHEME_PROSPERO;
1569     TS_URL_SCHEME_TELNET   = URL_SCHEME_TELNET;
1570     TS_URL_SCHEME_WAIS     = URL_SCHEME_WAIS;
1571     TS_URL_SCHEME_WS       = URL_SCHEME_WS;
1572     TS_URL_SCHEME_WSS      = URL_SCHEME_WSS;
1573 
1574     TS_URL_LEN_FILE     = URL_LEN_FILE;
1575     TS_URL_LEN_FTP      = URL_LEN_FTP;
1576     TS_URL_LEN_GOPHER   = URL_LEN_GOPHER;
1577     TS_URL_LEN_HTTP     = URL_LEN_HTTP;
1578     TS_URL_LEN_HTTPS    = URL_LEN_HTTPS;
1579     TS_URL_LEN_MAILTO   = URL_LEN_MAILTO;
1580     TS_URL_LEN_NEWS     = URL_LEN_NEWS;
1581     TS_URL_LEN_NNTP     = URL_LEN_NNTP;
1582     TS_URL_LEN_PROSPERO = URL_LEN_PROSPERO;
1583     TS_URL_LEN_TELNET   = URL_LEN_TELNET;
1584     TS_URL_LEN_WAIS     = URL_LEN_WAIS;
1585     TS_URL_LEN_WS       = URL_LEN_WS;
1586     TS_URL_LEN_WSS      = URL_LEN_WSS;
1587 
1588     /* MIME fields */
1589     TS_MIME_FIELD_ACCEPT                    = MIME_FIELD_ACCEPT;
1590     TS_MIME_FIELD_ACCEPT_CHARSET            = MIME_FIELD_ACCEPT_CHARSET;
1591     TS_MIME_FIELD_ACCEPT_ENCODING           = MIME_FIELD_ACCEPT_ENCODING;
1592     TS_MIME_FIELD_ACCEPT_LANGUAGE           = MIME_FIELD_ACCEPT_LANGUAGE;
1593     TS_MIME_FIELD_ACCEPT_RANGES             = MIME_FIELD_ACCEPT_RANGES;
1594     TS_MIME_FIELD_AGE                       = MIME_FIELD_AGE;
1595     TS_MIME_FIELD_ALLOW                     = MIME_FIELD_ALLOW;
1596     TS_MIME_FIELD_APPROVED                  = MIME_FIELD_APPROVED;
1597     TS_MIME_FIELD_AUTHORIZATION             = MIME_FIELD_AUTHORIZATION;
1598     TS_MIME_FIELD_BYTES                     = MIME_FIELD_BYTES;
1599     TS_MIME_FIELD_CACHE_CONTROL             = MIME_FIELD_CACHE_CONTROL;
1600     TS_MIME_FIELD_CLIENT_IP                 = MIME_FIELD_CLIENT_IP;
1601     TS_MIME_FIELD_CONNECTION                = MIME_FIELD_CONNECTION;
1602     TS_MIME_FIELD_CONTENT_BASE              = MIME_FIELD_CONTENT_BASE;
1603     TS_MIME_FIELD_CONTENT_ENCODING          = MIME_FIELD_CONTENT_ENCODING;
1604     TS_MIME_FIELD_CONTENT_LANGUAGE          = MIME_FIELD_CONTENT_LANGUAGE;
1605     TS_MIME_FIELD_CONTENT_LENGTH            = MIME_FIELD_CONTENT_LENGTH;
1606     TS_MIME_FIELD_CONTENT_LOCATION          = MIME_FIELD_CONTENT_LOCATION;
1607     TS_MIME_FIELD_CONTENT_MD5               = MIME_FIELD_CONTENT_MD5;
1608     TS_MIME_FIELD_CONTENT_RANGE             = MIME_FIELD_CONTENT_RANGE;
1609     TS_MIME_FIELD_CONTENT_TYPE              = MIME_FIELD_CONTENT_TYPE;
1610     TS_MIME_FIELD_CONTROL                   = MIME_FIELD_CONTROL;
1611     TS_MIME_FIELD_COOKIE                    = MIME_FIELD_COOKIE;
1612     TS_MIME_FIELD_DATE                      = MIME_FIELD_DATE;
1613     TS_MIME_FIELD_DISTRIBUTION              = MIME_FIELD_DISTRIBUTION;
1614     TS_MIME_FIELD_ETAG                      = MIME_FIELD_ETAG;
1615     TS_MIME_FIELD_EXPECT                    = MIME_FIELD_EXPECT;
1616     TS_MIME_FIELD_EXPIRES                   = MIME_FIELD_EXPIRES;
1617     TS_MIME_FIELD_FOLLOWUP_TO               = MIME_FIELD_FOLLOWUP_TO;
1618     TS_MIME_FIELD_FROM                      = MIME_FIELD_FROM;
1619     TS_MIME_FIELD_HOST                      = MIME_FIELD_HOST;
1620     TS_MIME_FIELD_IF_MATCH                  = MIME_FIELD_IF_MATCH;
1621     TS_MIME_FIELD_IF_MODIFIED_SINCE         = MIME_FIELD_IF_MODIFIED_SINCE;
1622     TS_MIME_FIELD_IF_NONE_MATCH             = MIME_FIELD_IF_NONE_MATCH;
1623     TS_MIME_FIELD_IF_RANGE                  = MIME_FIELD_IF_RANGE;
1624     TS_MIME_FIELD_IF_UNMODIFIED_SINCE       = MIME_FIELD_IF_UNMODIFIED_SINCE;
1625     TS_MIME_FIELD_KEEP_ALIVE                = MIME_FIELD_KEEP_ALIVE;
1626     TS_MIME_FIELD_KEYWORDS                  = MIME_FIELD_KEYWORDS;
1627     TS_MIME_FIELD_LAST_MODIFIED             = MIME_FIELD_LAST_MODIFIED;
1628     TS_MIME_FIELD_LINES                     = MIME_FIELD_LINES;
1629     TS_MIME_FIELD_LOCATION                  = MIME_FIELD_LOCATION;
1630     TS_MIME_FIELD_MAX_FORWARDS              = MIME_FIELD_MAX_FORWARDS;
1631     TS_MIME_FIELD_MESSAGE_ID                = MIME_FIELD_MESSAGE_ID;
1632     TS_MIME_FIELD_NEWSGROUPS                = MIME_FIELD_NEWSGROUPS;
1633     TS_MIME_FIELD_ORGANIZATION              = MIME_FIELD_ORGANIZATION;
1634     TS_MIME_FIELD_PATH                      = MIME_FIELD_PATH;
1635     TS_MIME_FIELD_PRAGMA                    = MIME_FIELD_PRAGMA;
1636     TS_MIME_FIELD_PROXY_AUTHENTICATE        = MIME_FIELD_PROXY_AUTHENTICATE;
1637     TS_MIME_FIELD_PROXY_AUTHORIZATION       = MIME_FIELD_PROXY_AUTHORIZATION;
1638     TS_MIME_FIELD_PROXY_CONNECTION          = MIME_FIELD_PROXY_CONNECTION;
1639     TS_MIME_FIELD_PUBLIC                    = MIME_FIELD_PUBLIC;
1640     TS_MIME_FIELD_RANGE                     = MIME_FIELD_RANGE;
1641     TS_MIME_FIELD_REFERENCES                = MIME_FIELD_REFERENCES;
1642     TS_MIME_FIELD_REFERER                   = MIME_FIELD_REFERER;
1643     TS_MIME_FIELD_REPLY_TO                  = MIME_FIELD_REPLY_TO;
1644     TS_MIME_FIELD_RETRY_AFTER               = MIME_FIELD_RETRY_AFTER;
1645     TS_MIME_FIELD_SENDER                    = MIME_FIELD_SENDER;
1646     TS_MIME_FIELD_SERVER                    = MIME_FIELD_SERVER;
1647     TS_MIME_FIELD_SET_COOKIE                = MIME_FIELD_SET_COOKIE;
1648     TS_MIME_FIELD_STRICT_TRANSPORT_SECURITY = MIME_FIELD_STRICT_TRANSPORT_SECURITY;
1649     TS_MIME_FIELD_SUBJECT                   = MIME_FIELD_SUBJECT;
1650     TS_MIME_FIELD_SUMMARY                   = MIME_FIELD_SUMMARY;
1651     TS_MIME_FIELD_TE                        = MIME_FIELD_TE;
1652     TS_MIME_FIELD_TRANSFER_ENCODING         = MIME_FIELD_TRANSFER_ENCODING;
1653     TS_MIME_FIELD_UPGRADE                   = MIME_FIELD_UPGRADE;
1654     TS_MIME_FIELD_USER_AGENT                = MIME_FIELD_USER_AGENT;
1655     TS_MIME_FIELD_VARY                      = MIME_FIELD_VARY;
1656     TS_MIME_FIELD_VIA                       = MIME_FIELD_VIA;
1657     TS_MIME_FIELD_WARNING                   = MIME_FIELD_WARNING;
1658     TS_MIME_FIELD_WWW_AUTHENTICATE          = MIME_FIELD_WWW_AUTHENTICATE;
1659     TS_MIME_FIELD_XREF                      = MIME_FIELD_XREF;
1660     TS_MIME_FIELD_X_FORWARDED_FOR           = MIME_FIELD_X_FORWARDED_FOR;
1661     TS_MIME_FIELD_FORWARDED                 = MIME_FIELD_FORWARDED;
1662 
1663     TS_MIME_LEN_ACCEPT                    = MIME_LEN_ACCEPT;
1664     TS_MIME_LEN_ACCEPT_CHARSET            = MIME_LEN_ACCEPT_CHARSET;
1665     TS_MIME_LEN_ACCEPT_ENCODING           = MIME_LEN_ACCEPT_ENCODING;
1666     TS_MIME_LEN_ACCEPT_LANGUAGE           = MIME_LEN_ACCEPT_LANGUAGE;
1667     TS_MIME_LEN_ACCEPT_RANGES             = MIME_LEN_ACCEPT_RANGES;
1668     TS_MIME_LEN_AGE                       = MIME_LEN_AGE;
1669     TS_MIME_LEN_ALLOW                     = MIME_LEN_ALLOW;
1670     TS_MIME_LEN_APPROVED                  = MIME_LEN_APPROVED;
1671     TS_MIME_LEN_AUTHORIZATION             = MIME_LEN_AUTHORIZATION;
1672     TS_MIME_LEN_BYTES                     = MIME_LEN_BYTES;
1673     TS_MIME_LEN_CACHE_CONTROL             = MIME_LEN_CACHE_CONTROL;
1674     TS_MIME_LEN_CLIENT_IP                 = MIME_LEN_CLIENT_IP;
1675     TS_MIME_LEN_CONNECTION                = MIME_LEN_CONNECTION;
1676     TS_MIME_LEN_CONTENT_BASE              = MIME_LEN_CONTENT_BASE;
1677     TS_MIME_LEN_CONTENT_ENCODING          = MIME_LEN_CONTENT_ENCODING;
1678     TS_MIME_LEN_CONTENT_LANGUAGE          = MIME_LEN_CONTENT_LANGUAGE;
1679     TS_MIME_LEN_CONTENT_LENGTH            = MIME_LEN_CONTENT_LENGTH;
1680     TS_MIME_LEN_CONTENT_LOCATION          = MIME_LEN_CONTENT_LOCATION;
1681     TS_MIME_LEN_CONTENT_MD5               = MIME_LEN_CONTENT_MD5;
1682     TS_MIME_LEN_CONTENT_RANGE             = MIME_LEN_CONTENT_RANGE;
1683     TS_MIME_LEN_CONTENT_TYPE              = MIME_LEN_CONTENT_TYPE;
1684     TS_MIME_LEN_CONTROL                   = MIME_LEN_CONTROL;
1685     TS_MIME_LEN_COOKIE                    = MIME_LEN_COOKIE;
1686     TS_MIME_LEN_DATE                      = MIME_LEN_DATE;
1687     TS_MIME_LEN_DISTRIBUTION              = MIME_LEN_DISTRIBUTION;
1688     TS_MIME_LEN_ETAG                      = MIME_LEN_ETAG;
1689     TS_MIME_LEN_EXPECT                    = MIME_LEN_EXPECT;
1690     TS_MIME_LEN_EXPIRES                   = MIME_LEN_EXPIRES;
1691     TS_MIME_LEN_FOLLOWUP_TO               = MIME_LEN_FOLLOWUP_TO;
1692     TS_MIME_LEN_FROM                      = MIME_LEN_FROM;
1693     TS_MIME_LEN_HOST                      = MIME_LEN_HOST;
1694     TS_MIME_LEN_IF_MATCH                  = MIME_LEN_IF_MATCH;
1695     TS_MIME_LEN_IF_MODIFIED_SINCE         = MIME_LEN_IF_MODIFIED_SINCE;
1696     TS_MIME_LEN_IF_NONE_MATCH             = MIME_LEN_IF_NONE_MATCH;
1697     TS_MIME_LEN_IF_RANGE                  = MIME_LEN_IF_RANGE;
1698     TS_MIME_LEN_IF_UNMODIFIED_SINCE       = MIME_LEN_IF_UNMODIFIED_SINCE;
1699     TS_MIME_LEN_KEEP_ALIVE                = MIME_LEN_KEEP_ALIVE;
1700     TS_MIME_LEN_KEYWORDS                  = MIME_LEN_KEYWORDS;
1701     TS_MIME_LEN_LAST_MODIFIED             = MIME_LEN_LAST_MODIFIED;
1702     TS_MIME_LEN_LINES                     = MIME_LEN_LINES;
1703     TS_MIME_LEN_LOCATION                  = MIME_LEN_LOCATION;
1704     TS_MIME_LEN_MAX_FORWARDS              = MIME_LEN_MAX_FORWARDS;
1705     TS_MIME_LEN_MESSAGE_ID                = MIME_LEN_MESSAGE_ID;
1706     TS_MIME_LEN_NEWSGROUPS                = MIME_LEN_NEWSGROUPS;
1707     TS_MIME_LEN_ORGANIZATION              = MIME_LEN_ORGANIZATION;
1708     TS_MIME_LEN_PATH                      = MIME_LEN_PATH;
1709     TS_MIME_LEN_PRAGMA                    = MIME_LEN_PRAGMA;
1710     TS_MIME_LEN_PROXY_AUTHENTICATE        = MIME_LEN_PROXY_AUTHENTICATE;
1711     TS_MIME_LEN_PROXY_AUTHORIZATION       = MIME_LEN_PROXY_AUTHORIZATION;
1712     TS_MIME_LEN_PROXY_CONNECTION          = MIME_LEN_PROXY_CONNECTION;
1713     TS_MIME_LEN_PUBLIC                    = MIME_LEN_PUBLIC;
1714     TS_MIME_LEN_RANGE                     = MIME_LEN_RANGE;
1715     TS_MIME_LEN_REFERENCES                = MIME_LEN_REFERENCES;
1716     TS_MIME_LEN_REFERER                   = MIME_LEN_REFERER;
1717     TS_MIME_LEN_REPLY_TO                  = MIME_LEN_REPLY_TO;
1718     TS_MIME_LEN_RETRY_AFTER               = MIME_LEN_RETRY_AFTER;
1719     TS_MIME_LEN_SENDER                    = MIME_LEN_SENDER;
1720     TS_MIME_LEN_SERVER                    = MIME_LEN_SERVER;
1721     TS_MIME_LEN_SET_COOKIE                = MIME_LEN_SET_COOKIE;
1722     TS_MIME_LEN_STRICT_TRANSPORT_SECURITY = MIME_LEN_STRICT_TRANSPORT_SECURITY;
1723     TS_MIME_LEN_SUBJECT                   = MIME_LEN_SUBJECT;
1724     TS_MIME_LEN_SUMMARY                   = MIME_LEN_SUMMARY;
1725     TS_MIME_LEN_TE                        = MIME_LEN_TE;
1726     TS_MIME_LEN_TRANSFER_ENCODING         = MIME_LEN_TRANSFER_ENCODING;
1727     TS_MIME_LEN_UPGRADE                   = MIME_LEN_UPGRADE;
1728     TS_MIME_LEN_USER_AGENT                = MIME_LEN_USER_AGENT;
1729     TS_MIME_LEN_VARY                      = MIME_LEN_VARY;
1730     TS_MIME_LEN_VIA                       = MIME_LEN_VIA;
1731     TS_MIME_LEN_WARNING                   = MIME_LEN_WARNING;
1732     TS_MIME_LEN_WWW_AUTHENTICATE          = MIME_LEN_WWW_AUTHENTICATE;
1733     TS_MIME_LEN_XREF                      = MIME_LEN_XREF;
1734     TS_MIME_LEN_X_FORWARDED_FOR           = MIME_LEN_X_FORWARDED_FOR;
1735     TS_MIME_LEN_FORWARDED                 = MIME_LEN_FORWARDED;
1736 
1737     /* HTTP methods */
1738     TS_HTTP_METHOD_CONNECT = HTTP_METHOD_CONNECT;
1739     TS_HTTP_METHOD_DELETE  = HTTP_METHOD_DELETE;
1740     TS_HTTP_METHOD_GET     = HTTP_METHOD_GET;
1741     TS_HTTP_METHOD_HEAD    = HTTP_METHOD_HEAD;
1742     TS_HTTP_METHOD_OPTIONS = HTTP_METHOD_OPTIONS;
1743     TS_HTTP_METHOD_POST    = HTTP_METHOD_POST;
1744     TS_HTTP_METHOD_PURGE   = HTTP_METHOD_PURGE;
1745     TS_HTTP_METHOD_PUT     = HTTP_METHOD_PUT;
1746     TS_HTTP_METHOD_TRACE   = HTTP_METHOD_TRACE;
1747     TS_HTTP_METHOD_PUSH    = HTTP_METHOD_PUSH;
1748 
1749     TS_HTTP_LEN_CONNECT = HTTP_LEN_CONNECT;
1750     TS_HTTP_LEN_DELETE  = HTTP_LEN_DELETE;
1751     TS_HTTP_LEN_GET     = HTTP_LEN_GET;
1752     TS_HTTP_LEN_HEAD    = HTTP_LEN_HEAD;
1753     TS_HTTP_LEN_OPTIONS = HTTP_LEN_OPTIONS;
1754     TS_HTTP_LEN_POST    = HTTP_LEN_POST;
1755     TS_HTTP_LEN_PURGE   = HTTP_LEN_PURGE;
1756     TS_HTTP_LEN_PUT     = HTTP_LEN_PUT;
1757     TS_HTTP_LEN_TRACE   = HTTP_LEN_TRACE;
1758     TS_HTTP_LEN_PUSH    = HTTP_LEN_PUSH;
1759 
1760     /* HTTP miscellaneous values */
1761     TS_HTTP_VALUE_BYTES            = HTTP_VALUE_BYTES;
1762     TS_HTTP_VALUE_CHUNKED          = HTTP_VALUE_CHUNKED;
1763     TS_HTTP_VALUE_CLOSE            = HTTP_VALUE_CLOSE;
1764     TS_HTTP_VALUE_COMPRESS         = HTTP_VALUE_COMPRESS;
1765     TS_HTTP_VALUE_DEFLATE          = HTTP_VALUE_DEFLATE;
1766     TS_HTTP_VALUE_GZIP             = HTTP_VALUE_GZIP;
1767     TS_HTTP_VALUE_IDENTITY         = HTTP_VALUE_IDENTITY;
1768     TS_HTTP_VALUE_KEEP_ALIVE       = HTTP_VALUE_KEEP_ALIVE;
1769     TS_HTTP_VALUE_MAX_AGE          = HTTP_VALUE_MAX_AGE;
1770     TS_HTTP_VALUE_MAX_STALE        = HTTP_VALUE_MAX_STALE;
1771     TS_HTTP_VALUE_MIN_FRESH        = HTTP_VALUE_MIN_FRESH;
1772     TS_HTTP_VALUE_MUST_REVALIDATE  = HTTP_VALUE_MUST_REVALIDATE;
1773     TS_HTTP_VALUE_NONE             = HTTP_VALUE_NONE;
1774     TS_HTTP_VALUE_NO_CACHE         = HTTP_VALUE_NO_CACHE;
1775     TS_HTTP_VALUE_NO_STORE         = HTTP_VALUE_NO_STORE;
1776     TS_HTTP_VALUE_NO_TRANSFORM     = HTTP_VALUE_NO_TRANSFORM;
1777     TS_HTTP_VALUE_ONLY_IF_CACHED   = HTTP_VALUE_ONLY_IF_CACHED;
1778     TS_HTTP_VALUE_PRIVATE          = HTTP_VALUE_PRIVATE;
1779     TS_HTTP_VALUE_PROXY_REVALIDATE = HTTP_VALUE_PROXY_REVALIDATE;
1780     TS_HTTP_VALUE_PUBLIC           = HTTP_VALUE_PUBLIC;
1781     TS_HTTP_VALUE_S_MAXAGE         = HTTP_VALUE_S_MAXAGE;
1782 
1783     TS_HTTP_LEN_BYTES            = HTTP_LEN_BYTES;
1784     TS_HTTP_LEN_CHUNKED          = HTTP_LEN_CHUNKED;
1785     TS_HTTP_LEN_CLOSE            = HTTP_LEN_CLOSE;
1786     TS_HTTP_LEN_COMPRESS         = HTTP_LEN_COMPRESS;
1787     TS_HTTP_LEN_DEFLATE          = HTTP_LEN_DEFLATE;
1788     TS_HTTP_LEN_GZIP             = HTTP_LEN_GZIP;
1789     TS_HTTP_LEN_IDENTITY         = HTTP_LEN_IDENTITY;
1790     TS_HTTP_LEN_KEEP_ALIVE       = HTTP_LEN_KEEP_ALIVE;
1791     TS_HTTP_LEN_MAX_AGE          = HTTP_LEN_MAX_AGE;
1792     TS_HTTP_LEN_MAX_STALE        = HTTP_LEN_MAX_STALE;
1793     TS_HTTP_LEN_MIN_FRESH        = HTTP_LEN_MIN_FRESH;
1794     TS_HTTP_LEN_MUST_REVALIDATE  = HTTP_LEN_MUST_REVALIDATE;
1795     TS_HTTP_LEN_NONE             = HTTP_LEN_NONE;
1796     TS_HTTP_LEN_NO_CACHE         = HTTP_LEN_NO_CACHE;
1797     TS_HTTP_LEN_NO_STORE         = HTTP_LEN_NO_STORE;
1798     TS_HTTP_LEN_NO_TRANSFORM     = HTTP_LEN_NO_TRANSFORM;
1799     TS_HTTP_LEN_ONLY_IF_CACHED   = HTTP_LEN_ONLY_IF_CACHED;
1800     TS_HTTP_LEN_PRIVATE          = HTTP_LEN_PRIVATE;
1801     TS_HTTP_LEN_PROXY_REVALIDATE = HTTP_LEN_PROXY_REVALIDATE;
1802     TS_HTTP_LEN_PUBLIC           = HTTP_LEN_PUBLIC;
1803     TS_HTTP_LEN_S_MAXAGE         = HTTP_LEN_S_MAXAGE;
1804 
1805     http_global_hooks = new HttpAPIHooks;
1806     ssl_hooks         = new SslAPIHooks;
1807     lifecycle_hooks   = new LifecycleAPIHooks;
1808     global_config_cbs = new ConfigUpdateCbTable;
1809 
1810     int api_metrics = max_records_entries - REC_INTERNAL_RECORDS;
1811     if (api_metrics > 0) {
1812       api_rsb = RecAllocateRawStatBlock(api_metrics);
1813       if (nullptr == api_rsb) {
1814         Warning("Can't allocate API stats block");
1815       } else {
1816         Debug("sdk", "initialized SDK stats APIs with %d slots", api_metrics);
1817       }
1818     } else {
1819       api_rsb = nullptr;
1820     }
1821 
1822     // Setup the version string for returning to plugins
1823     ink_strlcpy(traffic_server_version, appVersionInfo.VersionStr, sizeof(traffic_server_version));
1824     // Extract the elements.
1825     // coverity[secure_coding]
1826     if (sscanf(traffic_server_version, "%d.%d.%d", &ts_major_version, &ts_minor_version, &ts_patch_version) != 3) {
1827       Warning("Unable to parse traffic server version string '%s'\n", traffic_server_version);
1828     }
1829   }
1830 }
1831 
1832 ////////////////////////////////////////////////////////////////////
1833 //
1834 // API memory management
1835 //
1836 ////////////////////////////////////////////////////////////////////
1837 
1838 void *
_TSmalloc(size_t size,const char *)1839 _TSmalloc(size_t size, const char * /* path ATS_UNUSED */)
1840 {
1841   return ats_malloc(size);
1842 }
1843 
1844 void *
_TSrealloc(void * ptr,size_t size,const char *)1845 _TSrealloc(void *ptr, size_t size, const char * /* path ATS_UNUSED */)
1846 {
1847   return ats_realloc(ptr, size);
1848 }
1849 
1850 // length has to be int64_t and not size_t, since -1 means to call strlen() to get length
1851 char *
_TSstrdup(const char * str,int64_t length,const char * path)1852 _TSstrdup(const char *str, int64_t length, const char *path)
1853 {
1854   return _xstrdup(str, length, path);
1855 }
1856 
1857 size_t
_TSstrlcpy(char * dst,const char * str,size_t siz)1858 _TSstrlcpy(char *dst, const char *str, size_t siz)
1859 {
1860   return ink_strlcpy(dst, str, siz);
1861 }
1862 
1863 size_t
_TSstrlcat(char * dst,const char * str,size_t siz)1864 _TSstrlcat(char *dst, const char *str, size_t siz)
1865 {
1866   return ink_strlcat(dst, str, siz);
1867 }
1868 
1869 void
_TSfree(void * ptr)1870 _TSfree(void *ptr)
1871 {
1872   ats_free(ptr);
1873 }
1874 
1875 ////////////////////////////////////////////////////////////////////
1876 //
1877 // Encoding utility
1878 //
1879 ////////////////////////////////////////////////////////////////////
1880 TSReturnCode
TSBase64Decode(const char * str,size_t str_len,unsigned char * dst,size_t dst_size,size_t * length)1881 TSBase64Decode(const char *str, size_t str_len, unsigned char *dst, size_t dst_size, size_t *length)
1882 {
1883   sdk_assert(sdk_sanity_check_null_ptr((void *)str) == TS_SUCCESS);
1884   sdk_assert(sdk_sanity_check_null_ptr((void *)dst) == TS_SUCCESS);
1885 
1886   return ats_base64_decode(str, str_len, dst, dst_size, length) ? TS_SUCCESS : TS_ERROR;
1887 }
1888 
1889 TSReturnCode
TSBase64Encode(const char * str,size_t str_len,char * dst,size_t dst_size,size_t * length)1890 TSBase64Encode(const char *str, size_t str_len, char *dst, size_t dst_size, size_t *length)
1891 {
1892   sdk_assert(sdk_sanity_check_null_ptr((void *)str) == TS_SUCCESS);
1893   sdk_assert(sdk_sanity_check_null_ptr((void *)dst) == TS_SUCCESS);
1894 
1895   return ats_base64_encode(str, str_len, dst, dst_size, length) ? TS_SUCCESS : TS_ERROR;
1896 }
1897 
1898 ////////////////////////////////////////////////////////////////////
1899 //
1900 // API utility routines
1901 //
1902 ////////////////////////////////////////////////////////////////////
1903 
1904 unsigned int
TSrandom()1905 TSrandom()
1906 {
1907   return this_ethread()->generator.random();
1908 }
1909 
1910 double
TSdrandom()1911 TSdrandom()
1912 {
1913   return this_ethread()->generator.drandom();
1914 }
1915 
1916 ink_hrtime
TShrtime()1917 TShrtime()
1918 {
1919   return Thread::get_hrtime();
1920 }
1921 
1922 ////////////////////////////////////////////////////////////////////
1923 //
1924 // API install and plugin locations
1925 //
1926 ////////////////////////////////////////////////////////////////////
1927 
1928 const char *
TSInstallDirGet()1929 TSInstallDirGet()
1930 {
1931   static std::string prefix = Layout::get()->prefix;
1932   return prefix.c_str();
1933 }
1934 
1935 const char *
TSConfigDirGet()1936 TSConfigDirGet()
1937 {
1938   static std::string sysconfdir = RecConfigReadConfigDir();
1939   return sysconfdir.c_str();
1940 }
1941 
1942 const char *
TSRuntimeDirGet()1943 TSRuntimeDirGet()
1944 {
1945   static std::string runtimedir = RecConfigReadRuntimeDir();
1946   return runtimedir.c_str();
1947 }
1948 
1949 const char *
TSTrafficServerVersionGet()1950 TSTrafficServerVersionGet()
1951 {
1952   return traffic_server_version;
1953 }
1954 
1955 int
TSTrafficServerVersionGetMajor()1956 TSTrafficServerVersionGetMajor()
1957 {
1958   return ts_major_version;
1959 }
1960 int
TSTrafficServerVersionGetMinor()1961 TSTrafficServerVersionGetMinor()
1962 {
1963   return ts_minor_version;
1964 }
1965 int
TSTrafficServerVersionGetPatch()1966 TSTrafficServerVersionGetPatch()
1967 {
1968   return ts_patch_version;
1969 }
1970 
1971 const char *
TSPluginDirGet()1972 TSPluginDirGet()
1973 {
1974   static std::string path = RecConfigReadPluginDir();
1975   return path.c_str();
1976 }
1977 
1978 ////////////////////////////////////////////////////////////////////
1979 //
1980 // Plugin registration
1981 //
1982 ////////////////////////////////////////////////////////////////////
1983 
1984 TSReturnCode
TSPluginRegister(const TSPluginRegistrationInfo * plugin_info)1985 TSPluginRegister(const TSPluginRegistrationInfo *plugin_info)
1986 {
1987   sdk_assert(sdk_sanity_check_null_ptr((void *)plugin_info) == TS_SUCCESS);
1988 
1989   if (!plugin_reg_current) {
1990     return TS_ERROR;
1991   }
1992 
1993   plugin_reg_current->plugin_registered = true;
1994 
1995   if (plugin_info->plugin_name) {
1996     plugin_reg_current->plugin_name = ats_strdup(plugin_info->plugin_name);
1997   }
1998 
1999   if (plugin_info->vendor_name) {
2000     plugin_reg_current->vendor_name = ats_strdup(plugin_info->vendor_name);
2001   }
2002 
2003   if (plugin_info->support_email) {
2004     plugin_reg_current->support_email = ats_strdup(plugin_info->support_email);
2005   }
2006 
2007   return TS_SUCCESS;
2008 }
2009 
2010 TSReturnCode
TSPluginDSOReloadEnable(int enabled)2011 TSPluginDSOReloadEnable(int enabled)
2012 {
2013   TSReturnCode ret = TS_SUCCESS;
2014   if (!plugin_reg_current) {
2015     return TS_ERROR;
2016   }
2017 
2018   if (!enabled) {
2019     if (!PluginDso::loadedPlugins()->addPluginPathToDsoOptOutTable(plugin_reg_current->plugin_path)) {
2020       ret = TS_ERROR;
2021     }
2022   }
2023 
2024   return ret;
2025 }
2026 
2027 ////////////////////////////////////////////////////////////////////
2028 //
2029 // API file management
2030 //
2031 ////////////////////////////////////////////////////////////////////
2032 
2033 TSFile
TSfopen(const char * filename,const char * mode)2034 TSfopen(const char *filename, const char *mode)
2035 {
2036   FileImpl *file;
2037 
2038   file = new FileImpl;
2039   if (!file->fopen(filename, mode)) {
2040     delete file;
2041     return nullptr;
2042   }
2043 
2044   return (TSFile)file;
2045 }
2046 
2047 void
TSfclose(TSFile filep)2048 TSfclose(TSFile filep)
2049 {
2050   FileImpl *file = (FileImpl *)filep;
2051   file->fclose();
2052   delete file;
2053 }
2054 
2055 ssize_t
TSfread(TSFile filep,void * buf,size_t length)2056 TSfread(TSFile filep, void *buf, size_t length)
2057 {
2058   FileImpl *file = (FileImpl *)filep;
2059   return file->fread(buf, length);
2060 }
2061 
2062 ssize_t
TSfwrite(TSFile filep,const void * buf,size_t length)2063 TSfwrite(TSFile filep, const void *buf, size_t length)
2064 {
2065   FileImpl *file = (FileImpl *)filep;
2066   return file->fwrite(buf, length);
2067 }
2068 
2069 void
TSfflush(TSFile filep)2070 TSfflush(TSFile filep)
2071 {
2072   FileImpl *file = (FileImpl *)filep;
2073   file->fflush();
2074 }
2075 
2076 char *
TSfgets(TSFile filep,char * buf,size_t length)2077 TSfgets(TSFile filep, char *buf, size_t length)
2078 {
2079   FileImpl *file = (FileImpl *)filep;
2080   return file->fgets(buf, length);
2081 }
2082 
2083 ////////////////////////////////////////////////////////////////////
2084 //
2085 // Header component object handles
2086 //
2087 ////////////////////////////////////////////////////////////////////
2088 
2089 TSReturnCode
TSHandleMLocRelease(TSMBuffer bufp,TSMLoc parent,TSMLoc mloc)2090 TSHandleMLocRelease(TSMBuffer bufp, TSMLoc parent, TSMLoc mloc)
2091 {
2092   MIMEFieldSDKHandle *field_handle;
2093   HdrHeapObjImpl *obj = (HdrHeapObjImpl *)mloc;
2094 
2095   if (mloc == TS_NULL_MLOC) {
2096     return TS_SUCCESS;
2097   }
2098 
2099   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2100 
2101   switch (obj->m_type) {
2102   case HDR_HEAP_OBJ_URL:
2103   case HDR_HEAP_OBJ_HTTP_HEADER:
2104   case HDR_HEAP_OBJ_MIME_HEADER:
2105     return TS_SUCCESS;
2106 
2107   case HDR_HEAP_OBJ_FIELD_SDK_HANDLE:
2108     field_handle = (MIMEFieldSDKHandle *)obj;
2109     if (sdk_sanity_check_field_handle(mloc, parent) != TS_SUCCESS) {
2110       return TS_ERROR;
2111     }
2112 
2113     sdk_free_field_handle(bufp, field_handle);
2114     return TS_SUCCESS;
2115 
2116   default:
2117     ink_release_assert(!"invalid mloc");
2118     return TS_ERROR;
2119   }
2120 }
2121 
2122 ////////////////////////////////////////////////////////////////////
2123 //
2124 // HdrHeaps (previously known as "Marshal Buffers")
2125 //
2126 ////////////////////////////////////////////////////////////////////
2127 
2128 // TSMBuffer: pointers to HdrHeapSDKHandle objects
2129 
2130 TSMBuffer
TSMBufferCreate()2131 TSMBufferCreate()
2132 {
2133   TSMBuffer bufp;
2134   HdrHeapSDKHandle *new_heap = new HdrHeapSDKHandle;
2135 
2136   new_heap->m_heap = new_HdrHeap();
2137   bufp             = (TSMBuffer)new_heap;
2138   // TODO: Should remove this when memory allocation is guaranteed to fail.
2139   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2140   return bufp;
2141 }
2142 
2143 TSReturnCode
TSMBufferDestroy(TSMBuffer bufp)2144 TSMBufferDestroy(TSMBuffer bufp)
2145 {
2146   // Allow to modify the buffer only
2147   // if bufp is modifiable. If bufp is not modifiable return
2148   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
2149   // return value of function from void to TSReturnCode.
2150   if (!isWriteable(bufp)) {
2151     return TS_ERROR;
2152   }
2153 
2154   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2155   HdrHeapSDKHandle *sdk_heap = (HdrHeapSDKHandle *)bufp;
2156   sdk_heap->m_heap->destroy();
2157   delete sdk_heap;
2158   return TS_SUCCESS;
2159 }
2160 
2161 ////////////////////////////////////////////////////////////////////
2162 //
2163 // URLs
2164 //
2165 ////////////////////////////////////////////////////////////////////
2166 
2167 // TSMBuffer: pointers to HdrHeapSDKHandle objects
2168 // TSMLoc:    pointers to URLImpl objects
2169 TSReturnCode
TSUrlCreate(TSMBuffer bufp,TSMLoc * locp)2170 TSUrlCreate(TSMBuffer bufp, TSMLoc *locp)
2171 {
2172   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2173   sdk_assert(sdk_sanity_check_null_ptr(locp) == TS_SUCCESS);
2174 
2175   if (isWriteable(bufp)) {
2176     HdrHeap *heap = ((HdrHeapSDKHandle *)bufp)->m_heap;
2177     *locp         = (TSMLoc)url_create(heap);
2178     return TS_SUCCESS;
2179   }
2180   return TS_ERROR;
2181 }
2182 
2183 TSReturnCode
TSUrlClone(TSMBuffer dest_bufp,TSMBuffer src_bufp,TSMLoc src_url,TSMLoc * locp)2184 TSUrlClone(TSMBuffer dest_bufp, TSMBuffer src_bufp, TSMLoc src_url, TSMLoc *locp)
2185 {
2186   sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
2187   sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
2188   sdk_assert(sdk_sanity_check_url_handle(src_url) == TS_SUCCESS);
2189   sdk_assert(sdk_sanity_check_null_ptr(locp) == TS_SUCCESS);
2190 
2191   if (!isWriteable(dest_bufp)) {
2192     return TS_ERROR;
2193   }
2194 
2195   HdrHeap *s_heap, *d_heap;
2196   URLImpl *s_url, *d_url;
2197 
2198   s_heap = ((HdrHeapSDKHandle *)src_bufp)->m_heap;
2199   d_heap = ((HdrHeapSDKHandle *)dest_bufp)->m_heap;
2200   s_url  = (URLImpl *)src_url;
2201 
2202   d_url = url_copy(s_url, s_heap, d_heap, (s_heap != d_heap));
2203   *locp = (TSMLoc)d_url;
2204   return TS_SUCCESS;
2205 }
2206 
2207 TSReturnCode
TSUrlCopy(TSMBuffer dest_bufp,TSMLoc dest_obj,TSMBuffer src_bufp,TSMLoc src_obj)2208 TSUrlCopy(TSMBuffer dest_bufp, TSMLoc dest_obj, TSMBuffer src_bufp, TSMLoc src_obj)
2209 {
2210   sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
2211   sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
2212   sdk_assert(sdk_sanity_check_url_handle(src_obj) == TS_SUCCESS);
2213   sdk_assert(sdk_sanity_check_url_handle(dest_obj) == TS_SUCCESS);
2214 
2215   if (!isWriteable(dest_bufp)) {
2216     return TS_ERROR;
2217   }
2218 
2219   HdrHeap *s_heap, *d_heap;
2220   URLImpl *s_url, *d_url;
2221 
2222   s_heap = ((HdrHeapSDKHandle *)src_bufp)->m_heap;
2223   d_heap = ((HdrHeapSDKHandle *)dest_bufp)->m_heap;
2224   s_url  = (URLImpl *)src_obj;
2225   d_url  = (URLImpl *)dest_obj;
2226 
2227   url_copy_onto(s_url, s_heap, d_url, d_heap, (s_heap != d_heap));
2228   return TS_SUCCESS;
2229 }
2230 
2231 void
TSUrlPrint(TSMBuffer bufp,TSMLoc obj,TSIOBuffer iobufp)2232 TSUrlPrint(TSMBuffer bufp, TSMLoc obj, TSIOBuffer iobufp)
2233 {
2234   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2235   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
2236   sdk_assert(sdk_sanity_check_iocore_structure(iobufp) == TS_SUCCESS);
2237 
2238   MIOBuffer *b = (MIOBuffer *)iobufp;
2239   IOBufferBlock *blk;
2240   int bufindex;
2241   int tmp, dumpoffset;
2242   int done;
2243   URL u;
2244 
2245   u.m_heap     = ((HdrHeapSDKHandle *)bufp)->m_heap;
2246   u.m_url_impl = (URLImpl *)obj;
2247   dumpoffset   = 0;
2248 
2249   do {
2250     blk = b->get_current_block();
2251     if (!blk || blk->write_avail() == 0) {
2252       b->add_block();
2253       blk = b->get_current_block();
2254     }
2255 
2256     bufindex = 0;
2257     tmp      = dumpoffset;
2258 
2259     done = u.print(blk->end(), blk->write_avail(), &bufindex, &tmp);
2260 
2261     dumpoffset += bufindex;
2262     b->fill(bufindex);
2263   } while (!done);
2264 }
2265 
2266 TSParseResult
TSUrlParse(TSMBuffer bufp,TSMLoc obj,const char ** start,const char * end)2267 TSUrlParse(TSMBuffer bufp, TSMLoc obj, const char **start, const char *end)
2268 {
2269   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2270   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
2271   sdk_assert(sdk_sanity_check_null_ptr((void *)start) == TS_SUCCESS);
2272   sdk_assert(sdk_sanity_check_null_ptr((void *)*start) == TS_SUCCESS);
2273   sdk_assert(sdk_sanity_check_null_ptr((void *)end) == TS_SUCCESS);
2274 
2275   if (!isWriteable(bufp)) {
2276     return TS_PARSE_ERROR;
2277   }
2278 
2279   URL u;
2280   u.m_heap     = ((HdrHeapSDKHandle *)bufp)->m_heap;
2281   u.m_url_impl = (URLImpl *)obj;
2282   url_clear(u.m_url_impl);
2283   return (TSParseResult)u.parse(start, end);
2284 }
2285 
2286 int
TSUrlLengthGet(TSMBuffer bufp,TSMLoc obj)2287 TSUrlLengthGet(TSMBuffer bufp, TSMLoc obj)
2288 {
2289   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2290   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
2291 
2292   URLImpl *url_impl = (URLImpl *)obj;
2293   return url_length_get(url_impl);
2294 }
2295 
2296 char *
TSUrlStringGet(TSMBuffer bufp,TSMLoc obj,int * length)2297 TSUrlStringGet(TSMBuffer bufp, TSMLoc obj, int *length)
2298 {
2299   // bufp is not actually used anymore, so it can be null.
2300   if (bufp) {
2301     sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2302   }
2303   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
2304   sdk_assert(sdk_sanity_check_null_ptr((void *)length) == TS_SUCCESS);
2305 
2306   URLImpl *url_impl = (URLImpl *)obj;
2307   return url_string_get(url_impl, nullptr, length, nullptr);
2308 }
2309 
2310 using URLPartGetF = const char *(URL::*)(int *);
2311 using URLPartSetF = void (URL::*)(const char *, int);
2312 
2313 static const char *
URLPartGet(TSMBuffer bufp,TSMLoc obj,int * length,URLPartGetF url_f)2314 URLPartGet(TSMBuffer bufp, TSMLoc obj, int *length, URLPartGetF url_f)
2315 {
2316   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2317   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
2318   sdk_assert(sdk_sanity_check_null_ptr((void *)length) == TS_SUCCESS);
2319 
2320   URL u;
2321 
2322   u.m_heap     = ((HdrHeapSDKHandle *)bufp)->m_heap;
2323   u.m_url_impl = (URLImpl *)obj;
2324 
2325   return (u.*url_f)(length);
2326 }
2327 
2328 static TSReturnCode
URLPartSet(TSMBuffer bufp,TSMLoc obj,const char * value,int length,URLPartSetF url_f)2329 URLPartSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length, URLPartSetF url_f)
2330 {
2331   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2332   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
2333 
2334   if (!isWriteable(bufp)) {
2335     return TS_ERROR;
2336   }
2337 
2338   URL u;
2339   u.m_heap     = ((HdrHeapSDKHandle *)bufp)->m_heap;
2340   u.m_url_impl = (URLImpl *)obj;
2341 
2342   if (!value) {
2343     length = 0;
2344   } else if (length < 0) {
2345     length = strlen(value);
2346   }
2347   (u.*url_f)(value, length);
2348 
2349   return TS_SUCCESS;
2350 }
2351 
2352 const char *
TSUrlRawSchemeGet(TSMBuffer bufp,TSMLoc obj,int * length)2353 TSUrlRawSchemeGet(TSMBuffer bufp, TSMLoc obj, int *length)
2354 {
2355   return URLPartGet(bufp, obj, length, &URL::scheme_get);
2356 }
2357 
2358 const char *
TSUrlSchemeGet(TSMBuffer bufp,TSMLoc obj,int * length)2359 TSUrlSchemeGet(TSMBuffer bufp, TSMLoc obj, int *length)
2360 {
2361   char const *data = TSUrlRawSchemeGet(bufp, obj, length);
2362   if (data && *length) {
2363     return data;
2364   }
2365   switch (reinterpret_cast<URLImpl *>(obj)->m_url_type) {
2366   case URL_TYPE_HTTP:
2367     data    = URL_SCHEME_HTTP;
2368     *length = URL_LEN_HTTP;
2369     break;
2370   case URL_TYPE_HTTPS:
2371     data    = URL_SCHEME_HTTPS;
2372     *length = URL_LEN_HTTPS;
2373     break;
2374   default:
2375     *length = 0;
2376     data    = nullptr;
2377   }
2378   return data;
2379 }
2380 
2381 TSReturnCode
TSUrlSchemeSet(TSMBuffer bufp,TSMLoc obj,const char * value,int length)2382 TSUrlSchemeSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
2383 {
2384   return URLPartSet(bufp, obj, value, length, &URL::scheme_set);
2385 }
2386 
2387 /* Internet specific URLs */
2388 
2389 const char *
TSUrlUserGet(TSMBuffer bufp,TSMLoc obj,int * length)2390 TSUrlUserGet(TSMBuffer bufp, TSMLoc obj, int *length)
2391 {
2392   return URLPartGet(bufp, obj, length, &URL::user_get);
2393 }
2394 
2395 TSReturnCode
TSUrlUserSet(TSMBuffer bufp,TSMLoc obj,const char * value,int length)2396 TSUrlUserSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
2397 {
2398   return URLPartSet(bufp, obj, value, length, &URL::user_set);
2399 }
2400 
2401 const char *
TSUrlPasswordGet(TSMBuffer bufp,TSMLoc obj,int * length)2402 TSUrlPasswordGet(TSMBuffer bufp, TSMLoc obj, int *length)
2403 {
2404   return URLPartGet(bufp, obj, length, &URL::password_get);
2405 }
2406 
2407 TSReturnCode
TSUrlPasswordSet(TSMBuffer bufp,TSMLoc obj,const char * value,int length)2408 TSUrlPasswordSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
2409 {
2410   return URLPartSet(bufp, obj, value, length, &URL::password_set);
2411 }
2412 
2413 const char *
TSUrlHostGet(TSMBuffer bufp,TSMLoc obj,int * length)2414 TSUrlHostGet(TSMBuffer bufp, TSMLoc obj, int *length)
2415 {
2416   return URLPartGet(bufp, obj, length, &URL::host_get);
2417 }
2418 
2419 TSReturnCode
TSUrlHostSet(TSMBuffer bufp,TSMLoc obj,const char * value,int length)2420 TSUrlHostSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
2421 {
2422   return URLPartSet(bufp, obj, value, length, &URL::host_set);
2423 }
2424 
2425 int
TSUrlPortGet(TSMBuffer bufp,TSMLoc obj)2426 TSUrlPortGet(TSMBuffer bufp, TSMLoc obj)
2427 {
2428   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2429   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
2430 
2431   URL u;
2432   u.m_heap     = ((HdrHeapSDKHandle *)bufp)->m_heap;
2433   u.m_url_impl = (URLImpl *)obj;
2434 
2435   return u.port_get();
2436 }
2437 
2438 int
TSUrlRawPortGet(TSMBuffer bufp,TSMLoc obj)2439 TSUrlRawPortGet(TSMBuffer bufp, TSMLoc obj)
2440 {
2441   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2442   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
2443 
2444   URL u;
2445   u.m_heap     = ((HdrHeapSDKHandle *)bufp)->m_heap;
2446   u.m_url_impl = (URLImpl *)obj;
2447 
2448   return u.port_get_raw();
2449 }
2450 
2451 TSReturnCode
TSUrlPortSet(TSMBuffer bufp,TSMLoc obj,int port)2452 TSUrlPortSet(TSMBuffer bufp, TSMLoc obj, int port)
2453 {
2454   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2455   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
2456 
2457   if (!isWriteable(bufp) || (port < 0)) {
2458     return TS_ERROR;
2459   }
2460 
2461   URL u;
2462 
2463   u.m_heap     = ((HdrHeapSDKHandle *)bufp)->m_heap;
2464   u.m_url_impl = (URLImpl *)obj;
2465   u.port_set(port);
2466   return TS_SUCCESS;
2467 }
2468 
2469 /* FTP and HTTP specific URLs  */
2470 
2471 const char *
TSUrlPathGet(TSMBuffer bufp,TSMLoc obj,int * length)2472 TSUrlPathGet(TSMBuffer bufp, TSMLoc obj, int *length)
2473 {
2474   return URLPartGet(bufp, obj, length, &URL::path_get);
2475 }
2476 
2477 TSReturnCode
TSUrlPathSet(TSMBuffer bufp,TSMLoc obj,const char * value,int length)2478 TSUrlPathSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
2479 {
2480   return URLPartSet(bufp, obj, value, length, &URL::path_set);
2481 }
2482 
2483 /* FTP specific URLs */
2484 
2485 int
TSUrlFtpTypeGet(TSMBuffer bufp,TSMLoc obj)2486 TSUrlFtpTypeGet(TSMBuffer bufp, TSMLoc obj)
2487 {
2488   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2489   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
2490 
2491   URL u;
2492   u.m_heap     = ((HdrHeapSDKHandle *)bufp)->m_heap;
2493   u.m_url_impl = (URLImpl *)obj;
2494   return u.type_get();
2495 }
2496 
2497 TSReturnCode
TSUrlFtpTypeSet(TSMBuffer bufp,TSMLoc obj,int type)2498 TSUrlFtpTypeSet(TSMBuffer bufp, TSMLoc obj, int type)
2499 {
2500   // The valid values are : 0, 65('A'), 97('a'),
2501   // 69('E'), 101('e'), 73 ('I') and 105('i').
2502   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2503   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
2504 
2505   if ((type == 0 || type == 'A' || type == 'E' || type == 'I' || type == 'a' || type == 'i' || type == 'e') && isWriteable(bufp)) {
2506     URL u;
2507 
2508     u.m_heap     = ((HdrHeapSDKHandle *)bufp)->m_heap;
2509     u.m_url_impl = (URLImpl *)obj;
2510     u.type_set(type);
2511     return TS_SUCCESS;
2512   }
2513 
2514   return TS_ERROR;
2515 }
2516 
2517 /* HTTP specific URLs */
2518 
2519 const char *
TSUrlHttpParamsGet(TSMBuffer bufp,TSMLoc obj,int * length)2520 TSUrlHttpParamsGet(TSMBuffer bufp, TSMLoc obj, int *length)
2521 {
2522   return URLPartGet(bufp, obj, length, &URL::params_get);
2523 }
2524 
2525 TSReturnCode
TSUrlHttpParamsSet(TSMBuffer bufp,TSMLoc obj,const char * value,int length)2526 TSUrlHttpParamsSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
2527 {
2528   return URLPartSet(bufp, obj, value, length, &URL::params_set);
2529 }
2530 
2531 const char *
TSUrlHttpQueryGet(TSMBuffer bufp,TSMLoc obj,int * length)2532 TSUrlHttpQueryGet(TSMBuffer bufp, TSMLoc obj, int *length)
2533 {
2534   return URLPartGet(bufp, obj, length, &URL::query_get);
2535 }
2536 
2537 TSReturnCode
TSUrlHttpQuerySet(TSMBuffer bufp,TSMLoc obj,const char * value,int length)2538 TSUrlHttpQuerySet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
2539 {
2540   return URLPartSet(bufp, obj, value, length, &URL::query_set);
2541 }
2542 
2543 const char *
TSUrlHttpFragmentGet(TSMBuffer bufp,TSMLoc obj,int * length)2544 TSUrlHttpFragmentGet(TSMBuffer bufp, TSMLoc obj, int *length)
2545 {
2546   return URLPartGet(bufp, obj, length, &URL::fragment_get);
2547 }
2548 
2549 TSReturnCode
TSUrlHttpFragmentSet(TSMBuffer bufp,TSMLoc obj,const char * value,int length)2550 TSUrlHttpFragmentSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
2551 {
2552   return URLPartSet(bufp, obj, value, length, &URL::fragment_set);
2553 }
2554 
2555 // URL percent encoding
2556 TSReturnCode
TSStringPercentEncode(const char * str,int str_len,char * dst,size_t dst_size,size_t * length,const unsigned char * map)2557 TSStringPercentEncode(const char *str, int str_len, char *dst, size_t dst_size, size_t *length, const unsigned char *map)
2558 {
2559   sdk_assert(sdk_sanity_check_null_ptr((void *)str) == TS_SUCCESS);
2560   sdk_assert(sdk_sanity_check_null_ptr((void *)dst) == TS_SUCCESS);
2561 
2562   int new_len; // Unfortunately, a lot of the core uses "int" for length's internally...
2563 
2564   if (str_len < 0) {
2565     str_len = strlen(str);
2566   }
2567 
2568   sdk_assert(str_len < static_cast<int>(dst_size));
2569 
2570   // TODO: Perhaps we should make escapify_url() deal with const properly...
2571   // You would think making escapify_url const correct for the source argument would be easy, but in the case where
2572   // No escaping is needed, the source argument is returned.  If there is a destination argument, the source is copied over
2573   // However, if there is no destination argument, none is allocated.  I don't understand the full possibility of calling cases.
2574   // It seems like we might want to review how this is being called and perhaps create a number of smaller accessor methods that
2575   // can be set up correctly.
2576   if (nullptr == LogUtils::pure_escapify_url(nullptr, const_cast<char *>(str), str_len, &new_len, dst, dst_size, map)) {
2577     if (length) {
2578       *length = 0;
2579     }
2580     return TS_ERROR;
2581   }
2582 
2583   if (length) {
2584     *length = new_len;
2585   }
2586 
2587   return TS_SUCCESS;
2588 }
2589 
2590 TSReturnCode
TSStringPercentDecode(const char * str,size_t str_len,char * dst,size_t dst_size,size_t * length)2591 TSStringPercentDecode(const char *str, size_t str_len, char *dst, size_t dst_size, size_t *length)
2592 {
2593   sdk_assert(sdk_sanity_check_null_ptr((void *)str) == TS_SUCCESS);
2594   sdk_assert(sdk_sanity_check_null_ptr((void *)dst) == TS_SUCCESS);
2595 
2596   if (0 == str_len) {
2597     str_len = strlen(str);
2598   }
2599 
2600   // return unescapifyStr(str);
2601   char *buffer    = dst;
2602   const char *src = str;
2603   int s           = 0; // State, which we don't really use
2604 
2605   // TODO: We should check for "failures" here?
2606   unescape_str(buffer, buffer + dst_size, src, src + str_len, s);
2607 
2608   size_t data_written   = std::min<size_t>(buffer - dst, dst_size - 1);
2609   *(dst + data_written) = '\0';
2610 
2611   if (length) {
2612     *length = (data_written);
2613   }
2614 
2615   return TS_SUCCESS;
2616 }
2617 
2618 TSReturnCode
TSUrlPercentEncode(TSMBuffer bufp,TSMLoc obj,char * dst,size_t dst_size,size_t * length,const unsigned char * map)2619 TSUrlPercentEncode(TSMBuffer bufp, TSMLoc obj, char *dst, size_t dst_size, size_t *length, const unsigned char *map)
2620 {
2621   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2622   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
2623 
2624   char *url;
2625   int url_len;
2626   TSReturnCode ret;
2627   URLImpl *url_impl = (URLImpl *)obj;
2628 
2629   // TODO: at some point, it might be nice to allow this to write to a pre-allocated buffer
2630   url = url_string_get(url_impl, nullptr, &url_len, nullptr);
2631   ret = TSStringPercentEncode(url, url_len, dst, dst_size, length, map);
2632   ats_free(url);
2633 
2634   return ret;
2635 }
2636 
2637 // pton
2638 TSReturnCode
TSIpStringToAddr(const char * str,size_t str_len,sockaddr * addr)2639 TSIpStringToAddr(const char *str, size_t str_len, sockaddr *addr)
2640 {
2641   sdk_assert(sdk_sanity_check_null_ptr((void *)str) == TS_SUCCESS);
2642 
2643   if (0 != ats_ip_pton(std::string_view(str, str_len), addr)) {
2644     return TS_ERROR;
2645   }
2646 
2647   return TS_SUCCESS;
2648 }
2649 
2650 ////////////////////////////////////////////////////////////////////
2651 //
2652 // MIME Headers
2653 //
2654 ////////////////////////////////////////////////////////////////////
2655 
2656 /**************/
2657 /* MimeParser */
2658 /**************/
2659 
2660 TSMimeParser
TSMimeParserCreate()2661 TSMimeParserCreate()
2662 {
2663   TSMimeParser parser = reinterpret_cast<TSMimeParser>(ats_malloc(sizeof(MIMEParser)));
2664 
2665   mime_parser_init((MIMEParser *)parser);
2666   return parser;
2667 }
2668 
2669 void
TSMimeParserClear(TSMimeParser parser)2670 TSMimeParserClear(TSMimeParser parser)
2671 {
2672   sdk_assert(sdk_sanity_check_mime_parser(parser) == TS_SUCCESS);
2673 
2674   mime_parser_clear((MIMEParser *)parser);
2675 }
2676 
2677 void
TSMimeParserDestroy(TSMimeParser parser)2678 TSMimeParserDestroy(TSMimeParser parser)
2679 {
2680   sdk_assert(sdk_sanity_check_mime_parser(parser) == TS_SUCCESS);
2681 
2682   mime_parser_clear((MIMEParser *)parser);
2683   ats_free(parser);
2684 }
2685 
2686 /***********/
2687 /* MimeHdr */
2688 /***********/
2689 
2690 // TSMBuffer: pointers to HdrHeapSDKHandle objects
2691 // TSMLoc:    pointers to MIMEFieldSDKHandle objects
2692 
2693 TSReturnCode
TSMimeHdrCreate(TSMBuffer bufp,TSMLoc * locp)2694 TSMimeHdrCreate(TSMBuffer bufp, TSMLoc *locp)
2695 {
2696   // Allow to modify the buffer only
2697   // if bufp is modifiable. If bufp is not modifiable return
2698   // TS_ERROR. If not allowed, return NULL.
2699   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2700   sdk_assert(sdk_sanity_check_null_ptr((void *)locp) == TS_SUCCESS);
2701 
2702   if (!isWriteable(bufp)) {
2703     return TS_ERROR;
2704   }
2705 
2706   *locp = reinterpret_cast<TSMLoc>(mime_hdr_create(((HdrHeapSDKHandle *)bufp)->m_heap));
2707   return TS_SUCCESS;
2708 }
2709 
2710 TSReturnCode
TSMimeHdrDestroy(TSMBuffer bufp,TSMLoc obj)2711 TSMimeHdrDestroy(TSMBuffer bufp, TSMLoc obj)
2712 {
2713   // Allow to modify the buffer only
2714   // if bufp is modifiable. If bufp is not modifiable return
2715   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
2716   // return value of function from void to TSReturnCode.
2717   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2718   sdk_assert((sdk_sanity_check_mime_hdr_handle(obj) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS));
2719 
2720   if (!isWriteable(bufp)) {
2721     return TS_ERROR;
2722   }
2723 
2724   MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(obj);
2725 
2726   mime_hdr_destroy(((HdrHeapSDKHandle *)bufp)->m_heap, mh);
2727   return TS_SUCCESS;
2728 }
2729 
2730 TSReturnCode
TSMimeHdrClone(TSMBuffer dest_bufp,TSMBuffer src_bufp,TSMLoc src_hdr,TSMLoc * locp)2731 TSMimeHdrClone(TSMBuffer dest_bufp, TSMBuffer src_bufp, TSMLoc src_hdr, TSMLoc *locp)
2732 {
2733   // Allow to modify the buffer only
2734   // if bufp is modifiable. If bufp is not modifiable return
2735   // TS_ERROR. If not allowed, return NULL.
2736   sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
2737   sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
2738   sdk_assert(sdk_sanity_check_mime_hdr_handle(src_hdr) == TS_SUCCESS);
2739   sdk_assert(sdk_sanity_check_http_hdr_handle(src_hdr) == TS_SUCCESS);
2740   sdk_assert(sdk_sanity_check_null_ptr((void *)locp) == TS_SUCCESS);
2741 
2742   if (!isWriteable(dest_bufp)) {
2743     return TS_ERROR;
2744   }
2745 
2746   HdrHeap *s_heap, *d_heap;
2747   MIMEHdrImpl *s_mh, *d_mh;
2748 
2749   s_heap = ((HdrHeapSDKHandle *)src_bufp)->m_heap;
2750   d_heap = ((HdrHeapSDKHandle *)dest_bufp)->m_heap;
2751   s_mh   = _hdr_mloc_to_mime_hdr_impl(src_hdr);
2752 
2753   d_mh  = mime_hdr_clone(s_mh, s_heap, d_heap, (s_heap != d_heap));
2754   *locp = (TSMLoc)d_mh;
2755 
2756   return TS_SUCCESS;
2757 }
2758 
2759 TSReturnCode
TSMimeHdrCopy(TSMBuffer dest_bufp,TSMLoc dest_obj,TSMBuffer src_bufp,TSMLoc src_obj)2760 TSMimeHdrCopy(TSMBuffer dest_bufp, TSMLoc dest_obj, TSMBuffer src_bufp, TSMLoc src_obj)
2761 {
2762   // Allow to modify the buffer only
2763   // if bufp is modifiable. If bufp is not modifiable return
2764   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
2765   // return value of function from void to TSReturnCode.
2766   sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
2767   sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
2768   sdk_assert((sdk_sanity_check_mime_hdr_handle(src_obj) == TS_SUCCESS) ||
2769              (sdk_sanity_check_http_hdr_handle(src_obj) == TS_SUCCESS));
2770   sdk_assert((sdk_sanity_check_mime_hdr_handle(dest_obj) == TS_SUCCESS) ||
2771              (sdk_sanity_check_http_hdr_handle(dest_obj) == TS_SUCCESS));
2772 
2773   if (!isWriteable(dest_bufp)) {
2774     return TS_ERROR;
2775   }
2776 
2777   HdrHeap *s_heap, *d_heap;
2778   MIMEHdrImpl *s_mh, *d_mh;
2779 
2780   s_heap = ((HdrHeapSDKHandle *)src_bufp)->m_heap;
2781   d_heap = ((HdrHeapSDKHandle *)dest_bufp)->m_heap;
2782   s_mh   = _hdr_mloc_to_mime_hdr_impl(src_obj);
2783   d_mh   = _hdr_mloc_to_mime_hdr_impl(dest_obj);
2784 
2785   mime_hdr_fields_clear(d_heap, d_mh);
2786   mime_hdr_copy_onto(s_mh, s_heap, d_mh, d_heap, (s_heap != d_heap));
2787   return TS_SUCCESS;
2788 }
2789 
2790 void
TSMimeHdrPrint(TSMBuffer bufp,TSMLoc obj,TSIOBuffer iobufp)2791 TSMimeHdrPrint(TSMBuffer bufp, TSMLoc obj, TSIOBuffer iobufp)
2792 {
2793   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2794   sdk_assert((sdk_sanity_check_mime_hdr_handle(obj) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS));
2795   sdk_assert(sdk_sanity_check_iocore_structure(iobufp) == TS_SUCCESS);
2796 
2797   HdrHeap *heap   = ((HdrHeapSDKHandle *)bufp)->m_heap;
2798   MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(obj);
2799   MIOBuffer *b    = (MIOBuffer *)iobufp;
2800   IOBufferBlock *blk;
2801   int bufindex;
2802   int tmp, dumpoffset = 0;
2803   int done;
2804 
2805   do {
2806     blk = b->get_current_block();
2807     if (!blk || blk->write_avail() == 0) {
2808       b->add_block();
2809       blk = b->get_current_block();
2810     }
2811 
2812     bufindex = 0;
2813     tmp      = dumpoffset;
2814     done     = mime_hdr_print(heap, mh, blk->end(), blk->write_avail(), &bufindex, &tmp);
2815 
2816     dumpoffset += bufindex;
2817     b->fill(bufindex);
2818   } while (!done);
2819 }
2820 
2821 TSParseResult
TSMimeHdrParse(TSMimeParser parser,TSMBuffer bufp,TSMLoc obj,const char ** start,const char * end)2822 TSMimeHdrParse(TSMimeParser parser, TSMBuffer bufp, TSMLoc obj, const char **start, const char *end)
2823 {
2824   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2825   sdk_assert((sdk_sanity_check_mime_hdr_handle(obj) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS));
2826   sdk_assert(sdk_sanity_check_null_ptr((void *)start) == TS_SUCCESS);
2827   sdk_assert(sdk_sanity_check_null_ptr((void *)*start) == TS_SUCCESS);
2828   sdk_assert(sdk_sanity_check_null_ptr((void *)end) == TS_SUCCESS);
2829 
2830   if (!isWriteable(bufp)) {
2831     return TS_PARSE_ERROR;
2832   }
2833 
2834   MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(obj);
2835 
2836   return (TSParseResult)mime_parser_parse((MIMEParser *)parser, ((HdrHeapSDKHandle *)bufp)->m_heap, mh, start, end, false, false,
2837                                           false);
2838 }
2839 
2840 int
TSMimeHdrLengthGet(TSMBuffer bufp,TSMLoc obj)2841 TSMimeHdrLengthGet(TSMBuffer bufp, TSMLoc obj)
2842 {
2843   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2844   sdk_assert((sdk_sanity_check_mime_hdr_handle(obj) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS));
2845 
2846   MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(obj);
2847   return mime_hdr_length_get(mh);
2848 }
2849 
2850 TSReturnCode
TSMimeHdrFieldsClear(TSMBuffer bufp,TSMLoc obj)2851 TSMimeHdrFieldsClear(TSMBuffer bufp, TSMLoc obj)
2852 {
2853   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2854   sdk_assert((sdk_sanity_check_mime_hdr_handle(obj) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS));
2855 
2856   if (!isWriteable(bufp)) {
2857     return TS_ERROR;
2858   }
2859 
2860   MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(obj);
2861 
2862   mime_hdr_fields_clear(((HdrHeapSDKHandle *)bufp)->m_heap, mh);
2863   return TS_SUCCESS;
2864 }
2865 
2866 int
TSMimeHdrFieldsCount(TSMBuffer bufp,TSMLoc obj)2867 TSMimeHdrFieldsCount(TSMBuffer bufp, TSMLoc obj)
2868 {
2869   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2870   sdk_assert((sdk_sanity_check_mime_hdr_handle(obj) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS));
2871 
2872   MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(obj);
2873   return mime_hdr_fields_count(mh);
2874 }
2875 
2876 // The following three helper functions should not be used in plugins! Since they are not used
2877 // by plugins, there's no need to validate the input.
2878 const char *
TSMimeFieldValueGet(TSMBuffer,TSMLoc field_obj,int idx,int * value_len_ptr)2879 TSMimeFieldValueGet(TSMBuffer /* bufp ATS_UNUSED */, TSMLoc field_obj, int idx, int *value_len_ptr)
2880 {
2881   MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *)field_obj;
2882 
2883   if (idx >= 0) {
2884     return mime_field_value_get_comma_val(handle->field_ptr, value_len_ptr, idx);
2885   } else {
2886     return handle->field_ptr->value_get(value_len_ptr);
2887   }
2888 }
2889 
2890 void
TSMimeFieldValueSet(TSMBuffer bufp,TSMLoc field_obj,int idx,const char * value,int length)2891 TSMimeFieldValueSet(TSMBuffer bufp, TSMLoc field_obj, int idx, const char *value, int length)
2892 {
2893   MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *)field_obj;
2894   HdrHeap *heap              = ((HdrHeapSDKHandle *)bufp)->m_heap;
2895 
2896   if (length == -1) {
2897     length = strlen(value);
2898   }
2899 
2900   if (idx >= 0) {
2901     mime_field_value_set_comma_val(heap, handle->mh, handle->field_ptr, idx, value, length);
2902   } else {
2903     mime_field_value_set(heap, handle->mh, handle->field_ptr, value, length, true);
2904   }
2905 }
2906 
2907 void
TSMimeFieldValueInsert(TSMBuffer bufp,TSMLoc field_obj,const char * value,int length,int idx)2908 TSMimeFieldValueInsert(TSMBuffer bufp, TSMLoc field_obj, const char *value, int length, int idx)
2909 {
2910   MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *)field_obj;
2911   HdrHeap *heap              = ((HdrHeapSDKHandle *)bufp)->m_heap;
2912 
2913   if (length == -1) {
2914     length = strlen(value);
2915   }
2916 
2917   mime_field_value_insert_comma_val(heap, handle->mh, handle->field_ptr, idx, value, length);
2918 }
2919 
2920 /****************/
2921 /* MimeHdrField */
2922 /****************/
2923 
2924 // TSMBuffer: pointers to HdrHeapSDKHandle objects
2925 // TSMLoc:    pointers to MIMEFieldSDKHandle objects
2926 
2927 int
TSMimeHdrFieldEqual(TSMBuffer bufp,TSMLoc hdr_obj,TSMLoc field1_obj,TSMLoc field2_obj)2928 TSMimeHdrFieldEqual(TSMBuffer bufp, TSMLoc hdr_obj, TSMLoc field1_obj, TSMLoc field2_obj)
2929 {
2930   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2931   sdk_assert(sdk_sanity_check_field_handle(field1_obj, hdr_obj) == TS_SUCCESS);
2932   sdk_assert(sdk_sanity_check_field_handle(field2_obj, hdr_obj) == TS_SUCCESS);
2933 
2934   MIMEFieldSDKHandle *field1_handle = (MIMEFieldSDKHandle *)field1_obj;
2935   MIMEFieldSDKHandle *field2_handle = (MIMEFieldSDKHandle *)field2_obj;
2936 
2937   if ((field1_handle == nullptr) || (field2_handle == nullptr)) {
2938     return (field1_handle == field2_handle);
2939   }
2940   return (field1_handle->field_ptr == field2_handle->field_ptr);
2941 }
2942 
2943 TSMLoc
TSMimeHdrFieldGet(TSMBuffer bufp,TSMLoc hdr_obj,int idx)2944 TSMimeHdrFieldGet(TSMBuffer bufp, TSMLoc hdr_obj, int idx)
2945 {
2946   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2947   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr_obj) == TS_SUCCESS) ||
2948              (sdk_sanity_check_http_hdr_handle(hdr_obj) == TS_SUCCESS));
2949   sdk_assert(idx >= 0);
2950 
2951   MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(hdr_obj);
2952   MIMEField *f    = mime_hdr_field_get(mh, idx);
2953 
2954   if (f == nullptr) {
2955     return TS_NULL_MLOC;
2956   }
2957 
2958   MIMEFieldSDKHandle *h = sdk_alloc_field_handle(bufp, mh);
2959 
2960   h->field_ptr = f;
2961   return reinterpret_cast<TSMLoc>(h);
2962 }
2963 
2964 TSMLoc
TSMimeHdrFieldFind(TSMBuffer bufp,TSMLoc hdr_obj,const char * name,int length)2965 TSMimeHdrFieldFind(TSMBuffer bufp, TSMLoc hdr_obj, const char *name, int length)
2966 {
2967   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2968   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr_obj) == TS_SUCCESS) ||
2969              (sdk_sanity_check_http_hdr_handle(hdr_obj) == TS_SUCCESS));
2970   sdk_assert(sdk_sanity_check_null_ptr((void *)name) == TS_SUCCESS);
2971 
2972   if (length == -1) {
2973     length = strlen(name);
2974   }
2975 
2976   MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(hdr_obj);
2977   MIMEField *f    = mime_hdr_field_find(mh, name, length);
2978 
2979   if (f == nullptr) {
2980     return TS_NULL_MLOC;
2981   }
2982 
2983   MIMEFieldSDKHandle *h = sdk_alloc_field_handle(bufp, mh);
2984 
2985   h->field_ptr = f;
2986   return reinterpret_cast<TSMLoc>(h);
2987 }
2988 
2989 TSReturnCode
TSMimeHdrFieldAppend(TSMBuffer bufp,TSMLoc mh_mloc,TSMLoc field_mloc)2990 TSMimeHdrFieldAppend(TSMBuffer bufp, TSMLoc mh_mloc, TSMLoc field_mloc)
2991 {
2992   // Allow to modify the buffer only
2993   // if bufp is modifiable. If bufp is not modifiable return
2994   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
2995   // return value of function from void to TSReturnCode.
2996   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
2997   sdk_assert((sdk_sanity_check_mime_hdr_handle(mh_mloc) == TS_SUCCESS) ||
2998              (sdk_sanity_check_http_hdr_handle(mh_mloc) == TS_SUCCESS));
2999   sdk_assert(sdk_sanity_check_field_handle(field_mloc) == TS_SUCCESS);
3000 
3001   if (!isWriteable(bufp)) {
3002     return TS_ERROR;
3003   }
3004 
3005   MIMEField *mh_field;
3006   MIMEHdrImpl *mh                  = _hdr_mloc_to_mime_hdr_impl(mh_mloc);
3007   MIMEFieldSDKHandle *field_handle = (MIMEFieldSDKHandle *)field_mloc;
3008 
3009   //////////////////////////////////////////////////////////////////////
3010   // The field passed in field_mloc might have been allocated from    //
3011   // inside a MIME header (the correct way), or it might have been    //
3012   // created in isolation as a "standalone field" (the old way).      //
3013   //                                                                  //
3014   // If it's a standalone field (the associated mime header is NULL), //
3015   // then we need to now allocate a real field inside the header,     //
3016   // copy over the data, and convert the standalone field into a      //
3017   // forwarding pointer to the real field, in case it's used again    //
3018   //////////////////////////////////////////////////////////////////////
3019   if (field_handle->mh == nullptr) {
3020     HdrHeap *heap = (HdrHeap *)(((HdrHeapSDKHandle *)bufp)->m_heap);
3021 
3022     // allocate a new hdr field and copy any pre-set info
3023     mh_field = mime_field_create(heap, mh);
3024 
3025     // FIX: is it safe to copy everything over?
3026     memcpy(mh_field, field_handle->field_ptr, sizeof(MIMEField));
3027 
3028     // now set up the forwarding ptr from standalone field to hdr field
3029     field_handle->mh        = mh;
3030     field_handle->field_ptr = mh_field;
3031   }
3032 
3033   ink_assert(field_handle->mh == mh);
3034   ink_assert(field_handle->field_ptr->m_ptr_name);
3035 
3036   mime_hdr_field_attach(mh, field_handle->field_ptr, 1, nullptr);
3037   return TS_SUCCESS;
3038 }
3039 
3040 TSReturnCode
TSMimeHdrFieldRemove(TSMBuffer bufp,TSMLoc mh_mloc,TSMLoc field_mloc)3041 TSMimeHdrFieldRemove(TSMBuffer bufp, TSMLoc mh_mloc, TSMLoc field_mloc)
3042 {
3043   // Allow to modify the buffer only
3044   // if bufp is modifiable. If bufp is not modifiable return
3045   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
3046   // return value of function from void to TSReturnCode.
3047   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3048   sdk_assert((sdk_sanity_check_mime_hdr_handle(mh_mloc) == TS_SUCCESS) ||
3049              (sdk_sanity_check_http_hdr_handle(mh_mloc) == TS_SUCCESS));
3050   sdk_assert(sdk_sanity_check_field_handle(field_mloc, mh_mloc) == TS_SUCCESS);
3051 
3052   if (!isWriteable(bufp)) {
3053     return TS_ERROR;
3054   }
3055 
3056   MIMEFieldSDKHandle *field_handle = (MIMEFieldSDKHandle *)field_mloc;
3057 
3058   if (field_handle->mh != nullptr) {
3059     MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(mh_mloc);
3060     ink_assert(mh == field_handle->mh);
3061     sdk_sanity_check_field_handle(field_mloc, mh_mloc);
3062     mime_hdr_field_detach(mh, field_handle->field_ptr, false); // only detach this dup
3063   }
3064   return TS_SUCCESS;
3065 }
3066 
3067 TSReturnCode
TSMimeHdrFieldDestroy(TSMBuffer bufp,TSMLoc mh_mloc,TSMLoc field_mloc)3068 TSMimeHdrFieldDestroy(TSMBuffer bufp, TSMLoc mh_mloc, TSMLoc field_mloc)
3069 {
3070   // Allow to modify the buffer only
3071   // if bufp is modifiable. If bufp is not modifiable return
3072   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
3073   // return value of function from void to TSReturnCode.
3074   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3075   sdk_assert((sdk_sanity_check_mime_hdr_handle(mh_mloc) == TS_SUCCESS) ||
3076              (sdk_sanity_check_http_hdr_handle(mh_mloc) == TS_SUCCESS));
3077   sdk_assert(sdk_sanity_check_field_handle(field_mloc, mh_mloc) == TS_SUCCESS);
3078 
3079   if (!isWriteable(bufp)) {
3080     return TS_ERROR;
3081   }
3082 
3083   MIMEFieldSDKHandle *field_handle = (MIMEFieldSDKHandle *)field_mloc;
3084 
3085   if (field_handle->mh == nullptr) { // NOT SUPPORTED!!
3086     ink_release_assert(!"Failed MH");
3087   } else {
3088     MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(mh_mloc);
3089     HdrHeap *heap   = (HdrHeap *)(((HdrHeapSDKHandle *)bufp)->m_heap);
3090 
3091     ink_assert(mh == field_handle->mh);
3092     if (sdk_sanity_check_field_handle(field_mloc, mh_mloc) != TS_SUCCESS) {
3093       return TS_ERROR;
3094     }
3095 
3096     // detach and delete this field, but not all dups
3097     mime_hdr_field_delete(heap, mh, field_handle->field_ptr, false);
3098   }
3099   // for consistence, the handle will not be released here.
3100   // users will be required to do it.
3101   return TS_SUCCESS;
3102 }
3103 
3104 TSReturnCode
TSMimeHdrFieldCreate(TSMBuffer bufp,TSMLoc mh_mloc,TSMLoc * locp)3105 TSMimeHdrFieldCreate(TSMBuffer bufp, TSMLoc mh_mloc, TSMLoc *locp)
3106 {
3107   // Allow to modify the buffer only
3108   // if bufp is modifiable. If bufp is not modifiable return
3109   // TS_ERROR. If not allowed, return NULL.
3110   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3111   sdk_assert((sdk_sanity_check_mime_hdr_handle(mh_mloc) == TS_SUCCESS) ||
3112              (sdk_sanity_check_http_hdr_handle(mh_mloc) == TS_SUCCESS));
3113   sdk_assert(sdk_sanity_check_null_ptr((void *)locp) == TS_SUCCESS);
3114 
3115   if (!isWriteable(bufp)) {
3116     return TS_ERROR;
3117   }
3118 
3119   MIMEHdrImpl *mh       = _hdr_mloc_to_mime_hdr_impl(mh_mloc);
3120   HdrHeap *heap         = (HdrHeap *)(((HdrHeapSDKHandle *)bufp)->m_heap);
3121   MIMEFieldSDKHandle *h = sdk_alloc_field_handle(bufp, mh);
3122 
3123   h->field_ptr = mime_field_create(heap, mh);
3124   *locp        = reinterpret_cast<TSMLoc>(h);
3125   return TS_SUCCESS;
3126 }
3127 
3128 TSReturnCode
TSMimeHdrFieldCreateNamed(TSMBuffer bufp,TSMLoc mh_mloc,const char * name,int name_len,TSMLoc * locp)3129 TSMimeHdrFieldCreateNamed(TSMBuffer bufp, TSMLoc mh_mloc, const char *name, int name_len, TSMLoc *locp)
3130 {
3131   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3132   sdk_assert((sdk_sanity_check_mime_hdr_handle(mh_mloc) == TS_SUCCESS) ||
3133              (sdk_sanity_check_http_hdr_handle(mh_mloc) == TS_SUCCESS));
3134   sdk_assert(sdk_sanity_check_null_ptr((void *)name) == TS_SUCCESS);
3135   sdk_assert(sdk_sanity_check_null_ptr((void *)locp) == TS_SUCCESS);
3136 
3137   if (!isWriteable(bufp)) {
3138     return TS_ERROR;
3139   }
3140 
3141   if (name_len == -1) {
3142     name_len = strlen(name);
3143   }
3144 
3145   MIMEHdrImpl *mh       = _hdr_mloc_to_mime_hdr_impl(mh_mloc);
3146   HdrHeap *heap         = (HdrHeap *)(((HdrHeapSDKHandle *)bufp)->m_heap);
3147   MIMEFieldSDKHandle *h = sdk_alloc_field_handle(bufp, mh);
3148   h->field_ptr          = mime_field_create_named(heap, mh, name, name_len);
3149   *locp                 = reinterpret_cast<TSMLoc>(h);
3150   return TS_SUCCESS;
3151 }
3152 
3153 TSReturnCode
TSMimeHdrFieldCopy(TSMBuffer dest_bufp,TSMLoc dest_hdr,TSMLoc dest_field,TSMBuffer src_bufp,TSMLoc src_hdr,TSMLoc src_field)3154 TSMimeHdrFieldCopy(TSMBuffer dest_bufp, TSMLoc dest_hdr, TSMLoc dest_field, TSMBuffer src_bufp, TSMLoc src_hdr, TSMLoc src_field)
3155 {
3156   // Allow to modify the buffer only
3157   // if bufp is modifiable. If bufp is not modifiable return
3158   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
3159   // return value of function from void to TSReturnCode.
3160   sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
3161   sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
3162   sdk_assert((sdk_sanity_check_mime_hdr_handle(src_hdr) == TS_SUCCESS) ||
3163              (sdk_sanity_check_http_hdr_handle(src_hdr) == TS_SUCCESS));
3164   sdk_assert((sdk_sanity_check_mime_hdr_handle(dest_hdr) == TS_SUCCESS) ||
3165              (sdk_sanity_check_http_hdr_handle(dest_hdr) == TS_SUCCESS));
3166   sdk_assert(sdk_sanity_check_field_handle(src_field, src_hdr) == TS_SUCCESS);
3167   sdk_assert(sdk_sanity_check_field_handle(dest_field, dest_hdr) == TS_SUCCESS);
3168 
3169   if (!isWriteable(dest_bufp)) {
3170     return TS_ERROR;
3171   }
3172 
3173   bool dest_attached;
3174   MIMEFieldSDKHandle *s_handle = (MIMEFieldSDKHandle *)src_field;
3175   MIMEFieldSDKHandle *d_handle = (MIMEFieldSDKHandle *)dest_field;
3176   HdrHeap *d_heap              = ((HdrHeapSDKHandle *)dest_bufp)->m_heap;
3177 
3178   // FIX: This tortuous detach/change/attach algorithm is due to the
3179   //      fact that we can't change the name of an attached header (assertion)
3180 
3181   // TODO: This is never used ... is_live() has no side effects, so this should be ok
3182   // to not call, so commented out
3183   // src_attached = (s_handle->mh && s_handle->field_ptr->is_live());
3184   dest_attached = (d_handle->mh && d_handle->field_ptr->is_live());
3185 
3186   if (dest_attached) {
3187     mime_hdr_field_detach(d_handle->mh, d_handle->field_ptr, false);
3188   }
3189 
3190   mime_field_name_value_set(d_heap, d_handle->mh, d_handle->field_ptr, s_handle->field_ptr->m_wks_idx,
3191                             s_handle->field_ptr->m_ptr_name, s_handle->field_ptr->m_len_name, s_handle->field_ptr->m_ptr_value,
3192                             s_handle->field_ptr->m_len_value, 0, 0, true);
3193 
3194   if (dest_attached) {
3195     mime_hdr_field_attach(d_handle->mh, d_handle->field_ptr, 1, nullptr);
3196   }
3197   return TS_SUCCESS;
3198 }
3199 
3200 TSReturnCode
TSMimeHdrFieldClone(TSMBuffer dest_bufp,TSMLoc dest_hdr,TSMBuffer src_bufp,TSMLoc src_hdr,TSMLoc src_field,TSMLoc * locp)3201 TSMimeHdrFieldClone(TSMBuffer dest_bufp, TSMLoc dest_hdr, TSMBuffer src_bufp, TSMLoc src_hdr, TSMLoc src_field, TSMLoc *locp)
3202 {
3203   // Allow to modify the buffer only
3204   // if bufp is modifiable. If bufp is not modifiable return
3205   // TS_ERROR. If not allowed, return NULL.
3206   sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
3207   sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
3208   sdk_assert((sdk_sanity_check_mime_hdr_handle(dest_hdr) == TS_SUCCESS) ||
3209              (sdk_sanity_check_http_hdr_handle(dest_hdr) == TS_SUCCESS));
3210   sdk_assert((sdk_sanity_check_mime_hdr_handle(src_hdr) == TS_SUCCESS) ||
3211              (sdk_sanity_check_http_hdr_handle(src_hdr) == TS_SUCCESS));
3212   sdk_assert(sdk_sanity_check_field_handle(src_field, src_hdr) == TS_SUCCESS);
3213   sdk_assert(sdk_sanity_check_null_ptr((void *)locp) == TS_SUCCESS);
3214 
3215   if (!isWriteable(dest_bufp)) {
3216     return TS_ERROR;
3217   }
3218 
3219   // This is sort of sub-optimal, since we'll check the args again. TODO.
3220   if (TSMimeHdrFieldCreate(dest_bufp, dest_hdr, locp) == TS_SUCCESS) {
3221     TSMimeHdrFieldCopy(dest_bufp, dest_hdr, *locp, src_bufp, src_hdr, src_field);
3222     return TS_SUCCESS;
3223   }
3224   // TSMimeHdrFieldCreate() failed for some reason.
3225   return TS_ERROR;
3226 }
3227 
3228 TSReturnCode
TSMimeHdrFieldCopyValues(TSMBuffer dest_bufp,TSMLoc dest_hdr,TSMLoc dest_field,TSMBuffer src_bufp,TSMLoc src_hdr,TSMLoc src_field)3229 TSMimeHdrFieldCopyValues(TSMBuffer dest_bufp, TSMLoc dest_hdr, TSMLoc dest_field, TSMBuffer src_bufp, TSMLoc src_hdr,
3230                          TSMLoc src_field)
3231 {
3232   // Allow to modify the buffer only
3233   // if bufp is modifiable. If bufp is not modifiable return
3234   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
3235   // return value of function from void to TSReturnCode.
3236   sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
3237   sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
3238   sdk_assert((sdk_sanity_check_mime_hdr_handle(src_hdr) == TS_SUCCESS) ||
3239              (sdk_sanity_check_http_hdr_handle(src_hdr) == TS_SUCCESS));
3240   sdk_assert((sdk_sanity_check_mime_hdr_handle(dest_hdr) == TS_SUCCESS) ||
3241              (sdk_sanity_check_http_hdr_handle(dest_hdr) == TS_SUCCESS));
3242   sdk_assert(sdk_sanity_check_field_handle(src_field, src_hdr) == TS_SUCCESS);
3243   sdk_assert(sdk_sanity_check_field_handle(dest_field, dest_hdr) == TS_SUCCESS);
3244 
3245   if (!isWriteable(dest_bufp)) {
3246     return TS_ERROR;
3247   }
3248 
3249   MIMEFieldSDKHandle *s_handle = (MIMEFieldSDKHandle *)src_field;
3250   MIMEFieldSDKHandle *d_handle = (MIMEFieldSDKHandle *)dest_field;
3251   HdrHeap *d_heap              = ((HdrHeapSDKHandle *)dest_bufp)->m_heap;
3252   MIMEField *s_field, *d_field;
3253 
3254   s_field = s_handle->field_ptr;
3255   d_field = d_handle->field_ptr;
3256   mime_field_value_set(d_heap, d_handle->mh, d_field, s_field->m_ptr_value, s_field->m_len_value, true);
3257   return TS_SUCCESS;
3258 }
3259 
3260 // TODO: This is implemented horribly slowly, but who's using it anyway?
3261 //       If we threaded all the MIMEFields, this function could be easier,
3262 //       but we'd have to print dups in order and we'd need a flag saying
3263 //       end of dup list or dup follows.
3264 TSMLoc
TSMimeHdrFieldNext(TSMBuffer bufp,TSMLoc hdr,TSMLoc field)3265 TSMimeHdrFieldNext(TSMBuffer bufp, TSMLoc hdr, TSMLoc field)
3266 {
3267   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3268   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
3269   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
3270 
3271   MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *)field;
3272 
3273   if (handle->mh == nullptr) {
3274     return TS_NULL_MLOC;
3275   }
3276 
3277   int slotnum = mime_hdr_field_slotnum(handle->mh, handle->field_ptr);
3278   if (slotnum == -1) {
3279     return TS_NULL_MLOC;
3280   }
3281 
3282   while (true) {
3283     ++slotnum;
3284     MIMEField *f = mime_hdr_field_get_slotnum(handle->mh, slotnum);
3285 
3286     if (f == nullptr) {
3287       return TS_NULL_MLOC;
3288     }
3289     if (f->is_live()) {
3290       MIMEFieldSDKHandle *h = sdk_alloc_field_handle(bufp, handle->mh);
3291 
3292       h->field_ptr = f;
3293       return reinterpret_cast<TSMLoc>(h);
3294     }
3295   }
3296   return TS_NULL_MLOC; // Shouldn't happen.
3297 }
3298 
3299 TSMLoc
TSMimeHdrFieldNextDup(TSMBuffer bufp,TSMLoc hdr,TSMLoc field)3300 TSMimeHdrFieldNextDup(TSMBuffer bufp, TSMLoc hdr, TSMLoc field)
3301 {
3302   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3303   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
3304   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
3305 
3306   MIMEHdrImpl *mh                  = _hdr_mloc_to_mime_hdr_impl(hdr);
3307   MIMEFieldSDKHandle *field_handle = (MIMEFieldSDKHandle *)field;
3308   MIMEField *next                  = field_handle->field_ptr->m_next_dup;
3309   if (next == nullptr) {
3310     return TS_NULL_MLOC;
3311   }
3312 
3313   MIMEFieldSDKHandle *next_handle = sdk_alloc_field_handle(bufp, mh);
3314   next_handle->field_ptr          = next;
3315   return (TSMLoc)next_handle;
3316 }
3317 
3318 int
TSMimeHdrFieldLengthGet(TSMBuffer bufp,TSMLoc hdr,TSMLoc field)3319 TSMimeHdrFieldLengthGet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field)
3320 {
3321   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3322   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
3323   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
3324 
3325   MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *)field;
3326   return mime_field_length_get(handle->field_ptr);
3327 }
3328 
3329 const char *
TSMimeHdrFieldNameGet(TSMBuffer bufp,TSMLoc hdr,TSMLoc field,int * length)3330 TSMimeHdrFieldNameGet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int *length)
3331 {
3332   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3333   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
3334   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
3335   sdk_assert(sdk_sanity_check_null_ptr((void *)length) == TS_SUCCESS);
3336 
3337   MIMEFieldSDKHandle *handle = reinterpret_cast<MIMEFieldSDKHandle *>(field);
3338   return handle->field_ptr->name_get(length);
3339 }
3340 
3341 TSReturnCode
TSMimeHdrFieldNameSet(TSMBuffer bufp,TSMLoc hdr,TSMLoc field,const char * name,int length)3342 TSMimeHdrFieldNameSet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, const char *name, int length)
3343 {
3344   // Allow to modify the buffer only
3345   // if bufp is modifiable. If bufp is not modifiable return
3346   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
3347   // return value of function from void to TSReturnCode.
3348   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3349   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
3350   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
3351   sdk_assert(sdk_sanity_check_null_ptr((void *)name) == TS_SUCCESS);
3352 
3353   if (!isWriteable(bufp)) {
3354     return TS_ERROR;
3355   }
3356 
3357   if (length == -1) {
3358     length = strlen(name);
3359   }
3360 
3361   MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *)field;
3362   HdrHeap *heap              = ((HdrHeapSDKHandle *)bufp)->m_heap;
3363 
3364   int attached = (handle->mh && handle->field_ptr->is_live());
3365 
3366   if (attached) {
3367     mime_hdr_field_detach(handle->mh, handle->field_ptr, false);
3368   }
3369 
3370   handle->field_ptr->name_set(heap, handle->mh, name, length);
3371 
3372   if (attached) {
3373     mime_hdr_field_attach(handle->mh, handle->field_ptr, 1, nullptr);
3374   }
3375   return TS_SUCCESS;
3376 }
3377 
3378 TSReturnCode
TSMimeHdrFieldValuesClear(TSMBuffer bufp,TSMLoc hdr,TSMLoc field)3379 TSMimeHdrFieldValuesClear(TSMBuffer bufp, TSMLoc hdr, TSMLoc field)
3380 {
3381   // Allow to modify the buffer only
3382   // if bufp is modifiable. If bufp is not modifiable return
3383   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
3384   // return value of function from void to TSReturnCode.
3385   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3386   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
3387   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
3388 
3389   if (!isWriteable(bufp)) {
3390     return TS_ERROR;
3391   }
3392 
3393   MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *)field;
3394   HdrHeap *heap              = ((HdrHeapSDKHandle *)bufp)->m_heap;
3395 
3396   /**
3397    * Modified the string value passed from an empty string ("") to NULL.
3398    * An empty string is also considered to be a token. The correct value of
3399    * the field after this function should be NULL.
3400    */
3401   mime_field_value_set(heap, handle->mh, handle->field_ptr, nullptr, 0, true);
3402   return TS_SUCCESS;
3403 }
3404 
3405 int
TSMimeHdrFieldValuesCount(TSMBuffer bufp,TSMLoc hdr,TSMLoc field)3406 TSMimeHdrFieldValuesCount(TSMBuffer bufp, TSMLoc hdr, TSMLoc field)
3407 {
3408   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3409   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
3410   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
3411 
3412   MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *)field;
3413   return mime_field_value_get_comma_val_count(handle->field_ptr);
3414 }
3415 
3416 const char *
TSMimeHdrFieldValueStringGet(TSMBuffer bufp,TSMLoc hdr,TSMLoc field,int idx,int * value_len_ptr)3417 TSMimeHdrFieldValueStringGet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, int *value_len_ptr)
3418 {
3419   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3420   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
3421   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
3422   sdk_assert(sdk_sanity_check_null_ptr((void *)value_len_ptr) == TS_SUCCESS);
3423 
3424   return TSMimeFieldValueGet(bufp, field, idx, value_len_ptr);
3425 }
3426 
3427 time_t
TSMimeHdrFieldValueDateGet(TSMBuffer bufp,TSMLoc hdr,TSMLoc field)3428 TSMimeHdrFieldValueDateGet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field)
3429 {
3430   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3431   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
3432   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
3433 
3434   int value_len;
3435   const char *value_str = TSMimeFieldValueGet(bufp, field, -1, &value_len);
3436 
3437   if (value_str == nullptr) {
3438     return (time_t)0;
3439   }
3440 
3441   return mime_parse_date(value_str, value_str + value_len);
3442 }
3443 
3444 time_t
TSMimeParseDate(char const * const value_str,int const value_len)3445 TSMimeParseDate(char const *const value_str, int const value_len)
3446 {
3447   if (value_str == nullptr) {
3448     return (time_t)0;
3449   }
3450 
3451   return mime_parse_date(value_str, value_str + value_len);
3452 }
3453 
3454 int
TSMimeHdrFieldValueIntGet(TSMBuffer bufp,TSMLoc hdr,TSMLoc field,int idx)3455 TSMimeHdrFieldValueIntGet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx)
3456 {
3457   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3458   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
3459   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
3460 
3461   int value_len;
3462   const char *value_str = TSMimeFieldValueGet(bufp, field, idx, &value_len);
3463 
3464   if (value_str == nullptr) {
3465     return 0;
3466   }
3467 
3468   return mime_parse_int(value_str, value_str + value_len);
3469 }
3470 
3471 int64_t
TSMimeHdrFieldValueInt64Get(TSMBuffer bufp,TSMLoc hdr,TSMLoc field,int idx)3472 TSMimeHdrFieldValueInt64Get(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx)
3473 {
3474   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3475   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
3476   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
3477 
3478   int value_len;
3479   const char *value_str = TSMimeFieldValueGet(bufp, field, idx, &value_len);
3480 
3481   if (value_str == nullptr) {
3482     return 0;
3483   }
3484 
3485   return mime_parse_int64(value_str, value_str + value_len);
3486 }
3487 
3488 unsigned int
TSMimeHdrFieldValueUintGet(TSMBuffer bufp,TSMLoc hdr,TSMLoc field,int idx)3489 TSMimeHdrFieldValueUintGet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx)
3490 {
3491   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3492   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
3493   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
3494 
3495   int value_len;
3496   const char *value_str = TSMimeFieldValueGet(bufp, field, idx, &value_len);
3497 
3498   if (value_str == nullptr) {
3499     return 0;
3500   }
3501 
3502   return mime_parse_uint(value_str, value_str + value_len);
3503 }
3504 
3505 TSReturnCode
TSMimeHdrFieldValueStringSet(TSMBuffer bufp,TSMLoc hdr,TSMLoc field,int idx,const char * value,int length)3506 TSMimeHdrFieldValueStringSet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, const char *value, int length)
3507 {
3508   // Allow to modify the buffer only
3509   // if bufp is modifiable. If bufp is not modifiable return
3510   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
3511   // return value of function from void to TSReturnCode.
3512   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3513   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
3514   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
3515   sdk_assert(sdk_sanity_check_null_ptr((void *)value) == TS_SUCCESS);
3516 
3517   if (!isWriteable(bufp)) {
3518     return TS_ERROR;
3519   }
3520 
3521   if (length == -1) {
3522     length = strlen(value);
3523   }
3524 
3525   TSMimeFieldValueSet(bufp, field, idx, value, length);
3526   return TS_SUCCESS;
3527 }
3528 
3529 TSReturnCode
TSMimeHdrFieldValueDateSet(TSMBuffer bufp,TSMLoc hdr,TSMLoc field,time_t value)3530 TSMimeHdrFieldValueDateSet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, time_t value)
3531 {
3532   // Allow to modify the buffer only
3533   // if bufp is modifiable. If bufp is not modifiable return
3534   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
3535   // return value of function from void to TSReturnCode.
3536   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3537   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
3538   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
3539 
3540   if (!isWriteable(bufp)) {
3541     return TS_ERROR;
3542   }
3543 
3544   char tmp[33];
3545   int len = mime_format_date(tmp, value);
3546 
3547   // idx is ignored and we overwrite all existing values
3548   // TSMimeFieldValueSet(bufp, field_obj, idx, tmp, len);
3549   TSMimeFieldValueSet(bufp, field, -1, tmp, len);
3550   return TS_SUCCESS;
3551 }
3552 
3553 TSReturnCode
TSMimeFormatDate(time_t const value_time,char * const value_str,int * const value_length)3554 TSMimeFormatDate(time_t const value_time, char *const value_str, int *const value_length)
3555 {
3556   if (value_length == nullptr) {
3557     return TS_ERROR;
3558   }
3559 
3560   if (*value_length < 33) {
3561     return TS_ERROR;
3562   }
3563 
3564   *value_length = mime_format_date(value_str, value_time);
3565   return TS_SUCCESS;
3566 }
3567 
3568 TSReturnCode
TSMimeHdrFieldValueIntSet(TSMBuffer bufp,TSMLoc hdr,TSMLoc field,int idx,int value)3569 TSMimeHdrFieldValueIntSet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, int value)
3570 {
3571   // Allow to modify the buffer only
3572   // if bufp is modifiable. If bufp is not modifiable return
3573   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
3574   // return value of function from void to TSReturnCode.
3575   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3576   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
3577   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
3578 
3579   if (!isWriteable(bufp)) {
3580     return TS_ERROR;
3581   }
3582 
3583   char tmp[16];
3584   int len = mime_format_int(tmp, value, sizeof(tmp));
3585 
3586   TSMimeFieldValueSet(bufp, field, idx, tmp, len);
3587   return TS_SUCCESS;
3588 }
3589 
3590 TSReturnCode
TSMimeHdrFieldValueInt64Set(TSMBuffer bufp,TSMLoc hdr,TSMLoc field,int idx,int64_t value)3591 TSMimeHdrFieldValueInt64Set(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, int64_t value)
3592 {
3593   // Allow to modify the buffer only
3594   // if bufp is modifiable. If bufp is not modifiable return
3595   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
3596   // return value of function from void to TSReturnCode.
3597   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3598   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
3599   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
3600 
3601   if (!isWriteable(bufp)) {
3602     return TS_ERROR;
3603   }
3604 
3605   char tmp[20];
3606   int len = mime_format_int64(tmp, value, sizeof(tmp));
3607 
3608   TSMimeFieldValueSet(bufp, field, idx, tmp, len);
3609   return TS_SUCCESS;
3610 }
3611 
3612 TSReturnCode
TSMimeHdrFieldValueUintSet(TSMBuffer bufp,TSMLoc hdr,TSMLoc field,int idx,unsigned int value)3613 TSMimeHdrFieldValueUintSet(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, unsigned int value)
3614 {
3615   // Allow to modify the buffer only
3616   // if bufp is modifiable. If bufp is not modifiable return
3617   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
3618   // return value of function from void to TSReturnCode.
3619   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3620   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
3621   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
3622 
3623   if (!isWriteable(bufp)) {
3624     return TS_ERROR;
3625   }
3626 
3627   char tmp[16];
3628   int len = mime_format_uint(tmp, value, sizeof(tmp));
3629 
3630   TSMimeFieldValueSet(bufp, field, idx, tmp, len);
3631   return TS_SUCCESS;
3632 }
3633 
3634 TSReturnCode
TSMimeHdrFieldValueAppend(TSMBuffer bufp,TSMLoc hdr,TSMLoc field,int idx,const char * value,int length)3635 TSMimeHdrFieldValueAppend(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, const char *value, int length)
3636 {
3637   // Allow to modify the buffer only
3638   // if bufp is modifiable. If bufp is not modifiable return
3639   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
3640   // return value of function from void to TSReturnCode.
3641   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3642   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
3643   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
3644   sdk_assert(sdk_sanity_check_null_ptr((void *)value) == TS_SUCCESS);
3645   sdk_assert(idx >= 0);
3646 
3647   if (!isWriteable(bufp)) {
3648     return TS_ERROR;
3649   }
3650 
3651   MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *)field;
3652   HdrHeap *heap              = ((HdrHeapSDKHandle *)bufp)->m_heap;
3653 
3654   if (length == -1) {
3655     length = strlen(value);
3656   }
3657   mime_field_value_extend_comma_val(heap, handle->mh, handle->field_ptr, idx, value, length);
3658   return TS_SUCCESS;
3659 }
3660 
3661 TSReturnCode
TSMimeHdrFieldValueStringInsert(TSMBuffer bufp,TSMLoc hdr,TSMLoc field,int idx,const char * value,int length)3662 TSMimeHdrFieldValueStringInsert(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, const char *value, int length)
3663 {
3664   // Allow to modify the buffer only
3665   // if bufp is modifiable. If bufp is not modifiable return
3666   // TS_ERROR, else return TS_SUCCESS.
3667   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3668   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
3669   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
3670   sdk_assert(sdk_sanity_check_null_ptr((void *)value) == TS_SUCCESS);
3671 
3672   if (!isWriteable(bufp)) {
3673     return TS_ERROR;
3674   }
3675 
3676   if (length == -1) {
3677     length = strlen(value);
3678   }
3679   TSMimeFieldValueInsert(bufp, field, value, length, idx);
3680   return TS_SUCCESS;
3681 }
3682 
3683 TSReturnCode
TSMimeHdrFieldValueIntInsert(TSMBuffer bufp,TSMLoc hdr,TSMLoc field,int idx,int value)3684 TSMimeHdrFieldValueIntInsert(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, int value)
3685 {
3686   // Allow to modify the buffer only
3687   // if bufp is modifiable. If bufp is not modifiable return
3688   // TS_ERROR, else return TS_SUCCESS.
3689   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3690   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
3691   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
3692 
3693   if (!isWriteable(bufp)) {
3694     return TS_ERROR;
3695   }
3696 
3697   char tmp[16];
3698   int len = mime_format_int(tmp, value, sizeof(tmp));
3699 
3700   TSMimeFieldValueInsert(bufp, field, tmp, len, idx);
3701   return TS_SUCCESS;
3702 }
3703 
3704 TSReturnCode
TSMimeHdrFieldValueUintInsert(TSMBuffer bufp,TSMLoc hdr,TSMLoc field,int idx,unsigned int value)3705 TSMimeHdrFieldValueUintInsert(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx, unsigned int value)
3706 {
3707   // Allow to modify the buffer only
3708   // if bufp is modifiable. If bufp is not modifiable return
3709   // TS_ERROR, else return TS_SUCCESS.
3710   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3711   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
3712   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
3713 
3714   if (!isWriteable(bufp)) {
3715     return TS_ERROR;
3716   }
3717 
3718   char tmp[16];
3719   int len = mime_format_uint(tmp, value, sizeof(tmp));
3720 
3721   TSMimeFieldValueInsert(bufp, field, tmp, len, idx);
3722   return TS_SUCCESS;
3723 }
3724 
3725 TSReturnCode
TSMimeHdrFieldValueDateInsert(TSMBuffer bufp,TSMLoc hdr,TSMLoc field,time_t value)3726 TSMimeHdrFieldValueDateInsert(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, time_t value)
3727 {
3728   // Allow to modify the buffer only
3729   // if bufp is modifiable. If bufp is not modifiable return
3730   // TS_ERROR, else return TS_SUCCESS
3731   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3732   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
3733   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
3734 
3735   if (!isWriteable(bufp)) {
3736     return TS_ERROR;
3737   }
3738 
3739   if (TSMimeHdrFieldValuesClear(bufp, hdr, field) == TS_ERROR) {
3740     return TS_ERROR;
3741   }
3742 
3743   char tmp[33];
3744   int len = mime_format_date(tmp, value);
3745   // idx ignored, overwrite all existing values
3746   // (void)TSMimeFieldValueInsert(bufp, field_obj, tmp, len, idx);
3747   (void)TSMimeFieldValueSet(bufp, field, -1, tmp, len);
3748   return TS_SUCCESS;
3749 }
3750 
3751 TSReturnCode
TSMimeHdrFieldValueDelete(TSMBuffer bufp,TSMLoc hdr,TSMLoc field,int idx)3752 TSMimeHdrFieldValueDelete(TSMBuffer bufp, TSMLoc hdr, TSMLoc field, int idx)
3753 {
3754   // Allow to modify the buffer only
3755   // if bufp is modifiable. If bufp is not modifiable return
3756   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
3757   // return value of function from void to TSReturnCode.
3758   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3759   sdk_assert((sdk_sanity_check_mime_hdr_handle(hdr) == TS_SUCCESS) || (sdk_sanity_check_http_hdr_handle(hdr) == TS_SUCCESS));
3760   sdk_assert(sdk_sanity_check_field_handle(field, hdr) == TS_SUCCESS);
3761   sdk_assert(idx >= 0);
3762 
3763   if (!isWriteable(bufp)) {
3764     return TS_ERROR;
3765   }
3766 
3767   MIMEFieldSDKHandle *handle = (MIMEFieldSDKHandle *)field;
3768   HdrHeap *heap              = ((HdrHeapSDKHandle *)bufp)->m_heap;
3769 
3770   mime_field_value_delete_comma_val(heap, handle->mh, handle->field_ptr, idx);
3771   return TS_SUCCESS;
3772 }
3773 
3774 /**************/
3775 /* HttpParser */
3776 /**************/
3777 TSHttpParser
TSHttpParserCreate()3778 TSHttpParserCreate()
3779 {
3780   TSHttpParser parser = reinterpret_cast<TSHttpParser>(ats_malloc(sizeof(HTTPParser)));
3781   http_parser_init((HTTPParser *)parser);
3782 
3783   return parser;
3784 }
3785 
3786 void
TSHttpParserClear(TSHttpParser parser)3787 TSHttpParserClear(TSHttpParser parser)
3788 {
3789   sdk_assert(sdk_sanity_check_http_parser(parser) == TS_SUCCESS);
3790   http_parser_clear((HTTPParser *)parser);
3791 }
3792 
3793 void
TSHttpParserDestroy(TSHttpParser parser)3794 TSHttpParserDestroy(TSHttpParser parser)
3795 {
3796   sdk_assert(sdk_sanity_check_http_parser(parser) == TS_SUCCESS);
3797   http_parser_clear((HTTPParser *)parser);
3798   ats_free(parser);
3799 }
3800 
3801 /***********/
3802 /* HttpHdr */
3803 /***********/
3804 
3805 TSMLoc
TSHttpHdrCreate(TSMBuffer bufp)3806 TSHttpHdrCreate(TSMBuffer bufp)
3807 {
3808   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3809 
3810   HTTPHdr h;
3811   h.m_heap = ((HdrHeapSDKHandle *)bufp)->m_heap;
3812   h.create(HTTP_TYPE_UNKNOWN);
3813   return (TSMLoc)(h.m_http);
3814 }
3815 
3816 void
TSHttpHdrDestroy(TSMBuffer bufp,TSMLoc obj)3817 TSHttpHdrDestroy(TSMBuffer bufp, TSMLoc obj)
3818 {
3819   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3820   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
3821 
3822   // No more objects counts in heap or deallocation
3823   //   so do nothing!
3824 
3825   // HDR FIX ME - Did this free the MBuffer in Pete's old system
3826 }
3827 
3828 TSReturnCode
TSHttpHdrClone(TSMBuffer dest_bufp,TSMBuffer src_bufp,TSMLoc src_hdr,TSMLoc * locp)3829 TSHttpHdrClone(TSMBuffer dest_bufp, TSMBuffer src_bufp, TSMLoc src_hdr, TSMLoc *locp)
3830 {
3831   // Allow to modify the buffer only
3832   // if bufp is modifiable. If bufp is not modifiable return
3833   // TS_ERROR. If not allowed, return NULL.
3834   sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
3835   sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
3836   sdk_assert(sdk_sanity_check_http_hdr_handle(src_hdr) == TS_SUCCESS);
3837 
3838   if (!isWriteable(dest_bufp)) {
3839     return TS_ERROR;
3840   }
3841 
3842   HdrHeap *s_heap, *d_heap;
3843   HTTPHdrImpl *s_hh, *d_hh;
3844 
3845   s_heap = ((HdrHeapSDKHandle *)src_bufp)->m_heap;
3846   d_heap = ((HdrHeapSDKHandle *)dest_bufp)->m_heap;
3847   s_hh   = (HTTPHdrImpl *)src_hdr;
3848 
3849   if (s_hh->m_type != HDR_HEAP_OBJ_HTTP_HEADER) {
3850     return TS_ERROR;
3851   }
3852 
3853   // TODO: This is never used
3854   // inherit_strs = (s_heap != d_heap ? true : false);
3855   d_hh  = http_hdr_clone(s_hh, s_heap, d_heap);
3856   *locp = (TSMLoc)d_hh;
3857 
3858   return TS_SUCCESS;
3859 }
3860 
3861 TSReturnCode
TSHttpHdrCopy(TSMBuffer dest_bufp,TSMLoc dest_obj,TSMBuffer src_bufp,TSMLoc src_obj)3862 TSHttpHdrCopy(TSMBuffer dest_bufp, TSMLoc dest_obj, TSMBuffer src_bufp, TSMLoc src_obj)
3863 {
3864   // Allow to modify the buffer only
3865   // if bufp is modifiable. If bufp is not modifiable return
3866   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
3867   // return value of function from void to TSReturnCode.
3868   sdk_assert(sdk_sanity_check_mbuffer(src_bufp) == TS_SUCCESS);
3869   sdk_assert(sdk_sanity_check_mbuffer(dest_bufp) == TS_SUCCESS);
3870   sdk_assert(sdk_sanity_check_http_hdr_handle(dest_obj) == TS_SUCCESS);
3871   sdk_assert(sdk_sanity_check_http_hdr_handle(src_obj) == TS_SUCCESS);
3872 
3873   if (!isWriteable(dest_bufp)) {
3874     return TS_ERROR;
3875   }
3876 
3877   bool inherit_strs;
3878   HdrHeap *s_heap, *d_heap;
3879   HTTPHdrImpl *s_hh, *d_hh;
3880 
3881   s_heap = ((HdrHeapSDKHandle *)src_bufp)->m_heap;
3882   d_heap = ((HdrHeapSDKHandle *)dest_bufp)->m_heap;
3883   s_hh   = (HTTPHdrImpl *)src_obj;
3884   d_hh   = (HTTPHdrImpl *)dest_obj;
3885 
3886   if ((s_hh->m_type != HDR_HEAP_OBJ_HTTP_HEADER) || (d_hh->m_type != HDR_HEAP_OBJ_HTTP_HEADER)) {
3887     return TS_ERROR;
3888   }
3889 
3890   inherit_strs = (s_heap != d_heap ? true : false);
3891   TSHttpHdrTypeSet(dest_bufp, dest_obj, (TSHttpType)(s_hh->m_polarity));
3892   http_hdr_copy_onto(s_hh, s_heap, d_hh, d_heap, inherit_strs);
3893   return TS_SUCCESS;
3894 }
3895 
3896 void
TSHttpHdrPrint(TSMBuffer bufp,TSMLoc obj,TSIOBuffer iobufp)3897 TSHttpHdrPrint(TSMBuffer bufp, TSMLoc obj, TSIOBuffer iobufp)
3898 {
3899   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3900   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
3901   sdk_assert(sdk_sanity_check_iocore_structure(iobufp) == TS_SUCCESS);
3902 
3903   MIOBuffer *b = (MIOBuffer *)iobufp;
3904   IOBufferBlock *blk;
3905   HTTPHdr h;
3906   int bufindex;
3907   int tmp, dumpoffset;
3908   int done;
3909 
3910   SET_HTTP_HDR(h, bufp, obj);
3911   ink_assert(h.m_http->m_type == HDR_HEAP_OBJ_HTTP_HEADER);
3912 
3913   dumpoffset = 0;
3914   do {
3915     blk = b->get_current_block();
3916     if (!blk || blk->write_avail() == 0) {
3917       b->add_block();
3918       blk = b->get_current_block();
3919     }
3920 
3921     bufindex = 0;
3922     tmp      = dumpoffset;
3923 
3924     done = h.print(blk->end(), blk->write_avail(), &bufindex, &tmp);
3925 
3926     dumpoffset += bufindex;
3927     b->fill(bufindex);
3928   } while (!done);
3929 }
3930 
3931 TSParseResult
TSHttpHdrParseReq(TSHttpParser parser,TSMBuffer bufp,TSMLoc obj,const char ** start,const char * end)3932 TSHttpHdrParseReq(TSHttpParser parser, TSMBuffer bufp, TSMLoc obj, const char **start, const char *end)
3933 {
3934   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3935   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
3936   sdk_assert(sdk_sanity_check_null_ptr((void *)start) == TS_SUCCESS);
3937   sdk_assert(sdk_sanity_check_null_ptr((void *)*start) == TS_SUCCESS);
3938   sdk_assert(sdk_sanity_check_null_ptr((void *)end) == TS_SUCCESS);
3939 
3940   if (!isWriteable(bufp)) {
3941     return TS_PARSE_ERROR;
3942   }
3943 
3944   HTTPHdr h;
3945 
3946   SET_HTTP_HDR(h, bufp, obj);
3947   ink_assert(h.m_http->m_type == HDR_HEAP_OBJ_HTTP_HEADER);
3948   TSHttpHdrTypeSet(bufp, obj, TS_HTTP_TYPE_REQUEST);
3949   return (TSParseResult)h.parse_req((HTTPParser *)parser, start, end, false);
3950 }
3951 
3952 TSParseResult
TSHttpHdrParseResp(TSHttpParser parser,TSMBuffer bufp,TSMLoc obj,const char ** start,const char * end)3953 TSHttpHdrParseResp(TSHttpParser parser, TSMBuffer bufp, TSMLoc obj, const char **start, const char *end)
3954 {
3955   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3956   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
3957   sdk_assert(sdk_sanity_check_null_ptr((void *)start) == TS_SUCCESS);
3958   sdk_assert(sdk_sanity_check_null_ptr((void *)*start) == TS_SUCCESS);
3959   sdk_assert(sdk_sanity_check_null_ptr((void *)end) == TS_SUCCESS);
3960 
3961   if (!isWriteable(bufp)) {
3962     return TS_PARSE_ERROR;
3963   }
3964 
3965   HTTPHdr h;
3966 
3967   SET_HTTP_HDR(h, bufp, obj);
3968   ink_assert(h.m_http->m_type == HDR_HEAP_OBJ_HTTP_HEADER);
3969   TSHttpHdrTypeSet(bufp, obj, TS_HTTP_TYPE_RESPONSE);
3970   return (TSParseResult)h.parse_resp((HTTPParser *)parser, start, end, false);
3971 }
3972 
3973 int
TSHttpHdrLengthGet(TSMBuffer bufp,TSMLoc obj)3974 TSHttpHdrLengthGet(TSMBuffer bufp, TSMLoc obj)
3975 {
3976   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3977   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
3978 
3979   HTTPHdr h;
3980 
3981   SET_HTTP_HDR(h, bufp, obj);
3982   ink_assert(h.m_http->m_type == HDR_HEAP_OBJ_HTTP_HEADER);
3983   return h.length_get();
3984 }
3985 
3986 TSHttpType
TSHttpHdrTypeGet(TSMBuffer bufp,TSMLoc obj)3987 TSHttpHdrTypeGet(TSMBuffer bufp, TSMLoc obj)
3988 {
3989   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
3990   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
3991 
3992   HTTPHdr h;
3993   SET_HTTP_HDR(h, bufp, obj);
3994   /* Don't need the assert as the check is done in sdk_sanity_check_http_hdr_handle
3995      ink_assert(h.m_http->m_type == HDR_HEAP_OBJ_HTTP_HEADER);
3996    */
3997   return (TSHttpType)h.type_get();
3998 }
3999 
4000 TSReturnCode
TSHttpHdrTypeSet(TSMBuffer bufp,TSMLoc obj,TSHttpType type)4001 TSHttpHdrTypeSet(TSMBuffer bufp, TSMLoc obj, TSHttpType type)
4002 {
4003   // Allow to modify the buffer only
4004   // if bufp is modifiable. If bufp is not modifiable return
4005   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
4006   // return value of function from void to TSReturnCode.
4007   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
4008   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
4009   sdk_assert((type >= TS_HTTP_TYPE_UNKNOWN) && (type <= TS_HTTP_TYPE_RESPONSE));
4010 
4011   if (!isWriteable(bufp)) {
4012     return TS_ERROR;
4013   }
4014 
4015   HTTPHdr h;
4016 
4017   SET_HTTP_HDR(h, bufp, obj);
4018   ink_assert(h.m_http->m_type == HDR_HEAP_OBJ_HTTP_HEADER);
4019 
4020   // FIX: why are we using an HTTPHdr here?  why can't we
4021   //      just manipulate the impls directly?
4022 
4023   // In Pete's MBuffer system you can change the type
4024   //   at will.  Not so anymore.  We need to try to
4025   //   fake the difference.  We not going to let
4026   //   people change the types of a header.  If they
4027   //   try, too bad.
4028   if (h.m_http->m_polarity == HTTP_TYPE_UNKNOWN) {
4029     if (type == (TSHttpType)HTTP_TYPE_REQUEST) {
4030       h.m_http->u.req.m_url_impl = url_create(h.m_heap);
4031       h.m_http->m_polarity       = (HTTPType)type;
4032     } else if (type == (TSHttpType)HTTP_TYPE_RESPONSE) {
4033       h.m_http->m_polarity = (HTTPType)type;
4034     }
4035   }
4036   return TS_SUCCESS;
4037 }
4038 
4039 int
TSHttpHdrVersionGet(TSMBuffer bufp,TSMLoc obj)4040 TSHttpHdrVersionGet(TSMBuffer bufp, TSMLoc obj)
4041 {
4042   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
4043   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
4044 
4045   HTTPHdr h;
4046 
4047   SET_HTTP_HDR(h, bufp, obj);
4048   HTTPVersion ver = h.version_get();
4049   return ver.get_flat_version();
4050 }
4051 
4052 TSReturnCode
TSHttpHdrVersionSet(TSMBuffer bufp,TSMLoc obj,int ver)4053 TSHttpHdrVersionSet(TSMBuffer bufp, TSMLoc obj, int ver)
4054 {
4055   // Allow to modify the buffer only
4056   // if bufp is modifiable. If bufp is not modifiable return
4057   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
4058   // return value of function from void to TSReturnCode.
4059   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
4060   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
4061 
4062   if (!isWriteable(bufp)) {
4063     return TS_ERROR;
4064   }
4065 
4066   HTTPHdr h;
4067   HTTPVersion version{ver};
4068 
4069   SET_HTTP_HDR(h, bufp, obj);
4070   ink_assert(h.m_http->m_type == HDR_HEAP_OBJ_HTTP_HEADER);
4071 
4072   h.version_set(version);
4073   return TS_SUCCESS;
4074 }
4075 
4076 const char *
TSHttpHdrMethodGet(TSMBuffer bufp,TSMLoc obj,int * length)4077 TSHttpHdrMethodGet(TSMBuffer bufp, TSMLoc obj, int *length)
4078 {
4079   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
4080   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
4081   sdk_assert(sdk_sanity_check_null_ptr((void *)length) == TS_SUCCESS);
4082 
4083   HTTPHdr h;
4084 
4085   SET_HTTP_HDR(h, bufp, obj);
4086   return h.method_get(length);
4087 }
4088 
4089 TSReturnCode
TSHttpHdrMethodSet(TSMBuffer bufp,TSMLoc obj,const char * value,int length)4090 TSHttpHdrMethodSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
4091 {
4092   // Allow to modify the buffer only
4093   // if bufp is modifiable. If bufp is not modifiable return
4094   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
4095   // return value of function from void to TSReturnCode.
4096   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
4097   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
4098   sdk_assert(sdk_sanity_check_null_ptr((void *)value) == TS_SUCCESS);
4099 
4100   if (!isWriteable(bufp)) {
4101     return TS_ERROR;
4102   }
4103 
4104   HTTPHdr h;
4105 
4106   SET_HTTP_HDR(h, bufp, obj);
4107   if (length < 0) {
4108     length = strlen(value);
4109   }
4110 
4111   h.method_set(value, length);
4112   return TS_SUCCESS;
4113 }
4114 
4115 const char *
TSHttpHdrHostGet(TSMBuffer bufp,TSMLoc obj,int * length)4116 TSHttpHdrHostGet(TSMBuffer bufp, TSMLoc obj, int *length)
4117 {
4118   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
4119   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
4120   sdk_assert(sdk_sanity_check_null_ptr((void *)length) == TS_SUCCESS);
4121 
4122   HTTPHdr h;
4123 
4124   SET_HTTP_HDR(h, bufp, obj);
4125   return h.host_get(length);
4126 }
4127 
4128 TSReturnCode
TSHttpHdrUrlGet(TSMBuffer bufp,TSMLoc obj,TSMLoc * locp)4129 TSHttpHdrUrlGet(TSMBuffer bufp, TSMLoc obj, TSMLoc *locp)
4130 {
4131   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
4132   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
4133 
4134   HTTPHdrImpl *hh = (HTTPHdrImpl *)obj;
4135 
4136   if (hh->m_polarity != HTTP_TYPE_REQUEST) {
4137     return TS_ERROR;
4138   }
4139 
4140   *locp = ((TSMLoc)hh->u.req.m_url_impl);
4141   return TS_SUCCESS;
4142 }
4143 
4144 TSReturnCode
TSHttpHdrUrlSet(TSMBuffer bufp,TSMLoc obj,TSMLoc url)4145 TSHttpHdrUrlSet(TSMBuffer bufp, TSMLoc obj, TSMLoc url)
4146 {
4147   // Allow to modify the buffer only
4148   // if bufp is modifiable. If bufp is not modifiable return
4149   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
4150   // return value of function from void to TSReturnCode.
4151   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
4152   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
4153   sdk_assert(sdk_sanity_check_url_handle(url) == TS_SUCCESS);
4154 
4155   if (!isWriteable(bufp)) {
4156     return TS_ERROR;
4157   }
4158 
4159   HdrHeap *heap   = ((HdrHeapSDKHandle *)bufp)->m_heap;
4160   HTTPHdrImpl *hh = (HTTPHdrImpl *)obj;
4161 
4162   if (hh->m_type != HDR_HEAP_OBJ_HTTP_HEADER) {
4163     return TS_ERROR;
4164   }
4165 
4166   URLImpl *url_impl = (URLImpl *)url;
4167   http_hdr_url_set(heap, hh, url_impl);
4168   return TS_SUCCESS;
4169 }
4170 
4171 TSHttpStatus
TSHttpHdrStatusGet(TSMBuffer bufp,TSMLoc obj)4172 TSHttpHdrStatusGet(TSMBuffer bufp, TSMLoc obj)
4173 {
4174   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
4175   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
4176 
4177   HTTPHdr h;
4178 
4179   SET_HTTP_HDR(h, bufp, obj);
4180   return (TSHttpStatus)h.status_get();
4181 }
4182 
4183 TSReturnCode
TSHttpHdrStatusSet(TSMBuffer bufp,TSMLoc obj,TSHttpStatus status)4184 TSHttpHdrStatusSet(TSMBuffer bufp, TSMLoc obj, TSHttpStatus status)
4185 {
4186   // Allow to modify the buffer only
4187   // if bufp is modifiable. If bufp is not modifiable return
4188   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
4189   // return value of function from void to TSReturnCode.
4190   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
4191   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
4192 
4193   if (!isWriteable(bufp)) {
4194     return TS_ERROR;
4195   }
4196 
4197   HTTPHdr h;
4198 
4199   SET_HTTP_HDR(h, bufp, obj);
4200   ink_assert(h.m_http->m_type == HDR_HEAP_OBJ_HTTP_HEADER);
4201   h.status_set((HTTPStatus)status);
4202   return TS_SUCCESS;
4203 }
4204 
4205 const char *
TSHttpHdrReasonGet(TSMBuffer bufp,TSMLoc obj,int * length)4206 TSHttpHdrReasonGet(TSMBuffer bufp, TSMLoc obj, int *length)
4207 {
4208   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
4209   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
4210   sdk_assert(sdk_sanity_check_null_ptr((void *)length) == TS_SUCCESS);
4211 
4212   HTTPHdr h;
4213 
4214   SET_HTTP_HDR(h, bufp, obj);
4215   return h.reason_get(length);
4216 }
4217 
4218 TSReturnCode
TSHttpHdrReasonSet(TSMBuffer bufp,TSMLoc obj,const char * value,int length)4219 TSHttpHdrReasonSet(TSMBuffer bufp, TSMLoc obj, const char *value, int length)
4220 {
4221   // Allow to modify the buffer only
4222   // if bufp is modifiable. If bufp is not modifiable return
4223   // TS_ERROR. If allowed, return TS_SUCCESS. Changed the
4224   // return value of function from void to TSReturnCode.
4225   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
4226   sdk_assert(sdk_sanity_check_http_hdr_handle(obj) == TS_SUCCESS);
4227   sdk_assert(sdk_sanity_check_null_ptr((void *)value) == TS_SUCCESS);
4228 
4229   if (!isWriteable(bufp)) {
4230     return TS_ERROR;
4231   }
4232 
4233   HTTPHdr h;
4234 
4235   SET_HTTP_HDR(h, bufp, obj);
4236   /* Don't need the assert as the check is done in sdk_sanity_check_http_hdr_handle
4237      ink_assert(h.m_http->m_type == HDR_HEAP_OBJ_HTTP_HEADER);
4238   */
4239 
4240   if (length < 0) {
4241     length = strlen(value);
4242   }
4243   h.reason_set(value, length);
4244   return TS_SUCCESS;
4245 }
4246 
4247 const char *
TSHttpHdrReasonLookup(TSHttpStatus status)4248 TSHttpHdrReasonLookup(TSHttpStatus status)
4249 {
4250   return http_hdr_reason_lookup((HTTPStatus)status);
4251 }
4252 
4253 ////////////////////////////////////////////////////////////////////
4254 //
4255 // Cache
4256 //
4257 ////////////////////////////////////////////////////////////////////
4258 
4259 inline TSReturnCode
sdk_sanity_check_cachekey(TSCacheKey key)4260 sdk_sanity_check_cachekey(TSCacheKey key)
4261 {
4262   if (nullptr == key) {
4263     return TS_ERROR;
4264   }
4265 
4266   return TS_SUCCESS;
4267 }
4268 
4269 TSCacheKey
TSCacheKeyCreate()4270 TSCacheKeyCreate()
4271 {
4272   TSCacheKey key = (TSCacheKey) new CacheInfo();
4273 
4274   // TODO: Probably remove this when we can be use "NEW" can't fail.
4275   sdk_assert(sdk_sanity_check_cachekey(key) == TS_SUCCESS);
4276   return key;
4277 }
4278 
4279 TSReturnCode
TSCacheKeyDigestSet(TSCacheKey key,const char * input,int length)4280 TSCacheKeyDigestSet(TSCacheKey key, const char *input, int length)
4281 {
4282   sdk_assert(sdk_sanity_check_cachekey(key) == TS_SUCCESS);
4283   sdk_assert(sdk_sanity_check_iocore_structure((void *)input) == TS_SUCCESS);
4284   sdk_assert(length > 0);
4285   CacheInfo *ci = reinterpret_cast<CacheInfo *>(key);
4286 
4287   if (ci->magic != CACHE_INFO_MAGIC_ALIVE) {
4288     return TS_ERROR;
4289   }
4290 
4291   CryptoContext().hash_immediate(ci->cache_key, input, length);
4292   return TS_SUCCESS;
4293 }
4294 
4295 TSReturnCode
TSCacheKeyDigestFromUrlSet(TSCacheKey key,TSMLoc url)4296 TSCacheKeyDigestFromUrlSet(TSCacheKey key, TSMLoc url)
4297 {
4298   sdk_assert(sdk_sanity_check_cachekey(key) == TS_SUCCESS);
4299 
4300   if (((CacheInfo *)key)->magic != CACHE_INFO_MAGIC_ALIVE) {
4301     return TS_ERROR;
4302   }
4303 
4304   url_CryptoHash_get((URLImpl *)url, &((CacheInfo *)key)->cache_key);
4305   return TS_SUCCESS;
4306 }
4307 
4308 TSReturnCode
TSCacheKeyDataTypeSet(TSCacheKey key,TSCacheDataType type)4309 TSCacheKeyDataTypeSet(TSCacheKey key, TSCacheDataType type)
4310 {
4311   sdk_assert(sdk_sanity_check_cachekey(key) == TS_SUCCESS);
4312 
4313   if (((CacheInfo *)key)->magic != CACHE_INFO_MAGIC_ALIVE) {
4314     return TS_ERROR;
4315   }
4316 
4317   switch (type) {
4318   case TS_CACHE_DATA_TYPE_NONE:
4319     ((CacheInfo *)key)->frag_type = CACHE_FRAG_TYPE_NONE;
4320     break;
4321   case TS_CACHE_DATA_TYPE_OTHER: /* other maps to http */
4322   case TS_CACHE_DATA_TYPE_HTTP:
4323     ((CacheInfo *)key)->frag_type = CACHE_FRAG_TYPE_HTTP;
4324     break;
4325   default:
4326     return TS_ERROR;
4327   }
4328 
4329   return TS_SUCCESS;
4330 }
4331 
4332 TSReturnCode
TSCacheKeyHostNameSet(TSCacheKey key,const char * hostname,int host_len)4333 TSCacheKeyHostNameSet(TSCacheKey key, const char *hostname, int host_len)
4334 {
4335   sdk_assert(sdk_sanity_check_cachekey(key) == TS_SUCCESS);
4336   sdk_assert(sdk_sanity_check_null_ptr((void *)hostname) == TS_SUCCESS);
4337   sdk_assert(host_len > 0);
4338 
4339   if (((CacheInfo *)key)->magic != CACHE_INFO_MAGIC_ALIVE) {
4340     return TS_ERROR;
4341   }
4342 
4343   CacheInfo *i = (CacheInfo *)key;
4344   /* need to make a copy of the hostname. The caller
4345      might deallocate it anytime in the future */
4346   i->hostname = (char *)ats_malloc(host_len);
4347   memcpy(i->hostname, hostname, host_len);
4348   i->len = host_len;
4349   return TS_SUCCESS;
4350 }
4351 
4352 TSReturnCode
TSCacheKeyPinnedSet(TSCacheKey key,time_t pin_in_cache)4353 TSCacheKeyPinnedSet(TSCacheKey key, time_t pin_in_cache)
4354 {
4355   sdk_assert(sdk_sanity_check_cachekey(key) == TS_SUCCESS);
4356 
4357   if (((CacheInfo *)key)->magic != CACHE_INFO_MAGIC_ALIVE) {
4358     return TS_ERROR;
4359   }
4360 
4361   CacheInfo *i    = (CacheInfo *)key;
4362   i->pin_in_cache = pin_in_cache;
4363   return TS_SUCCESS;
4364 }
4365 
4366 TSReturnCode
TSCacheKeyDestroy(TSCacheKey key)4367 TSCacheKeyDestroy(TSCacheKey key)
4368 {
4369   sdk_assert(sdk_sanity_check_cachekey(key) == TS_SUCCESS);
4370 
4371   if (((CacheInfo *)key)->magic != CACHE_INFO_MAGIC_ALIVE) {
4372     return TS_ERROR;
4373   }
4374 
4375   CacheInfo *i = (CacheInfo *)key;
4376 
4377   ats_free(i->hostname);
4378   i->magic = CACHE_INFO_MAGIC_DEAD;
4379   delete i;
4380   return TS_SUCCESS;
4381 }
4382 
4383 TSCacheHttpInfo
TSCacheHttpInfoCopy(TSCacheHttpInfo infop)4384 TSCacheHttpInfoCopy(TSCacheHttpInfo infop)
4385 {
4386   CacheHTTPInfo *new_info = new CacheHTTPInfo;
4387 
4388   new_info->copy((CacheHTTPInfo *)infop);
4389   return reinterpret_cast<TSCacheHttpInfo>(new_info);
4390 }
4391 
4392 void
TSCacheHttpInfoReqGet(TSCacheHttpInfo infop,TSMBuffer * bufp,TSMLoc * obj)4393 TSCacheHttpInfoReqGet(TSCacheHttpInfo infop, TSMBuffer *bufp, TSMLoc *obj)
4394 {
4395   CacheHTTPInfo *info = (CacheHTTPInfo *)infop;
4396 
4397   *(reinterpret_cast<HTTPHdr **>(bufp)) = info->request_get();
4398   *obj                                  = reinterpret_cast<TSMLoc>(info->request_get()->m_http);
4399   sdk_assert(sdk_sanity_check_mbuffer(*bufp) == TS_SUCCESS);
4400 }
4401 
4402 void
TSCacheHttpInfoRespGet(TSCacheHttpInfo infop,TSMBuffer * bufp,TSMLoc * obj)4403 TSCacheHttpInfoRespGet(TSCacheHttpInfo infop, TSMBuffer *bufp, TSMLoc *obj)
4404 {
4405   CacheHTTPInfo *info = (CacheHTTPInfo *)infop;
4406 
4407   *(reinterpret_cast<HTTPHdr **>(bufp)) = info->response_get();
4408   *obj                                  = reinterpret_cast<TSMLoc>(info->response_get()->m_http);
4409   sdk_assert(sdk_sanity_check_mbuffer(*bufp) == TS_SUCCESS);
4410 }
4411 
4412 time_t
TSCacheHttpInfoReqSentTimeGet(TSCacheHttpInfo infop)4413 TSCacheHttpInfoReqSentTimeGet(TSCacheHttpInfo infop)
4414 {
4415   CacheHTTPInfo *info = (CacheHTTPInfo *)infop;
4416   return info->request_sent_time_get();
4417 }
4418 
4419 time_t
TSCacheHttpInfoRespReceivedTimeGet(TSCacheHttpInfo infop)4420 TSCacheHttpInfoRespReceivedTimeGet(TSCacheHttpInfo infop)
4421 {
4422   CacheHTTPInfo *info = (CacheHTTPInfo *)infop;
4423   return info->response_received_time_get();
4424 }
4425 
4426 int64_t
TSCacheHttpInfoSizeGet(TSCacheHttpInfo infop)4427 TSCacheHttpInfoSizeGet(TSCacheHttpInfo infop)
4428 {
4429   CacheHTTPInfo *info = (CacheHTTPInfo *)infop;
4430   return info->object_size_get();
4431 }
4432 
4433 void
TSCacheHttpInfoReqSet(TSCacheHttpInfo infop,TSMBuffer bufp,TSMLoc obj)4434 TSCacheHttpInfoReqSet(TSCacheHttpInfo infop, TSMBuffer bufp, TSMLoc obj)
4435 {
4436   HTTPHdr h;
4437 
4438   SET_HTTP_HDR(h, bufp, obj);
4439 
4440   CacheHTTPInfo *info = (CacheHTTPInfo *)infop;
4441   info->request_set(&h);
4442 }
4443 
4444 void
TSCacheHttpInfoRespSet(TSCacheHttpInfo infop,TSMBuffer bufp,TSMLoc obj)4445 TSCacheHttpInfoRespSet(TSCacheHttpInfo infop, TSMBuffer bufp, TSMLoc obj)
4446 {
4447   HTTPHdr h;
4448 
4449   SET_HTTP_HDR(h, bufp, obj);
4450 
4451   CacheHTTPInfo *info = (CacheHTTPInfo *)infop;
4452   info->response_set(&h);
4453 }
4454 
4455 int
TSCacheHttpInfoVector(TSCacheHttpInfo infop,void * data,int length)4456 TSCacheHttpInfoVector(TSCacheHttpInfo infop, void *data, int length)
4457 {
4458   CacheHTTPInfo *info = (CacheHTTPInfo *)infop;
4459   CacheHTTPInfoVector vector;
4460 
4461   vector.insert(info);
4462 
4463   int size = vector.marshal_length();
4464 
4465   if (size > length) {
4466     // error
4467     return 0;
4468   }
4469 
4470   return vector.marshal((char *)data, length);
4471 }
4472 
4473 void
TSCacheHttpInfoDestroy(TSCacheHttpInfo infop)4474 TSCacheHttpInfoDestroy(TSCacheHttpInfo infop)
4475 {
4476   ((CacheHTTPInfo *)infop)->destroy();
4477 }
4478 
4479 TSCacheHttpInfo
TSCacheHttpInfoCreate()4480 TSCacheHttpInfoCreate()
4481 {
4482   CacheHTTPInfo *info = new CacheHTTPInfo;
4483   info->create();
4484 
4485   return reinterpret_cast<TSCacheHttpInfo>(info);
4486 }
4487 
4488 ////////////////////////////////////////////////////////////////////
4489 //
4490 // Configuration
4491 //
4492 ////////////////////////////////////////////////////////////////////
4493 
4494 unsigned int
TSConfigSet(unsigned int id,void * data,TSConfigDestroyFunc funcp)4495 TSConfigSet(unsigned int id, void *data, TSConfigDestroyFunc funcp)
4496 {
4497   INKConfigImpl *config  = new INKConfigImpl;
4498   config->mdata          = data;
4499   config->m_destroy_func = funcp;
4500   return configProcessor.set(id, config);
4501 }
4502 
4503 TSConfig
TSConfigGet(unsigned int id)4504 TSConfigGet(unsigned int id)
4505 {
4506   return reinterpret_cast<TSConfig>(configProcessor.get(id));
4507 }
4508 
4509 void
TSConfigRelease(unsigned int id,TSConfig configp)4510 TSConfigRelease(unsigned int id, TSConfig configp)
4511 {
4512   configProcessor.release(id, (ConfigInfo *)configp);
4513 }
4514 
4515 void *
TSConfigDataGet(TSConfig configp)4516 TSConfigDataGet(TSConfig configp)
4517 {
4518   INKConfigImpl *config = (INKConfigImpl *)configp;
4519   return config->mdata;
4520 }
4521 
4522 ////////////////////////////////////////////////////////////////////
4523 //
4524 // Management
4525 //
4526 ////////////////////////////////////////////////////////////////////
4527 
4528 void
TSMgmtUpdateRegister(TSCont contp,const char * plugin_name)4529 TSMgmtUpdateRegister(TSCont contp, const char *plugin_name)
4530 {
4531   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
4532   sdk_assert(sdk_sanity_check_null_ptr((void *)plugin_name) == TS_SUCCESS);
4533 
4534   global_config_cbs->insert((INKContInternal *)contp, plugin_name);
4535 }
4536 
4537 TSReturnCode
TSMgmtIntGet(const char * var_name,TSMgmtInt * result)4538 TSMgmtIntGet(const char *var_name, TSMgmtInt *result)
4539 {
4540   return RecGetRecordInt((char *)var_name, (RecInt *)result) == REC_ERR_OKAY ? TS_SUCCESS : TS_ERROR;
4541 }
4542 
4543 TSReturnCode
TSMgmtCounterGet(const char * var_name,TSMgmtCounter * result)4544 TSMgmtCounterGet(const char *var_name, TSMgmtCounter *result)
4545 {
4546   return RecGetRecordCounter((char *)var_name, (RecCounter *)result) == REC_ERR_OKAY ? TS_SUCCESS : TS_ERROR;
4547 }
4548 
4549 TSReturnCode
TSMgmtFloatGet(const char * var_name,TSMgmtFloat * result)4550 TSMgmtFloatGet(const char *var_name, TSMgmtFloat *result)
4551 {
4552   return RecGetRecordFloat((char *)var_name, (RecFloat *)result) == REC_ERR_OKAY ? TS_SUCCESS : TS_ERROR;
4553 }
4554 
4555 TSReturnCode
TSMgmtStringGet(const char * var_name,TSMgmtString * result)4556 TSMgmtStringGet(const char *var_name, TSMgmtString *result)
4557 {
4558   RecString tmp = nullptr;
4559   (void)RecGetRecordString_Xmalloc((char *)var_name, &tmp);
4560 
4561   if (tmp) {
4562     *result = tmp;
4563     return TS_SUCCESS;
4564   }
4565 
4566   return TS_ERROR;
4567 }
4568 
4569 TSReturnCode
TSMgmtSourceGet(const char * var_name,TSMgmtSource * source)4570 TSMgmtSourceGet(const char *var_name, TSMgmtSource *source)
4571 {
4572   return REC_ERR_OKAY == RecGetRecordSource(var_name, reinterpret_cast<RecSourceT *>(source)) ? TS_SUCCESS : TS_ERROR;
4573 }
4574 
4575 TSReturnCode
TSMgmtDataTypeGet(const char * var_name,TSRecordDataType * result)4576 TSMgmtDataTypeGet(const char *var_name, TSRecordDataType *result)
4577 {
4578   return REC_ERR_OKAY == RecGetRecordDataType(var_name, reinterpret_cast<RecDataT *>(result)) ? TS_SUCCESS : TS_ERROR;
4579 }
4580 
4581 ////////////////////////////////////////////////////////////////////
4582 //
4583 // Continuations
4584 //
4585 ////////////////////////////////////////////////////////////////////
4586 
4587 extern thread_local PluginThreadContext *pluginThreadContext;
4588 
4589 TSCont
TSContCreate(TSEventFunc funcp,TSMutex mutexp)4590 TSContCreate(TSEventFunc funcp, TSMutex mutexp)
4591 {
4592   // mutexp can be NULL
4593   if (mutexp != nullptr) {
4594     sdk_assert(sdk_sanity_check_mutex(mutexp) == TS_SUCCESS);
4595   }
4596 
4597   if (pluginThreadContext) {
4598     pluginThreadContext->acquire();
4599   }
4600 
4601   INKContInternal *i = THREAD_ALLOC(INKContAllocator, this_thread());
4602 
4603   i->init(funcp, mutexp, pluginThreadContext);
4604   return (TSCont)i;
4605 }
4606 
4607 void
TSContDestroy(TSCont contp)4608 TSContDestroy(TSCont contp)
4609 {
4610   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
4611 
4612   INKContInternal *i = (INKContInternal *)contp;
4613 
4614   if (i->m_context) {
4615     reinterpret_cast<PluginThreadContext *>(i->m_context)->release();
4616   }
4617 
4618   i->destroy();
4619 }
4620 
4621 void
TSContDataSet(TSCont contp,void * data)4622 TSContDataSet(TSCont contp, void *data)
4623 {
4624   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
4625 
4626   INKContInternal *i = (INKContInternal *)contp;
4627 
4628   i->mdata = data;
4629 }
4630 
4631 void *
TSContDataGet(TSCont contp)4632 TSContDataGet(TSCont contp)
4633 {
4634   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
4635 
4636   INKContInternal *i = (INKContInternal *)contp;
4637 
4638   return i->mdata;
4639 }
4640 
4641 TSAction
TSContSchedule(TSCont contp,TSHRTime timeout)4642 TSContSchedule(TSCont contp, TSHRTime timeout)
4643 {
4644   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
4645 
4646   /* ensure we are on a EThread */
4647   sdk_assert(sdk_sanity_check_null_ptr((void *)this_ethread()) == TS_SUCCESS);
4648 
4649   FORCE_PLUGIN_SCOPED_MUTEX(contp);
4650 
4651   INKContInternal *i = reinterpret_cast<INKContInternal *>(contp);
4652 
4653   if (ink_atomic_increment(static_cast<int *>(&i->m_event_count), 1) < 0) {
4654     ink_assert(!"not reached");
4655   }
4656 
4657   EThread *eth = i->getThreadAffinity();
4658   if (eth == nullptr) {
4659     eth = this_ethread();
4660     i->setThreadAffinity(eth);
4661   }
4662 
4663   TSAction action;
4664   if (timeout == 0) {
4665     action = reinterpret_cast<TSAction>(eth->schedule_imm(i));
4666   } else {
4667     action = reinterpret_cast<TSAction>(eth->schedule_in(i, HRTIME_MSECONDS(timeout)));
4668   }
4669 
4670   /* This is a hack. Should be handled in ink_types */
4671   action = (TSAction)((uintptr_t)action | 0x1);
4672   return action;
4673 }
4674 
4675 TSAction
TSContScheduleOnPool(TSCont contp,TSHRTime timeout,TSThreadPool tp)4676 TSContScheduleOnPool(TSCont contp, TSHRTime timeout, TSThreadPool tp)
4677 {
4678   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
4679 
4680   /* ensure we are on a EThread */
4681   sdk_assert(sdk_sanity_check_null_ptr((void *)this_ethread()) == TS_SUCCESS);
4682 
4683   FORCE_PLUGIN_SCOPED_MUTEX(contp);
4684 
4685   INKContInternal *i = reinterpret_cast<INKContInternal *>(contp);
4686 
4687   if (ink_atomic_increment(static_cast<int *>(&i->m_event_count), 1) < 0) {
4688     ink_assert(!"not reached");
4689   }
4690 
4691   EventType etype;
4692 
4693   switch (tp) {
4694   case TS_THREAD_POOL_NET:
4695     etype = ET_NET;
4696     break;
4697   case TS_THREAD_POOL_TASK:
4698     etype = ET_TASK;
4699     break;
4700   case TS_THREAD_POOL_DNS:
4701     etype = ET_DNS;
4702     break;
4703   case TS_THREAD_POOL_UDP:
4704     etype = ET_UDP;
4705     break;
4706   default:
4707     etype = ET_TASK;
4708     break;
4709   }
4710 
4711   TSAction action;
4712   if (timeout == 0) {
4713     action = reinterpret_cast<TSAction>(eventProcessor.schedule_imm(i, etype));
4714   } else {
4715     action = reinterpret_cast<TSAction>(eventProcessor.schedule_in(i, HRTIME_MSECONDS(timeout), etype));
4716   }
4717 
4718   /* This is a hack. Should be handled in ink_types */
4719   action = (TSAction)((uintptr_t)action | 0x1);
4720   return action;
4721 }
4722 
4723 TSAction
TSContScheduleOnThread(TSCont contp,TSHRTime timeout,TSEventThread ethread)4724 TSContScheduleOnThread(TSCont contp, TSHRTime timeout, TSEventThread ethread)
4725 {
4726   ink_release_assert(ethread != nullptr);
4727 
4728   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
4729 
4730   FORCE_PLUGIN_SCOPED_MUTEX(contp);
4731 
4732   INKContInternal *i = reinterpret_cast<INKContInternal *>(contp);
4733 
4734   if (ink_atomic_increment(static_cast<int *>(&i->m_event_count), 1) < 0) {
4735     ink_assert(!"not reached");
4736   }
4737 
4738   EThread *eth = reinterpret_cast<EThread *>(ethread);
4739   if (i->getThreadAffinity() == nullptr) {
4740     i->setThreadAffinity(eth);
4741   }
4742 
4743   TSAction action;
4744   if (timeout == 0) {
4745     action = reinterpret_cast<TSAction>(eth->schedule_imm(i));
4746   } else {
4747     action = reinterpret_cast<TSAction>(eth->schedule_in(i, HRTIME_MSECONDS(timeout)));
4748   }
4749 
4750   /* This is a hack. Should be handled in ink_types */
4751   action = (TSAction)((uintptr_t)action | 0x1);
4752   return action;
4753 }
4754 
4755 TSAction
TSContScheduleEvery(TSCont contp,TSHRTime every)4756 TSContScheduleEvery(TSCont contp, TSHRTime every /* millisecs */)
4757 {
4758   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
4759 
4760   /* ensure we are on a EThread */
4761   sdk_assert(sdk_sanity_check_null_ptr((void *)this_ethread()) == TS_SUCCESS);
4762 
4763   FORCE_PLUGIN_SCOPED_MUTEX(contp);
4764 
4765   INKContInternal *i = reinterpret_cast<INKContInternal *>(contp);
4766 
4767   if (ink_atomic_increment(static_cast<int *>(&i->m_event_count), 1) < 0) {
4768     ink_assert(!"not reached");
4769   }
4770 
4771   EThread *eth = i->getThreadAffinity();
4772   if (eth == nullptr) {
4773     eth = this_ethread();
4774     i->setThreadAffinity(eth);
4775   }
4776 
4777   TSAction action = reinterpret_cast<TSAction>(eth->schedule_every(i, HRTIME_MSECONDS(every)));
4778 
4779   /* This is a hack. Should be handled in ink_types */
4780   action = (TSAction)((uintptr_t)action | 0x1);
4781   return action;
4782 }
4783 
4784 TSAction
TSContScheduleEveryOnPool(TSCont contp,TSHRTime every,TSThreadPool tp)4785 TSContScheduleEveryOnPool(TSCont contp, TSHRTime every, TSThreadPool tp)
4786 {
4787   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
4788 
4789   /* ensure we are on a EThread */
4790   sdk_assert(sdk_sanity_check_null_ptr((void *)this_ethread()) == TS_SUCCESS);
4791 
4792   FORCE_PLUGIN_SCOPED_MUTEX(contp);
4793 
4794   INKContInternal *i = reinterpret_cast<INKContInternal *>(contp);
4795 
4796   if (ink_atomic_increment(static_cast<int *>(&i->m_event_count), 1) < 0) {
4797     ink_assert(!"not reached");
4798   }
4799 
4800   EventType etype;
4801 
4802   switch (tp) {
4803   case TS_THREAD_POOL_NET:
4804     etype = ET_NET;
4805     break;
4806   case TS_THREAD_POOL_TASK:
4807     etype = ET_TASK;
4808     break;
4809   default:
4810     etype = ET_TASK;
4811     break;
4812   }
4813 
4814   TSAction action = reinterpret_cast<TSAction>(eventProcessor.schedule_every(i, HRTIME_MSECONDS(every), etype));
4815 
4816   /* This is a hack. Should be handled in ink_types */
4817   action = (TSAction)((uintptr_t)action | 0x1);
4818   return action;
4819 }
4820 
4821 TSAction
TSContScheduleEveryOnThread(TSCont contp,TSHRTime every,TSEventThread ethread)4822 TSContScheduleEveryOnThread(TSCont contp, TSHRTime every /* millisecs */, TSEventThread ethread)
4823 {
4824   ink_release_assert(ethread != nullptr);
4825 
4826   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
4827 
4828   FORCE_PLUGIN_SCOPED_MUTEX(contp);
4829 
4830   INKContInternal *i = reinterpret_cast<INKContInternal *>(contp);
4831 
4832   if (ink_atomic_increment(static_cast<int *>(&i->m_event_count), 1) < 0) {
4833     ink_assert(!"not reached");
4834   }
4835 
4836   EThread *eth = reinterpret_cast<EThread *>(ethread);
4837   if (i->getThreadAffinity() == nullptr) {
4838     i->setThreadAffinity(eth);
4839   }
4840 
4841   TSAction action = reinterpret_cast<TSAction>(eth->schedule_every(i, HRTIME_MSECONDS(every)));
4842 
4843   /* This is a hack. Should be handled in ink_types */
4844   action = (TSAction)((uintptr_t)action | 0x1);
4845   return action;
4846 }
4847 
4848 TSReturnCode
TSContThreadAffinitySet(TSCont contp,TSEventThread ethread)4849 TSContThreadAffinitySet(TSCont contp, TSEventThread ethread)
4850 {
4851   ink_release_assert(ethread != nullptr);
4852 
4853   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
4854 
4855   FORCE_PLUGIN_SCOPED_MUTEX(contp);
4856 
4857   INKContInternal *i       = reinterpret_cast<INKContInternal *>(contp);
4858   EThread *thread_affinity = reinterpret_cast<EThread *>(ethread);
4859 
4860   if (i->setThreadAffinity(thread_affinity)) {
4861     return TS_SUCCESS;
4862   }
4863   return TS_ERROR;
4864 }
4865 
4866 TSEventThread
TSContThreadAffinityGet(TSCont contp)4867 TSContThreadAffinityGet(TSCont contp)
4868 {
4869   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
4870 
4871   FORCE_PLUGIN_SCOPED_MUTEX(contp);
4872 
4873   INKContInternal *i = reinterpret_cast<INKContInternal *>(contp);
4874 
4875   return reinterpret_cast<TSEventThread>(i->getThreadAffinity());
4876 }
4877 
4878 void
TSContThreadAffinityClear(TSCont contp)4879 TSContThreadAffinityClear(TSCont contp)
4880 {
4881   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
4882 
4883   FORCE_PLUGIN_SCOPED_MUTEX(contp);
4884 
4885   INKContInternal *i = reinterpret_cast<INKContInternal *>(contp);
4886 
4887   i->clearThreadAffinity();
4888 }
4889 
4890 TSAction
TSHttpSchedule(TSCont contp,TSHttpTxn txnp,TSHRTime timeout)4891 TSHttpSchedule(TSCont contp, TSHttpTxn txnp, TSHRTime timeout)
4892 {
4893   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
4894 
4895   FORCE_PLUGIN_SCOPED_MUTEX(contp);
4896 
4897   INKContInternal *i = (INKContInternal *)contp;
4898 
4899   if (ink_atomic_increment((int *)&i->m_event_count, 1) < 0) {
4900     ink_assert(!"not reached");
4901   }
4902 
4903   TSAction action;
4904   Continuation *cont = (Continuation *)contp;
4905   HttpSM *sm         = (HttpSM *)txnp;
4906 
4907   sm->set_http_schedule(cont);
4908 
4909   if (timeout == 0) {
4910     action = reinterpret_cast<TSAction>(eventProcessor.schedule_imm(sm, ET_NET));
4911   } else {
4912     action = reinterpret_cast<TSAction>(eventProcessor.schedule_in(sm, HRTIME_MSECONDS(timeout), ET_NET));
4913   }
4914 
4915   action = (TSAction)((uintptr_t)action | 0x1);
4916   return action;
4917 }
4918 
4919 int
TSContCall(TSCont contp,TSEvent event,void * edata)4920 TSContCall(TSCont contp, TSEvent event, void *edata)
4921 {
4922   Continuation *c = (Continuation *)contp;
4923   WEAK_MUTEX_TRY_LOCK(lock, c->mutex, this_ethread());
4924   if (!lock.is_locked()) {
4925     // If we cannot get the lock, the caller needs to restructure to handle rescheduling
4926     ink_release_assert(0);
4927   }
4928   return c->handleEvent((int)event, edata);
4929 }
4930 
4931 TSMutex
TSContMutexGet(TSCont contp)4932 TSContMutexGet(TSCont contp)
4933 {
4934   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
4935 
4936   Continuation *c = (Continuation *)contp;
4937   return (TSMutex)(c->mutex.get());
4938 }
4939 
4940 /* HTTP hooks */
4941 
4942 void
TSHttpHookAdd(TSHttpHookID id,TSCont contp)4943 TSHttpHookAdd(TSHttpHookID id, TSCont contp)
4944 {
4945   INKContInternal *icontp;
4946   sdk_assert(sdk_sanity_check_continuation(contp) == TS_SUCCESS);
4947   sdk_assert(sdk_sanity_check_hook_id(id) == TS_SUCCESS);
4948 
4949   icontp = reinterpret_cast<INKContInternal *>(contp);
4950 
4951   TSSslHookInternalID internalId{id};
4952   if (internalId.is_in_bounds()) {
4953     ssl_hooks->append(internalId, icontp);
4954   } else { // Follow through the regular HTTP hook framework
4955     http_global_hooks->append(id, icontp);
4956   }
4957 }
4958 
4959 void
TSLifecycleHookAdd(TSLifecycleHookID id,TSCont contp)4960 TSLifecycleHookAdd(TSLifecycleHookID id, TSCont contp)
4961 {
4962   sdk_assert(sdk_sanity_check_continuation(contp) == TS_SUCCESS);
4963   sdk_assert(sdk_sanity_check_lifecycle_hook_id(id) == TS_SUCCESS);
4964 
4965   lifecycle_hooks->append(id, (INKContInternal *)contp);
4966 }
4967 
4968 /* HTTP sessions */
4969 void
TSHttpSsnHookAdd(TSHttpSsn ssnp,TSHttpHookID id,TSCont contp)4970 TSHttpSsnHookAdd(TSHttpSsn ssnp, TSHttpHookID id, TSCont contp)
4971 {
4972   sdk_assert(sdk_sanity_check_http_ssn(ssnp) == TS_SUCCESS);
4973   sdk_assert(sdk_sanity_check_continuation(contp) == TS_SUCCESS);
4974   sdk_assert(sdk_sanity_check_hook_id(id) == TS_SUCCESS);
4975 
4976   ProxySession *cs = reinterpret_cast<ProxySession *>(ssnp);
4977   cs->hook_add(id, (INKContInternal *)contp);
4978 }
4979 
4980 int
TSHttpSsnTransactionCount(TSHttpSsn ssnp)4981 TSHttpSsnTransactionCount(TSHttpSsn ssnp)
4982 {
4983   sdk_assert(sdk_sanity_check_http_ssn(ssnp) == TS_SUCCESS);
4984 
4985   ProxySession *cs = reinterpret_cast<ProxySession *>(ssnp);
4986   return cs->get_transact_count();
4987 }
4988 
4989 TSVConn
TSHttpSsnClientVConnGet(TSHttpSsn ssnp)4990 TSHttpSsnClientVConnGet(TSHttpSsn ssnp)
4991 {
4992   ProxySession *cs = reinterpret_cast<ProxySession *>(ssnp);
4993   return reinterpret_cast<TSVConn>(cs->get_netvc());
4994 }
4995 
4996 TSVConn
TSHttpSsnServerVConnGet(TSHttpSsn ssnp)4997 TSHttpSsnServerVConnGet(TSHttpSsn ssnp)
4998 {
4999   TSVConn vconn       = nullptr;
5000   PoolableSession *ss = reinterpret_cast<PoolableSession *>(ssnp);
5001   if (ss != nullptr) {
5002     vconn = reinterpret_cast<TSVConn>(ss->get_netvc());
5003   }
5004   return vconn;
5005 }
5006 
5007 TSVConn
TSHttpTxnServerVConnGet(TSHttpTxn txnp)5008 TSHttpTxnServerVConnGet(TSHttpTxn txnp)
5009 {
5010   TSVConn vconn = nullptr;
5011   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5012   HttpSM *sm = reinterpret_cast<HttpSM *>(txnp);
5013   if (sm != nullptr) {
5014     PoolableSession *ss = sm->get_server_session();
5015     if (ss != nullptr) {
5016       vconn = reinterpret_cast<TSVConn>(ss->get_netvc());
5017     }
5018   }
5019   return vconn;
5020 }
5021 
5022 class TSHttpSsnCallback : public Continuation
5023 {
5024 public:
TSHttpSsnCallback(ProxySession * cs,Ptr<ProxyMutex> m,TSEvent event)5025   TSHttpSsnCallback(ProxySession *cs, Ptr<ProxyMutex> m, TSEvent event) : Continuation(m), m_cs(cs), m_event(event)
5026   {
5027     SET_HANDLER(&TSHttpSsnCallback::event_handler);
5028   }
5029 
5030   int
event_handler(int,void *)5031   event_handler(int, void *)
5032   {
5033     // The current continuation is associated with the nethandler mutex.
5034     // We need to hold the nethandler mutex because the later Session logic may
5035     // activate the nethandler add_to_queue logic
5036     // Need to make sure we have the ProxySession mutex as well.
5037     EThread *eth = this_ethread();
5038     MUTEX_TRY_LOCK(trylock, m_cs->mutex, eth);
5039     if (!trylock.is_locked()) {
5040       eth->schedule_imm(this);
5041     } else {
5042       m_cs->handleEvent((int)m_event, nullptr);
5043       delete this;
5044     }
5045     return 0;
5046   }
5047 
5048 private:
5049   ProxySession *m_cs;
5050   TSEvent m_event;
5051 };
5052 
5053 void
TSHttpSsnReenable(TSHttpSsn ssnp,TSEvent event)5054 TSHttpSsnReenable(TSHttpSsn ssnp, TSEvent event)
5055 {
5056   sdk_assert(sdk_sanity_check_http_ssn(ssnp) == TS_SUCCESS);
5057 
5058   ProxySession *cs = reinterpret_cast<ProxySession *>(ssnp);
5059   EThread *eth     = this_ethread();
5060 
5061   // If this function is being executed on a thread created by the API
5062   // which is DEDICATED, the continuation needs to be called back on a
5063   // REGULAR thread. Specially an ET_NET thread
5064   if (!eth->is_event_type(ET_NET)) {
5065     EThread *affinity_thread = cs->getThreadAffinity();
5066     if (affinity_thread && affinity_thread->is_event_type(ET_NET)) {
5067       NetHandler *nh = get_NetHandler(affinity_thread);
5068       affinity_thread->schedule_imm(new TSHttpSsnCallback(cs, nh->mutex, event), ET_NET);
5069     } else {
5070       eventProcessor.schedule_imm(new TSHttpSsnCallback(cs, cs->mutex, event), ET_NET);
5071     }
5072   } else {
5073     MUTEX_TRY_LOCK(trylock, cs->mutex, eth);
5074     if (!trylock.is_locked()) {
5075       EThread *affinity_thread = cs->getThreadAffinity();
5076       if (affinity_thread && affinity_thread->is_event_type(ET_NET)) {
5077         NetHandler *nh = get_NetHandler(affinity_thread);
5078         affinity_thread->schedule_imm(new TSHttpSsnCallback(cs, nh->mutex, event), ET_NET);
5079       } else {
5080         eventProcessor.schedule_imm(new TSHttpSsnCallback(cs, cs->mutex, event), ET_NET);
5081       }
5082     } else {
5083       cs->handleEvent((int)event, nullptr);
5084     }
5085   }
5086 }
5087 
5088 /* HTTP transactions */
5089 void
TSHttpTxnHookAdd(TSHttpTxn txnp,TSHttpHookID id,TSCont contp)5090 TSHttpTxnHookAdd(TSHttpTxn txnp, TSHttpHookID id, TSCont contp)
5091 {
5092   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5093   sdk_assert(sdk_sanity_check_continuation(contp) == TS_SUCCESS);
5094   sdk_assert(sdk_sanity_check_hook_id(id) == TS_SUCCESS);
5095 
5096   HttpSM *sm    = (HttpSM *)txnp;
5097   APIHook *hook = sm->txn_hook_get(id);
5098 
5099   // Traverse list of hooks and add a particular hook only once
5100   while (hook != nullptr) {
5101     if (hook->m_cont == (INKContInternal *)contp) {
5102       return;
5103     }
5104     hook = hook->m_link.next;
5105   }
5106   sm->txn_hook_add(id, (INKContInternal *)contp);
5107 }
5108 
5109 // Private api function for gzip plugin.
5110 //  This function should only appear in TsapiPrivate.h
5111 TSReturnCode
TSHttpTxnHookRegisteredFor(TSHttpTxn txnp,TSHttpHookID id,TSEventFunc funcp)5112 TSHttpTxnHookRegisteredFor(TSHttpTxn txnp, TSHttpHookID id, TSEventFunc funcp)
5113 {
5114   HttpSM *sm    = (HttpSM *)txnp;
5115   APIHook *hook = sm->txn_hook_get(id);
5116 
5117   while (hook != nullptr) {
5118     if (hook->m_cont && hook->m_cont->m_event_func == funcp) {
5119       return TS_SUCCESS;
5120     }
5121     hook = hook->m_link.next;
5122   }
5123 
5124   return TS_ERROR;
5125 }
5126 
5127 TSHttpSsn
TSHttpTxnSsnGet(TSHttpTxn txnp)5128 TSHttpTxnSsnGet(TSHttpTxn txnp)
5129 {
5130   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5131 
5132   HttpSM *sm = reinterpret_cast<HttpSM *>(txnp);
5133   return reinterpret_cast<TSHttpSsn>(sm->ua_txn ? (TSHttpSsn)sm->ua_txn->get_proxy_ssn() : nullptr);
5134 }
5135 
5136 // TODO: Is this still necessary ??
5137 void
TSHttpTxnClientKeepaliveSet(TSHttpTxn txnp,int set)5138 TSHttpTxnClientKeepaliveSet(TSHttpTxn txnp, int set)
5139 {
5140   HttpSM *sm             = (HttpSM *)txnp;
5141   HttpTransact::State *s = &(sm->t_state);
5142 
5143   s->hdr_info.trust_response_cl = (set != 0);
5144 }
5145 
5146 TSReturnCode
TSHttpTxnClientReqGet(TSHttpTxn txnp,TSMBuffer * bufp,TSMLoc * obj)5147 TSHttpTxnClientReqGet(TSHttpTxn txnp, TSMBuffer *bufp, TSMLoc *obj)
5148 {
5149   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5150   sdk_assert(sdk_sanity_check_null_ptr((void *)bufp) == TS_SUCCESS);
5151   sdk_assert(sdk_sanity_check_null_ptr((void *)obj) == TS_SUCCESS);
5152 
5153   HttpSM *sm    = (HttpSM *)txnp;
5154   HTTPHdr *hptr = &(sm->t_state.hdr_info.client_request);
5155 
5156   if (hptr->valid()) {
5157     *(reinterpret_cast<HTTPHdr **>(bufp)) = hptr;
5158     *obj                                  = reinterpret_cast<TSMLoc>(hptr->m_http);
5159     if (sdk_sanity_check_mbuffer(*bufp) == TS_SUCCESS) {
5160       hptr->mark_target_dirty();
5161       return TS_SUCCESS;
5162       ;
5163     }
5164   }
5165   return TS_ERROR;
5166 }
5167 
5168 // pristine url is the url before remap
5169 TSReturnCode
TSHttpTxnPristineUrlGet(TSHttpTxn txnp,TSMBuffer * bufp,TSMLoc * url_loc)5170 TSHttpTxnPristineUrlGet(TSHttpTxn txnp, TSMBuffer *bufp, TSMLoc *url_loc)
5171 {
5172   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5173   sdk_assert(sdk_sanity_check_null_ptr((void *)bufp) == TS_SUCCESS);
5174   sdk_assert(sdk_sanity_check_null_ptr((void *)url_loc) == TS_SUCCESS);
5175 
5176   HttpSM *sm    = (HttpSM *)txnp;
5177   HTTPHdr *hptr = &(sm->t_state.hdr_info.client_request);
5178 
5179   if (hptr->valid()) {
5180     *(reinterpret_cast<HTTPHdr **>(bufp)) = hptr;
5181     *url_loc                              = (TSMLoc)sm->t_state.unmapped_url.m_url_impl;
5182 
5183     if (sdk_sanity_check_mbuffer(*bufp) == TS_SUCCESS) {
5184       if (*url_loc == nullptr) {
5185         *url_loc = (TSMLoc)hptr->m_http->u.req.m_url_impl;
5186       }
5187       if (*url_loc) {
5188         return TS_SUCCESS;
5189       }
5190     }
5191   }
5192   return TS_ERROR;
5193 }
5194 
5195 int
TSHttpTxnServerSsnTransactionCount(TSHttpTxn txnp)5196 TSHttpTxnServerSsnTransactionCount(TSHttpTxn txnp)
5197 {
5198   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5199 
5200   HttpSM *sm = (HttpSM *)txnp;
5201   // Any value greater than zero indicates connection reuse.
5202   return sm->server_transact_count;
5203 }
5204 
5205 // Shortcut to just get the URL.
5206 // The caller is responsible to free memory that is allocated for the string
5207 // that is returned.
5208 char *
TSHttpTxnEffectiveUrlStringGet(TSHttpTxn txnp,int * length)5209 TSHttpTxnEffectiveUrlStringGet(TSHttpTxn txnp, int *length)
5210 {
5211   sdk_assert(TS_SUCCESS == sdk_sanity_check_txn(txnp));
5212   sdk_assert(sdk_sanity_check_null_ptr((void *)length) == TS_SUCCESS);
5213 
5214   HttpSM *sm = reinterpret_cast<HttpSM *>(txnp);
5215   return sm->t_state.hdr_info.client_request.url_string_get(nullptr, length);
5216 }
5217 
5218 TSReturnCode
TSHttpHdrEffectiveUrlBufGet(TSMBuffer hdr_buf,TSMLoc hdr_loc,char * buf,int64_t size,int64_t * length)5219 TSHttpHdrEffectiveUrlBufGet(TSMBuffer hdr_buf, TSMLoc hdr_loc, char *buf, int64_t size, int64_t *length)
5220 {
5221   sdk_assert(sdk_sanity_check_mbuffer(hdr_buf) == TS_SUCCESS);
5222   sdk_assert(sdk_sanity_check_http_hdr_handle(hdr_loc) == TS_SUCCESS);
5223   if (size) {
5224     sdk_assert(sdk_sanity_check_null_ptr(buf) == TS_SUCCESS);
5225   }
5226   sdk_assert(sdk_sanity_check_null_ptr(length) == TS_SUCCESS);
5227 
5228   auto buf_handle = reinterpret_cast<HTTPHdr *>(hdr_buf);
5229   auto hdr_handle = reinterpret_cast<HTTPHdrImpl *>(hdr_loc);
5230 
5231   if (hdr_handle->m_polarity != HTTP_TYPE_REQUEST) {
5232     Debug("plugin", "Trying to get a URL from response header %p", hdr_loc);
5233     return TS_ERROR;
5234   }
5235 
5236   int url_length = buf_handle->url_printed_length(URLNormalize::LC_SCHEME_HOST | URLNormalize::IMPLIED_SCHEME);
5237 
5238   sdk_assert(url_length >= 0);
5239 
5240   *length = url_length;
5241 
5242   // If the user-provided buffer is too small to hold the URL string, do not put anything in it.  This is not considered
5243   // an error case.
5244   //
5245   if (url_length <= size) {
5246     int index  = 0;
5247     int offset = 0;
5248 
5249     buf_handle->url_print(buf, size, &index, &offset, URLNormalize::LC_SCHEME_HOST | URLNormalize::IMPLIED_SCHEME);
5250   }
5251 
5252   return TS_SUCCESS;
5253 }
5254 
5255 TSReturnCode
TSHttpTxnClientRespGet(TSHttpTxn txnp,TSMBuffer * bufp,TSMLoc * obj)5256 TSHttpTxnClientRespGet(TSHttpTxn txnp, TSMBuffer *bufp, TSMLoc *obj)
5257 {
5258   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5259   sdk_assert(sdk_sanity_check_null_ptr((void *)bufp) == TS_SUCCESS);
5260   sdk_assert(sdk_sanity_check_null_ptr((void *)obj) == TS_SUCCESS);
5261 
5262   HttpSM *sm    = (HttpSM *)txnp;
5263   HTTPHdr *hptr = &(sm->t_state.hdr_info.client_response);
5264 
5265   if (hptr->valid()) {
5266     *(reinterpret_cast<HTTPHdr **>(bufp)) = hptr;
5267     *obj                                  = reinterpret_cast<TSMLoc>(hptr->m_http);
5268     sdk_assert(sdk_sanity_check_mbuffer(*bufp) == TS_SUCCESS);
5269     return TS_SUCCESS;
5270   }
5271 
5272   return TS_ERROR;
5273 }
5274 
5275 TSReturnCode
TSHttpTxnServerReqGet(TSHttpTxn txnp,TSMBuffer * bufp,TSMLoc * obj)5276 TSHttpTxnServerReqGet(TSHttpTxn txnp, TSMBuffer *bufp, TSMLoc *obj)
5277 {
5278   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5279   sdk_assert(sdk_sanity_check_null_ptr((void *)bufp) == TS_SUCCESS);
5280   sdk_assert(sdk_sanity_check_null_ptr((void *)obj) == TS_SUCCESS);
5281 
5282   HttpSM *sm    = (HttpSM *)txnp;
5283   HTTPHdr *hptr = &(sm->t_state.hdr_info.server_request);
5284 
5285   if (hptr->valid()) {
5286     *(reinterpret_cast<HTTPHdr **>(bufp)) = hptr;
5287     *obj                                  = reinterpret_cast<TSMLoc>(hptr->m_http);
5288     sdk_assert(sdk_sanity_check_mbuffer(*bufp) == TS_SUCCESS);
5289     return TS_SUCCESS;
5290   }
5291 
5292   return TS_ERROR;
5293 }
5294 
5295 TSReturnCode
TSHttpTxnServerRespGet(TSHttpTxn txnp,TSMBuffer * bufp,TSMLoc * obj)5296 TSHttpTxnServerRespGet(TSHttpTxn txnp, TSMBuffer *bufp, TSMLoc *obj)
5297 {
5298   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5299   sdk_assert(sdk_sanity_check_null_ptr((void *)bufp) == TS_SUCCESS);
5300   sdk_assert(sdk_sanity_check_null_ptr((void *)obj) == TS_SUCCESS);
5301 
5302   HttpSM *sm    = (HttpSM *)txnp;
5303   HTTPHdr *hptr = &(sm->t_state.hdr_info.server_response);
5304 
5305   if (hptr->valid()) {
5306     *(reinterpret_cast<HTTPHdr **>(bufp)) = hptr;
5307     *obj                                  = reinterpret_cast<TSMLoc>(hptr->m_http);
5308     sdk_assert(sdk_sanity_check_mbuffer(*bufp) == TS_SUCCESS);
5309     return TS_SUCCESS;
5310   }
5311 
5312   return TS_ERROR;
5313 }
5314 
5315 TSReturnCode
TSHttpTxnCachedReqGet(TSHttpTxn txnp,TSMBuffer * bufp,TSMLoc * obj)5316 TSHttpTxnCachedReqGet(TSHttpTxn txnp, TSMBuffer *bufp, TSMLoc *obj)
5317 {
5318   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5319   sdk_assert(sdk_sanity_check_null_ptr((void *)bufp) == TS_SUCCESS);
5320   sdk_assert(sdk_sanity_check_null_ptr((void *)obj) == TS_SUCCESS);
5321 
5322   HttpSM *sm           = (HttpSM *)txnp;
5323   HTTPInfo *cached_obj = sm->t_state.cache_info.object_read;
5324 
5325   // The following check is need to prevent the HttpSM handle copy from going bad
5326   // Since the cache manages the header buffer, sm->t_state.cache_info.object_read
5327   // is the only way to tell if handle has gone bad.
5328   if ((!cached_obj) || (!cached_obj->valid())) {
5329     return TS_ERROR;
5330   }
5331 
5332   HTTPHdr *cached_hdr = sm->t_state.cache_info.object_read->request_get();
5333 
5334   if (!cached_hdr->valid()) {
5335     return TS_ERROR;
5336   }
5337   // We can't use the HdrHeapSDKHandle structure in the RamCache since multiple
5338   // threads can access. We need to create our own for the transaction and return that.
5339   HdrHeapSDKHandle **handle = &(sm->t_state.cache_req_hdr_heap_handle);
5340 
5341   if (*handle == nullptr) {
5342     *handle           = (HdrHeapSDKHandle *)sm->t_state.arena.alloc(sizeof(HdrHeapSDKHandle));
5343     (*handle)->m_heap = cached_hdr->m_heap;
5344   }
5345 
5346   *(reinterpret_cast<HdrHeapSDKHandle **>(bufp)) = *handle;
5347   *obj                                           = reinterpret_cast<TSMLoc>(cached_hdr->m_http);
5348   sdk_assert(sdk_sanity_check_mbuffer(*bufp) == TS_SUCCESS);
5349 
5350   return TS_SUCCESS;
5351 }
5352 
5353 TSReturnCode
TSHttpTxnCachedRespGet(TSHttpTxn txnp,TSMBuffer * bufp,TSMLoc * obj)5354 TSHttpTxnCachedRespGet(TSHttpTxn txnp, TSMBuffer *bufp, TSMLoc *obj)
5355 {
5356   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5357   sdk_assert(sdk_sanity_check_null_ptr((void *)bufp) == TS_SUCCESS);
5358   sdk_assert(sdk_sanity_check_null_ptr((void *)obj) == TS_SUCCESS);
5359 
5360   HttpSM *sm           = (HttpSM *)txnp;
5361   HTTPInfo *cached_obj = sm->t_state.cache_info.object_read;
5362 
5363   // The following check is need to prevent the HttpSM handle copy from going bad
5364   // Since the cache manages the header buffer, sm->t_state.cache_info.object_read
5365   // is the only way to tell if handle has gone bad.
5366   if ((!cached_obj) || (!cached_obj->valid())) {
5367     return TS_ERROR;
5368   }
5369 
5370   HTTPHdr *cached_hdr = sm->t_state.cache_info.object_read->response_get();
5371 
5372   if (!cached_hdr->valid()) {
5373     return TS_ERROR;
5374   }
5375   // We can't use the HdrHeapSDKHandle structure in the RamCache since multiple
5376   //  threads can access.  We need to create our own for the transaction and return that.
5377   HdrHeapSDKHandle **handle = &(sm->t_state.cache_resp_hdr_heap_handle);
5378 
5379   if (*handle == nullptr) {
5380     *handle = (HdrHeapSDKHandle *)sm->t_state.arena.alloc(sizeof(HdrHeapSDKHandle));
5381   }
5382   // Always reset the m_heap to make sure the heap is not stale
5383   (*handle)->m_heap = cached_hdr->m_heap;
5384 
5385   *(reinterpret_cast<HdrHeapSDKHandle **>(bufp)) = *handle;
5386   *obj                                           = reinterpret_cast<TSMLoc>(cached_hdr->m_http);
5387   sdk_assert(sdk_sanity_check_mbuffer(*bufp) == TS_SUCCESS);
5388 
5389   return TS_SUCCESS;
5390 }
5391 
5392 TSReturnCode
TSHttpTxnCachedRespModifiableGet(TSHttpTxn txnp,TSMBuffer * bufp,TSMLoc * obj)5393 TSHttpTxnCachedRespModifiableGet(TSHttpTxn txnp, TSMBuffer *bufp, TSMLoc *obj)
5394 {
5395   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5396   sdk_assert(sdk_sanity_check_null_ptr((void *)bufp) == TS_SUCCESS);
5397   sdk_assert(sdk_sanity_check_null_ptr((void *)obj) == TS_SUCCESS);
5398 
5399   HttpSM *sm                 = (HttpSM *)txnp;
5400   HttpTransact::State *s     = &(sm->t_state);
5401   HTTPHdr *c_resp            = nullptr;
5402   HTTPInfo *cached_obj       = sm->t_state.cache_info.object_read;
5403   HTTPInfo *cached_obj_store = &(sm->t_state.cache_info.object_store);
5404 
5405   if ((!cached_obj) || (!cached_obj->valid())) {
5406     return TS_ERROR;
5407   }
5408 
5409   if (!cached_obj_store->valid()) {
5410     cached_obj_store->create();
5411   }
5412 
5413   c_resp = cached_obj_store->response_get();
5414   if (!c_resp->valid()) {
5415     cached_obj_store->response_set(cached_obj->response_get());
5416   }
5417   c_resp                        = cached_obj_store->response_get();
5418   s->api_modifiable_cached_resp = true;
5419 
5420   ink_assert(c_resp != nullptr && c_resp->valid());
5421   *(reinterpret_cast<HTTPHdr **>(bufp)) = c_resp;
5422   *obj                                  = reinterpret_cast<TSMLoc>(c_resp->m_http);
5423   sdk_assert(sdk_sanity_check_mbuffer(*bufp) == TS_SUCCESS);
5424 
5425   return TS_SUCCESS;
5426 }
5427 
5428 TSReturnCode
TSHttpTxnCacheLookupStatusGet(TSHttpTxn txnp,int * lookup_status)5429 TSHttpTxnCacheLookupStatusGet(TSHttpTxn txnp, int *lookup_status)
5430 {
5431   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5432   sdk_assert(sdk_sanity_check_null_ptr((void *)lookup_status) == TS_SUCCESS);
5433 
5434   HttpSM *sm = (HttpSM *)txnp;
5435 
5436   switch (sm->t_state.cache_lookup_result) {
5437   case HttpTransact::CACHE_LOOKUP_MISS:
5438   case HttpTransact::CACHE_LOOKUP_DOC_BUSY:
5439     *lookup_status = TS_CACHE_LOOKUP_MISS;
5440     break;
5441   case HttpTransact::CACHE_LOOKUP_HIT_STALE:
5442     *lookup_status = TS_CACHE_LOOKUP_HIT_STALE;
5443     break;
5444   case HttpTransact::CACHE_LOOKUP_HIT_WARNING:
5445   case HttpTransact::CACHE_LOOKUP_HIT_FRESH:
5446     *lookup_status = TS_CACHE_LOOKUP_HIT_FRESH;
5447     break;
5448   case HttpTransact::CACHE_LOOKUP_SKIPPED:
5449     *lookup_status = TS_CACHE_LOOKUP_SKIPPED;
5450     break;
5451   case HttpTransact::CACHE_LOOKUP_NONE:
5452   default:
5453     return TS_ERROR;
5454   };
5455   return TS_SUCCESS;
5456 }
5457 
5458 TSReturnCode
TSHttpTxnCacheLookupCountGet(TSHttpTxn txnp,int * lookup_count)5459 TSHttpTxnCacheLookupCountGet(TSHttpTxn txnp, int *lookup_count)
5460 {
5461   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5462   sdk_assert(sdk_sanity_check_null_ptr((void *)lookup_count) == TS_SUCCESS);
5463 
5464   HttpSM *sm    = (HttpSM *)txnp;
5465   *lookup_count = sm->t_state.cache_info.lookup_count;
5466   return TS_SUCCESS;
5467 }
5468 
5469 /* two hooks this function may gets called:
5470    TS_HTTP_READ_CACHE_HDR_HOOK   &
5471    TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK
5472  */
5473 TSReturnCode
TSHttpTxnCacheLookupStatusSet(TSHttpTxn txnp,int cachelookup)5474 TSHttpTxnCacheLookupStatusSet(TSHttpTxn txnp, int cachelookup)
5475 {
5476   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5477 
5478   HttpSM *sm                                   = (HttpSM *)txnp;
5479   HttpTransact::CacheLookupResult_t *sm_status = &(sm->t_state.cache_lookup_result);
5480 
5481   // converting from a miss to a hit is not allowed
5482   if (*sm_status == HttpTransact::CACHE_LOOKUP_MISS && cachelookup != TS_CACHE_LOOKUP_MISS) {
5483     return TS_ERROR;
5484   }
5485 
5486   // here is to handle converting a hit to a miss
5487   if (cachelookup == TS_CACHE_LOOKUP_MISS && *sm_status != HttpTransact::CACHE_LOOKUP_MISS) {
5488     sm->t_state.api_cleanup_cache_read = true;
5489     ink_assert(sm->t_state.transact_return_point != nullptr);
5490     sm->t_state.transact_return_point = HttpTransact::HandleCacheOpenRead;
5491   }
5492 
5493   switch (cachelookup) {
5494   case TS_CACHE_LOOKUP_MISS:
5495     *sm_status = HttpTransact::CACHE_LOOKUP_MISS;
5496     break;
5497   case TS_CACHE_LOOKUP_HIT_STALE:
5498     *sm_status = HttpTransact::CACHE_LOOKUP_HIT_STALE;
5499     break;
5500   case TS_CACHE_LOOKUP_HIT_FRESH:
5501     *sm_status = HttpTransact::CACHE_LOOKUP_HIT_FRESH;
5502     break;
5503   default:
5504     return TS_ERROR;
5505   }
5506 
5507   return TS_SUCCESS;
5508 }
5509 
5510 TSReturnCode
TSHttpTxnInfoIntGet(TSHttpTxn txnp,TSHttpTxnInfoKey key,TSMgmtInt * value)5511 TSHttpTxnInfoIntGet(TSHttpTxn txnp, TSHttpTxnInfoKey key, TSMgmtInt *value)
5512 {
5513   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5514   sdk_assert(sdk_sanity_check_null_ptr((void *)value) == TS_SUCCESS);
5515 
5516   HttpSM *s         = reinterpret_cast<HttpSM *>(txnp);
5517   HttpCacheSM *c_sm = &(s->get_cache_sm());
5518 
5519   switch (key) {
5520   case TS_TXN_INFO_CACHE_HIT_RAM:
5521     *value = (static_cast<TSMgmtInt>(c_sm->is_ram_cache_hit()));
5522     break;
5523   case TS_TXN_INFO_CACHE_COMPRESSED_IN_RAM:
5524     *value = (static_cast<TSMgmtInt>(c_sm->is_compressed_in_ram()));
5525     break;
5526   case TS_TXN_INFO_CACHE_HIT_RWW:
5527     *value = (static_cast<TSMgmtInt>(c_sm->is_readwhilewrite_inprogress()));
5528     break;
5529   case TS_TXN_INFO_CACHE_OPEN_READ_TRIES:
5530     *value = (static_cast<TSMgmtInt>(c_sm->get_open_read_tries()));
5531     break;
5532   case TS_TXN_INFO_CACHE_OPEN_WRITE_TRIES:
5533     *value = (static_cast<TSMgmtInt>(c_sm->get_open_write_tries()));
5534     break;
5535   case TS_TXN_INFO_CACHE_VOLUME:
5536     *value = (static_cast<TSMgmtInt>(c_sm->get_volume_number()));
5537     break;
5538   default:
5539     return TS_ERROR;
5540   }
5541 
5542   return TS_SUCCESS;
5543 }
5544 
5545 int
TSHttpTxnIsWebsocket(TSHttpTxn txnp)5546 TSHttpTxnIsWebsocket(TSHttpTxn txnp)
5547 {
5548   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5549 
5550   HttpSM *sm = (HttpSM *)txnp;
5551   return sm->t_state.is_websocket;
5552 }
5553 
5554 const char *
TSHttpTxnCacheDiskPathGet(TSHttpTxn txnp,int * length)5555 TSHttpTxnCacheDiskPathGet(TSHttpTxn txnp, int *length)
5556 {
5557   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5558 
5559   HttpSM *sm       = reinterpret_cast<HttpSM *>(txnp);
5560   char const *path = nullptr;
5561 
5562   if (HttpCacheSM *c_sm = &(sm->get_cache_sm()); c_sm) {
5563     path = c_sm->get_disk_path();
5564   }
5565   if (length) {
5566     *length = path ? strlen(path) : 0;
5567   }
5568 
5569   return path;
5570 }
5571 
5572 TSReturnCode
TSHttpTxnCacheLookupUrlGet(TSHttpTxn txnp,TSMBuffer bufp,TSMLoc obj)5573 TSHttpTxnCacheLookupUrlGet(TSHttpTxn txnp, TSMBuffer bufp, TSMLoc obj)
5574 {
5575   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5576   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
5577   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
5578 
5579   HttpSM *sm = (HttpSM *)txnp;
5580   URL u, *l_url;
5581 
5582   u.m_heap     = ((HdrHeapSDKHandle *)bufp)->m_heap;
5583   u.m_url_impl = (URLImpl *)obj;
5584   if (!u.valid()) {
5585     return TS_ERROR;
5586   }
5587 
5588   l_url = sm->t_state.cache_info.lookup_url;
5589   if (l_url && l_url->valid()) {
5590     u.copy(l_url);
5591     return TS_SUCCESS;
5592   }
5593 
5594   return TS_ERROR;
5595 }
5596 
5597 TSReturnCode
TSHttpTxnCacheLookupUrlSet(TSHttpTxn txnp,TSMBuffer bufp,TSMLoc obj)5598 TSHttpTxnCacheLookupUrlSet(TSHttpTxn txnp, TSMBuffer bufp, TSMLoc obj)
5599 {
5600   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5601   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
5602   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
5603 
5604   HttpSM *sm = (HttpSM *)txnp;
5605   URL u, *l_url;
5606 
5607   u.m_heap     = ((HdrHeapSDKHandle *)bufp)->m_heap;
5608   u.m_url_impl = (URLImpl *)obj;
5609   if (!u.valid()) {
5610     return TS_ERROR;
5611   }
5612 
5613   l_url = sm->t_state.cache_info.lookup_url;
5614   if (!l_url) {
5615     sm->t_state.cache_info.lookup_url_storage.create(nullptr);
5616     sm->t_state.cache_info.lookup_url = &(sm->t_state.cache_info.lookup_url_storage);
5617     l_url                             = sm->t_state.cache_info.lookup_url;
5618   }
5619 
5620   if (!l_url || !l_url->valid()) {
5621     return TS_ERROR;
5622   } else {
5623     l_url->copy(&u);
5624   }
5625 
5626   return TS_SUCCESS;
5627 }
5628 
5629 /**
5630  * timeout is in msec
5631  * overrides as proxy.config.http.transaction_active_timeout_out
5632  **/
5633 void
TSHttpTxnActiveTimeoutSet(TSHttpTxn txnp,int timeout)5634 TSHttpTxnActiveTimeoutSet(TSHttpTxn txnp, int timeout)
5635 {
5636   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5637 
5638   HttpTransact::State *s          = &(((HttpSM *)txnp)->t_state);
5639   s->api_txn_active_timeout_value = timeout;
5640 }
5641 
5642 /**
5643  * timeout is in msec
5644  * overrides as proxy.config.http.connect_attempts_timeout
5645  **/
5646 void
TSHttpTxnConnectTimeoutSet(TSHttpTxn txnp,int timeout)5647 TSHttpTxnConnectTimeoutSet(TSHttpTxn txnp, int timeout)
5648 {
5649   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5650 
5651   HttpTransact::State *s           = &(((HttpSM *)txnp)->t_state);
5652   s->api_txn_connect_timeout_value = timeout;
5653 }
5654 
5655 /**
5656  * timeout is in msec
5657  * overrides as proxy.config.dns.lookup_timeout
5658  **/
5659 void
TSHttpTxnDNSTimeoutSet(TSHttpTxn txnp,int timeout)5660 TSHttpTxnDNSTimeoutSet(TSHttpTxn txnp, int timeout)
5661 {
5662   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5663 
5664   HttpTransact::State *s = &(((HttpSM *)txnp)->t_state);
5665 
5666   s->api_txn_dns_timeout_value = timeout;
5667 }
5668 
5669 /**
5670  * timeout is in msec
5671  * overrides as proxy.config.http.transaction_no_activity_timeout_out
5672  **/
5673 void
TSHttpTxnNoActivityTimeoutSet(TSHttpTxn txnp,int timeout)5674 TSHttpTxnNoActivityTimeoutSet(TSHttpTxn txnp, int timeout)
5675 {
5676   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5677 
5678   HttpTransact::State *s               = &(((HttpSM *)txnp)->t_state);
5679   s->api_txn_no_activity_timeout_value = timeout;
5680 }
5681 
5682 TSReturnCode
TSHttpTxnServerRespNoStoreSet(TSHttpTxn txnp,int flag)5683 TSHttpTxnServerRespNoStoreSet(TSHttpTxn txnp, int flag)
5684 {
5685   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5686 
5687   HttpTransact::State *s          = &(((HttpSM *)txnp)->t_state);
5688   s->api_server_response_no_store = (flag != 0);
5689 
5690   return TS_SUCCESS;
5691 }
5692 
5693 bool
TSHttpTxnServerRespNoStoreGet(TSHttpTxn txnp)5694 TSHttpTxnServerRespNoStoreGet(TSHttpTxn txnp)
5695 {
5696   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5697 
5698   HttpTransact::State *s = &(((HttpSM *)txnp)->t_state);
5699   return s->api_server_response_no_store;
5700 }
5701 
5702 TSReturnCode
TSHttpTxnServerRespIgnore(TSHttpTxn txnp)5703 TSHttpTxnServerRespIgnore(TSHttpTxn txnp)
5704 {
5705   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5706 
5707   HttpTransact::State *s = &(((HttpSM *)txnp)->t_state);
5708   HTTPInfo *cached_obj   = s->cache_info.object_read;
5709   HTTPHdr *cached_resp;
5710 
5711   if (cached_obj == nullptr || !cached_obj->valid()) {
5712     return TS_ERROR;
5713   }
5714 
5715   cached_resp = cached_obj->response_get();
5716   if (cached_resp == nullptr || !cached_resp->valid()) {
5717     return TS_ERROR;
5718   }
5719 
5720   s->api_server_response_ignore = true;
5721 
5722   return TS_SUCCESS;
5723 }
5724 
5725 TSReturnCode
TSHttpTxnShutDown(TSHttpTxn txnp,TSEvent event)5726 TSHttpTxnShutDown(TSHttpTxn txnp, TSEvent event)
5727 {
5728   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5729 
5730   if (event == TS_EVENT_HTTP_TXN_CLOSE) {
5731     return TS_ERROR;
5732   }
5733 
5734   HttpTransact::State *s  = &(((HttpSM *)txnp)->t_state);
5735   s->api_http_sm_shutdown = true;
5736 
5737   return TS_SUCCESS;
5738 }
5739 
5740 TSReturnCode
TSHttpTxnAborted(TSHttpTxn txnp)5741 TSHttpTxnAborted(TSHttpTxn txnp)
5742 {
5743   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5744 
5745   HttpSM *sm = (HttpSM *)txnp;
5746   switch (sm->t_state.squid_codes.log_code) {
5747   case SQUID_LOG_ERR_CLIENT_ABORT:
5748   case SQUID_LOG_ERR_CLIENT_READ_ERROR:
5749   case SQUID_LOG_TCP_SWAPFAIL:
5750     // check for client abort and cache read error
5751     return TS_SUCCESS;
5752   default:
5753     break;
5754   }
5755 
5756   if (sm->t_state.current.server && sm->t_state.current.server->abort == HttpTransact::ABORTED) {
5757     // check for the server abort
5758     return TS_SUCCESS;
5759   }
5760   // there can be the case of transformation error.
5761   return TS_ERROR;
5762 }
5763 
5764 void
TSHttpTxnReqCacheableSet(TSHttpTxn txnp,int flag)5765 TSHttpTxnReqCacheableSet(TSHttpTxn txnp, int flag)
5766 {
5767   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5768 
5769   HttpSM *sm                    = (HttpSM *)txnp;
5770   sm->t_state.api_req_cacheable = (flag != 0);
5771 }
5772 
5773 void
TSHttpTxnRespCacheableSet(TSHttpTxn txnp,int flag)5774 TSHttpTxnRespCacheableSet(TSHttpTxn txnp, int flag)
5775 {
5776   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5777 
5778   HttpSM *sm                     = (HttpSM *)txnp;
5779   sm->t_state.api_resp_cacheable = (flag != 0);
5780 }
5781 
5782 int
TSHttpTxnClientReqIsServerStyle(TSHttpTxn txnp)5783 TSHttpTxnClientReqIsServerStyle(TSHttpTxn txnp)
5784 {
5785   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5786 
5787   HttpSM *sm = (HttpSM *)txnp;
5788   return (sm->t_state.hdr_info.client_req_is_server_style ? 1 : 0);
5789 }
5790 
5791 void
TSHttpTxnOverwriteExpireTime(TSHttpTxn txnp,time_t expire_time)5792 TSHttpTxnOverwriteExpireTime(TSHttpTxn txnp, time_t expire_time)
5793 {
5794   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5795 
5796   HttpTransact::State *s    = &(((HttpSM *)txnp)->t_state);
5797   s->plugin_set_expire_time = expire_time;
5798 }
5799 
5800 TSReturnCode
TSHttpTxnUpdateCachedObject(TSHttpTxn txnp)5801 TSHttpTxnUpdateCachedObject(TSHttpTxn txnp)
5802 {
5803   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5804 
5805   HttpSM *sm                 = (HttpSM *)txnp;
5806   HttpTransact::State *s     = &(sm->t_state);
5807   HTTPInfo *cached_obj_store = &(sm->t_state.cache_info.object_store);
5808   HTTPHdr *client_request    = &(sm->t_state.hdr_info.client_request);
5809 
5810   if (!cached_obj_store->valid() || !cached_obj_store->response_get()) {
5811     return TS_ERROR;
5812   }
5813 
5814   if (!cached_obj_store->request_get() && !client_request->valid()) {
5815     return TS_ERROR;
5816   }
5817 
5818   if (s->cache_info.write_lock_state == HttpTransact::CACHE_WL_READ_RETRY) {
5819     return TS_ERROR;
5820   }
5821 
5822   s->api_update_cached_object = HttpTransact::UPDATE_CACHED_OBJECT_PREPARE;
5823   return TS_SUCCESS;
5824 }
5825 
5826 TSReturnCode
TSHttpTxnTransformRespGet(TSHttpTxn txnp,TSMBuffer * bufp,TSMLoc * obj)5827 TSHttpTxnTransformRespGet(TSHttpTxn txnp, TSMBuffer *bufp, TSMLoc *obj)
5828 {
5829   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5830 
5831   HttpSM *sm    = (HttpSM *)txnp;
5832   HTTPHdr *hptr = &(sm->t_state.hdr_info.transform_response);
5833 
5834   if (hptr->valid()) {
5835     *(reinterpret_cast<HTTPHdr **>(bufp)) = hptr;
5836     *obj                                  = reinterpret_cast<TSMLoc>(hptr->m_http);
5837     return sdk_sanity_check_mbuffer(*bufp);
5838   }
5839 
5840   return TS_ERROR;
5841 }
5842 
5843 sockaddr const *
TSHttpSsnClientAddrGet(TSHttpSsn ssnp)5844 TSHttpSsnClientAddrGet(TSHttpSsn ssnp)
5845 {
5846   ProxySession *cs = reinterpret_cast<ProxySession *>(ssnp);
5847 
5848   if (cs == nullptr) {
5849     return nullptr;
5850   }
5851   return cs->get_remote_addr();
5852 }
5853 sockaddr const *
TSHttpTxnClientAddrGet(TSHttpTxn txnp)5854 TSHttpTxnClientAddrGet(TSHttpTxn txnp)
5855 {
5856   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5857 
5858   TSHttpSsn ssnp = TSHttpTxnSsnGet(txnp);
5859   return TSHttpSsnClientAddrGet(ssnp);
5860 }
5861 
5862 sockaddr const *
TSHttpSsnIncomingAddrGet(TSHttpSsn ssnp)5863 TSHttpSsnIncomingAddrGet(TSHttpSsn ssnp)
5864 {
5865   ProxySession *cs = reinterpret_cast<ProxySession *>(ssnp);
5866 
5867   if (cs == nullptr) {
5868     return nullptr;
5869   }
5870   return cs->get_local_addr();
5871 }
5872 sockaddr const *
TSHttpTxnIncomingAddrGet(TSHttpTxn txnp)5873 TSHttpTxnIncomingAddrGet(TSHttpTxn txnp)
5874 {
5875   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5876 
5877   TSHttpSsn ssnp = TSHttpTxnSsnGet(txnp);
5878   return TSHttpSsnIncomingAddrGet(ssnp);
5879 }
5880 
5881 sockaddr const *
TSHttpTxnOutgoingAddrGet(TSHttpTxn txnp)5882 TSHttpTxnOutgoingAddrGet(TSHttpTxn txnp)
5883 {
5884   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5885 
5886   HttpSM *sm = reinterpret_cast<HttpSM *>(txnp);
5887 
5888   PoolableSession *ssn = sm->get_server_session();
5889   if (ssn == nullptr) {
5890     return nullptr;
5891   }
5892 
5893   NetVConnection *vc = ssn->get_netvc();
5894   if (vc == nullptr) {
5895     return nullptr;
5896   }
5897 
5898   return vc->get_local_addr();
5899 }
5900 
5901 sockaddr const *
TSHttpTxnServerAddrGet(TSHttpTxn txnp)5902 TSHttpTxnServerAddrGet(TSHttpTxn txnp)
5903 {
5904   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5905 
5906   HttpSM *sm = reinterpret_cast<HttpSM *>(txnp);
5907   return &sm->t_state.server_info.dst_addr.sa;
5908 }
5909 
5910 TSReturnCode
TSHttpTxnServerAddrSet(TSHttpTxn txnp,struct sockaddr const * addr)5911 TSHttpTxnServerAddrSet(TSHttpTxn txnp, struct sockaddr const *addr)
5912 {
5913   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5914 
5915   HttpSM *sm = reinterpret_cast<HttpSM *>(txnp);
5916   if (ats_ip_copy(&sm->t_state.server_info.dst_addr.sa, addr)) {
5917     sm->t_state.api_server_addr_set = true;
5918     return TS_SUCCESS;
5919   } else {
5920     return TS_ERROR;
5921   }
5922 }
5923 
5924 void
TSHttpTxnClientIncomingPortSet(TSHttpTxn txnp,int port)5925 TSHttpTxnClientIncomingPortSet(TSHttpTxn txnp, int port)
5926 {
5927   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5928 
5929   HttpSM *sm                              = reinterpret_cast<HttpSM *>(txnp);
5930   sm->t_state.client_info.dst_addr.port() = htons(port);
5931 }
5932 
5933 // [amc] This might use the port. The code path should do that but it
5934 // hasn't been tested.
5935 TSReturnCode
TSHttpTxnOutgoingAddrSet(TSHttpTxn txnp,const struct sockaddr * addr)5936 TSHttpTxnOutgoingAddrSet(TSHttpTxn txnp, const struct sockaddr *addr)
5937 {
5938   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5939   HttpSM *sm = (HttpSM *)txnp;
5940 
5941   sm->ua_txn->upstream_outbound_options.outbound_port = ats_ip_port_host_order(addr);
5942   sm->ua_txn->set_outbound_ip(IpAddr(addr));
5943   return TS_SUCCESS;
5944 }
5945 
5946 sockaddr const *
TSHttpTxnNextHopAddrGet(TSHttpTxn txnp)5947 TSHttpTxnNextHopAddrGet(TSHttpTxn txnp)
5948 {
5949   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5950 
5951   HttpSM *sm = reinterpret_cast<HttpSM *>(txnp);
5952 
5953   /**
5954    * Return zero if the server structure is not yet constructed.
5955    */
5956   if (sm->t_state.current.server == nullptr) {
5957     return nullptr;
5958   }
5959 
5960   return &sm->t_state.current.server->dst_addr.sa;
5961 }
5962 
5963 const char *
TSHttpTxnNextHopNameGet(TSHttpTxn txnp)5964 TSHttpTxnNextHopNameGet(TSHttpTxn txnp)
5965 {
5966   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
5967 
5968   HttpSM *sm = reinterpret_cast<HttpSM *>(txnp);
5969 
5970   /**
5971    * Return zero if the server structure is not yet constructed.
5972    */
5973   if (sm->t_state.current.server == nullptr) {
5974     return nullptr;
5975   }
5976 
5977   return sm->t_state.current.server->name;
5978 }
5979 
5980 TSReturnCode
TSHttpTxnOutgoingTransparencySet(TSHttpTxn txnp,int flag)5981 TSHttpTxnOutgoingTransparencySet(TSHttpTxn txnp, int flag)
5982 {
5983   if (TS_SUCCESS != sdk_sanity_check_txn(txnp)) {
5984     return TS_ERROR;
5985   }
5986 
5987   HttpSM *sm = reinterpret_cast<HttpSM *>(txnp);
5988   if (nullptr == sm || nullptr == sm->ua_txn) {
5989     return TS_ERROR;
5990   }
5991 
5992   sm->ua_txn->set_outbound_transparent(flag);
5993   return TS_SUCCESS;
5994 }
5995 
5996 TSReturnCode
TSHttpTxnClientPacketMarkSet(TSHttpTxn txnp,int mark)5997 TSHttpTxnClientPacketMarkSet(TSHttpTxn txnp, int mark)
5998 {
5999   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6000   HttpSM *sm = (HttpSM *)txnp;
6001   if (nullptr == sm->ua_txn) {
6002     return TS_ERROR;
6003   }
6004 
6005   NetVConnection *vc = sm->ua_txn->get_netvc();
6006   if (nullptr == vc) {
6007     return TS_ERROR;
6008   }
6009 
6010   vc->options.packet_mark = (uint32_t)mark;
6011   vc->apply_options();
6012   return TS_SUCCESS;
6013 }
6014 
6015 TSReturnCode
TSHttpTxnServerPacketMarkSet(TSHttpTxn txnp,int mark)6016 TSHttpTxnServerPacketMarkSet(TSHttpTxn txnp, int mark)
6017 {
6018   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6019   HttpSM *sm = (HttpSM *)txnp;
6020 
6021   // change the mark on an active server session
6022   if (nullptr != sm->ua_txn) {
6023     PoolableSession *ssn = sm->ua_txn->get_server_session();
6024     if (nullptr != ssn) {
6025       NetVConnection *vc = ssn->get_netvc();
6026       if (vc != nullptr) {
6027         vc->options.packet_mark = (uint32_t)mark;
6028         vc->apply_options();
6029       }
6030     }
6031   }
6032 
6033   // update the transactions mark config for future connections
6034   TSHttpTxnConfigIntSet(txnp, TS_CONFIG_NET_SOCK_PACKET_MARK_OUT, mark);
6035   return TS_SUCCESS;
6036 }
6037 
6038 TSReturnCode
TSHttpTxnClientPacketTosSet(TSHttpTxn txnp,int tos)6039 TSHttpTxnClientPacketTosSet(TSHttpTxn txnp, int tos)
6040 {
6041   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6042   HttpSM *sm = (HttpSM *)txnp;
6043   if (nullptr == sm->ua_txn) {
6044     return TS_ERROR;
6045   }
6046 
6047   NetVConnection *vc = sm->ua_txn->get_netvc();
6048   if (nullptr == vc) {
6049     return TS_ERROR;
6050   }
6051 
6052   vc->options.packet_tos = (uint32_t)tos;
6053   vc->apply_options();
6054   return TS_SUCCESS;
6055 }
6056 
6057 TSReturnCode
TSHttpTxnServerPacketTosSet(TSHttpTxn txnp,int tos)6058 TSHttpTxnServerPacketTosSet(TSHttpTxn txnp, int tos)
6059 {
6060   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6061   HttpSM *sm = (HttpSM *)txnp;
6062 
6063   // change the tos on an active server session
6064   if (nullptr != sm->ua_txn) {
6065     PoolableSession *ssn = sm->ua_txn->get_server_session();
6066     if (nullptr != ssn) {
6067       NetVConnection *vc = ssn->get_netvc();
6068       if (vc != nullptr) {
6069         vc->options.packet_tos = (uint32_t)tos;
6070         vc->apply_options();
6071       }
6072     }
6073   }
6074 
6075   // update the transactions mark config for future connections
6076   TSHttpTxnConfigIntSet(txnp, TS_CONFIG_NET_SOCK_PACKET_TOS_OUT, tos);
6077   return TS_SUCCESS;
6078 }
6079 
6080 TSReturnCode
TSHttpTxnClientPacketDscpSet(TSHttpTxn txnp,int dscp)6081 TSHttpTxnClientPacketDscpSet(TSHttpTxn txnp, int dscp)
6082 {
6083   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6084   HttpSM *sm = (HttpSM *)txnp;
6085   if (nullptr == sm->ua_txn) {
6086     return TS_ERROR;
6087   }
6088 
6089   NetVConnection *vc = sm->ua_txn->get_netvc();
6090   if (nullptr == vc) {
6091     return TS_ERROR;
6092   }
6093 
6094   vc->options.packet_tos = (uint32_t)dscp << 2;
6095   vc->apply_options();
6096   return TS_SUCCESS;
6097 }
6098 
6099 TSReturnCode
TSHttpTxnServerPacketDscpSet(TSHttpTxn txnp,int dscp)6100 TSHttpTxnServerPacketDscpSet(TSHttpTxn txnp, int dscp)
6101 {
6102   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6103   HttpSM *sm = (HttpSM *)txnp;
6104 
6105   // change the tos on an active server session
6106   if (nullptr != sm->ua_txn) {
6107     PoolableSession *ssn = sm->ua_txn->get_server_session();
6108     if (nullptr != ssn) {
6109       NetVConnection *vc = ssn->get_netvc();
6110       if (vc != nullptr) {
6111         vc->options.packet_tos = (uint32_t)dscp << 2;
6112         vc->apply_options();
6113       }
6114     }
6115   }
6116 
6117   // update the transactions mark config for future connections
6118   TSHttpTxnConfigIntSet(txnp, TS_CONFIG_NET_SOCK_PACKET_TOS_OUT, dscp << 2);
6119   return TS_SUCCESS;
6120 }
6121 
6122 // Set the body, or, if you provide a NULL buffer, clear the body message
6123 void
TSHttpTxnErrorBodySet(TSHttpTxn txnp,char * buf,size_t buflength,char * mimetype)6124 TSHttpTxnErrorBodySet(TSHttpTxn txnp, char *buf, size_t buflength, char *mimetype)
6125 {
6126   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6127 
6128   HttpSM *sm             = (HttpSM *)txnp;
6129   HttpTransact::State *s = &(sm->t_state);
6130 
6131   // Cleanup anything already set.
6132   s->free_internal_msg_buffer();
6133   ats_free(s->internal_msg_buffer_type);
6134 
6135   s->internal_msg_buffer                     = buf;
6136   s->internal_msg_buffer_size                = buf ? buflength : 0;
6137   s->internal_msg_buffer_fast_allocator_size = -1;
6138 
6139   s->internal_msg_buffer_type = mimetype;
6140 }
6141 
6142 void
TSHttpTxnServerRequestBodySet(TSHttpTxn txnp,char * buf,int64_t buflength)6143 TSHttpTxnServerRequestBodySet(TSHttpTxn txnp, char *buf, int64_t buflength)
6144 {
6145   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6146 
6147   HttpSM *sm             = (HttpSM *)txnp;
6148   HttpTransact::State *s = &(sm->t_state);
6149 
6150   // Cleanup anything already set.
6151   s->free_internal_msg_buffer();
6152 
6153   if (buf) {
6154     s->api_server_request_body_set = true;
6155     s->internal_msg_buffer         = buf;
6156     s->internal_msg_buffer_size    = buflength;
6157   } else {
6158     s->api_server_request_body_set = false;
6159     s->internal_msg_buffer         = nullptr;
6160     s->internal_msg_buffer_size    = 0;
6161   }
6162   s->internal_msg_buffer_fast_allocator_size = -1;
6163 }
6164 
6165 TSReturnCode
TSHttpTxnParentProxyGet(TSHttpTxn txnp,const char ** hostname,int * port)6166 TSHttpTxnParentProxyGet(TSHttpTxn txnp, const char **hostname, int *port)
6167 {
6168   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6169 
6170   HttpSM *sm = (HttpSM *)txnp;
6171 
6172   *hostname = sm->t_state.api_info.parent_proxy_name;
6173   *port     = sm->t_state.api_info.parent_proxy_port;
6174 
6175   return TS_SUCCESS;
6176 }
6177 
6178 void
TSHttpTxnParentProxySet(TSHttpTxn txnp,const char * hostname,int port)6179 TSHttpTxnParentProxySet(TSHttpTxn txnp, const char *hostname, int port)
6180 {
6181   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6182   sdk_assert(sdk_sanity_check_null_ptr((void *)hostname) == TS_SUCCESS);
6183   sdk_assert(port > 0);
6184 
6185   HttpSM *sm = (HttpSM *)txnp;
6186 
6187   sm->t_state.api_info.parent_proxy_name = sm->t_state.arena.str_store(hostname, strlen(hostname));
6188   sm->t_state.api_info.parent_proxy_port = port;
6189 }
6190 
6191 TSReturnCode
TSHttpTxnParentSelectionUrlGet(TSHttpTxn txnp,TSMBuffer bufp,TSMLoc obj)6192 TSHttpTxnParentSelectionUrlGet(TSHttpTxn txnp, TSMBuffer bufp, TSMLoc obj)
6193 {
6194   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6195   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
6196   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
6197 
6198   HttpSM *sm = (HttpSM *)txnp;
6199   URL u, *l_url;
6200 
6201   u.m_heap     = ((HdrHeapSDKHandle *)bufp)->m_heap;
6202   u.m_url_impl = (URLImpl *)obj;
6203   if (!u.valid()) {
6204     return TS_ERROR;
6205   }
6206 
6207   l_url = sm->t_state.cache_info.parent_selection_url;
6208   if (l_url && l_url->valid()) {
6209     u.copy(l_url);
6210     return TS_SUCCESS;
6211   }
6212 
6213   return TS_ERROR;
6214 }
6215 
6216 TSReturnCode
TSHttpTxnParentSelectionUrlSet(TSHttpTxn txnp,TSMBuffer bufp,TSMLoc obj)6217 TSHttpTxnParentSelectionUrlSet(TSHttpTxn txnp, TSMBuffer bufp, TSMLoc obj)
6218 {
6219   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6220   sdk_assert(sdk_sanity_check_mbuffer(bufp) == TS_SUCCESS);
6221   sdk_assert(sdk_sanity_check_url_handle(obj) == TS_SUCCESS);
6222 
6223   HttpSM *sm = (HttpSM *)txnp;
6224   URL u, *l_url;
6225 
6226   u.m_heap     = ((HdrHeapSDKHandle *)bufp)->m_heap;
6227   u.m_url_impl = (URLImpl *)obj;
6228   if (!u.valid()) {
6229     return TS_ERROR;
6230   }
6231 
6232   l_url = sm->t_state.cache_info.parent_selection_url;
6233   if (!l_url) {
6234     sm->t_state.cache_info.parent_selection_url_storage.create(nullptr);
6235     sm->t_state.cache_info.parent_selection_url = &(sm->t_state.cache_info.parent_selection_url_storage);
6236     l_url                                       = sm->t_state.cache_info.parent_selection_url;
6237   }
6238 
6239   if (!l_url || !l_url->valid()) {
6240     return TS_ERROR;
6241   } else {
6242     l_url->copy(&u);
6243   }
6244 
6245   Debug("parent_select", "TSHttpTxnParentSelectionUrlSet() parent_selection_url : addr = %p val = %p",
6246         &(sm->t_state.cache_info.parent_selection_url), sm->t_state.cache_info.parent_selection_url);
6247 
6248   return TS_SUCCESS;
6249 }
6250 
6251 void
TSHttpTxnUntransformedRespCache(TSHttpTxn txnp,int on)6252 TSHttpTxnUntransformedRespCache(TSHttpTxn txnp, int on)
6253 {
6254   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6255 
6256   HttpSM *sm                               = (HttpSM *)txnp;
6257   sm->t_state.api_info.cache_untransformed = (on ? true : false);
6258 }
6259 
6260 void
TSHttpTxnTransformedRespCache(TSHttpTxn txnp,int on)6261 TSHttpTxnTransformedRespCache(TSHttpTxn txnp, int on)
6262 {
6263   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6264 
6265   HttpSM *sm                             = (HttpSM *)txnp;
6266   sm->t_state.api_info.cache_transformed = (on ? true : false);
6267 }
6268 
6269 class TSHttpSMCallback : public Continuation
6270 {
6271 public:
TSHttpSMCallback(HttpSM * sm,TSEvent event)6272   TSHttpSMCallback(HttpSM *sm, TSEvent event) : Continuation(sm->mutex), m_sm(sm), m_event(event)
6273   {
6274     SET_HANDLER(&TSHttpSMCallback::event_handler);
6275   }
6276 
6277   int
event_handler(int,void *)6278   event_handler(int, void *)
6279   {
6280     m_sm->state_api_callback((int)m_event, nullptr);
6281     delete this;
6282     return 0;
6283   }
6284 
6285 private:
6286   HttpSM *m_sm;
6287   TSEvent m_event;
6288 };
6289 
6290 //----------------------------------------------------------------------------
6291 void
TSHttpTxnReenable(TSHttpTxn txnp,TSEvent event)6292 TSHttpTxnReenable(TSHttpTxn txnp, TSEvent event)
6293 {
6294   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6295 
6296   HttpSM *sm   = (HttpSM *)txnp;
6297   EThread *eth = this_ethread();
6298 
6299   // TS-2271: If this function is being executed on a thread which was not
6300   // created using the ATS EThread API, eth will be NULL, and the
6301   // continuation needs to be called back on a REGULAR thread.
6302   //
6303   // If we are not coming from the thread associated with the state machine,
6304   // reschedule.  Also reschedule if we cannot get the state machine lock.
6305   if (eth != nullptr && sm->getThreadAffinity() == eth) {
6306     MUTEX_TRY_LOCK(trylock, sm->mutex, eth);
6307     if (trylock.is_locked()) {
6308       ink_assert(eth->is_event_type(ET_NET));
6309       sm->state_api_callback((int)event, nullptr);
6310       return;
6311     }
6312   }
6313   // Couldn't call the handler directly, schedule to the original SM thread
6314   TSHttpSMCallback *cb = new TSHttpSMCallback(sm, event);
6315   cb->setThreadAffinity(sm->getThreadAffinity());
6316   eventProcessor.schedule_imm(cb, ET_NET);
6317 }
6318 
6319 TSReturnCode TSUserArgIndexNameLookup(TSUserArgType type, const char *name, int *arg_idx, const char **description);
6320 
6321 TSReturnCode
TSUserArgIndexReserve(TSUserArgType type,const char * name,const char * description,int * ptr_idx)6322 TSUserArgIndexReserve(TSUserArgType type, const char *name, const char *description, int *ptr_idx)
6323 {
6324   sdk_assert(sdk_sanity_check_null_ptr(ptr_idx) == TS_SUCCESS);
6325   sdk_assert(sdk_sanity_check_null_ptr(name) == TS_SUCCESS);
6326   sdk_assert(0 <= type && type < TS_USER_ARGS_COUNT);
6327 
6328   int idx;
6329 
6330   /* Since this function is meant to be called during plugin initialization we could end up "leaking" indices during plugins reload.
6331    * Make sure we allocate 1 index per name, also current TSUserArgIndexNameLookup() implementation assumes 1-1 relationship as
6332    * well. */
6333   const char *desc;
6334 
6335   if (TS_SUCCESS == TSUserArgIndexNameLookup(type, name, &idx, &desc)) {
6336     // Found existing index.
6337     *ptr_idx = idx;
6338     return TS_SUCCESS;
6339   }
6340 
6341   idx       = UserArgIdx[type]++;
6342   int limit = MAX_USER_ARGS[type];
6343 
6344   if (idx < limit) {
6345     UserArg &arg(UserArgTable[type][idx]);
6346     arg.name = name;
6347     if (description) {
6348       arg.description = description;
6349     }
6350     *ptr_idx = idx;
6351 
6352     return TS_SUCCESS;
6353   }
6354   return TS_ERROR;
6355 }
6356 
6357 TSReturnCode
TSUserArgIndexLookup(TSUserArgType type,int idx,const char ** name,const char ** description)6358 TSUserArgIndexLookup(TSUserArgType type, int idx, const char **name, const char **description)
6359 {
6360   sdk_assert(0 <= type && type < TS_USER_ARGS_COUNT);
6361   if (sdk_sanity_check_null_ptr(name) == TS_SUCCESS) {
6362     if (idx < UserArgIdx[type]) {
6363       UserArg &arg(UserArgTable[type][idx]);
6364       *name = arg.name.c_str();
6365       if (description) {
6366         *description = arg.description.c_str();
6367       }
6368       return TS_SUCCESS;
6369     }
6370   }
6371   return TS_ERROR;
6372 }
6373 
6374 // Not particularly efficient, but good enough for now.
6375 TSReturnCode
TSUserArgIndexNameLookup(TSUserArgType type,const char * name,int * arg_idx,const char ** description)6376 TSUserArgIndexNameLookup(TSUserArgType type, const char *name, int *arg_idx, const char **description)
6377 {
6378   sdk_assert(sdk_sanity_check_null_ptr(arg_idx) == TS_SUCCESS);
6379   sdk_assert(0 <= type && type < TS_USER_ARGS_COUNT);
6380 
6381   std::string_view n{name};
6382 
6383   for (UserArg *arg = UserArgTable[type], *limit = arg + UserArgIdx[type]; arg < limit; ++arg) {
6384     if (arg->name == n) {
6385       if (description) {
6386         *description = arg->description.c_str();
6387       }
6388       *arg_idx = arg - UserArgTable[type];
6389       return TS_SUCCESS;
6390     }
6391   }
6392   return TS_ERROR;
6393 }
6394 
6395 // -------------
6396 void
TSUserArgSet(void * data,int arg_idx,void * arg)6397 TSUserArgSet(void *data, int arg_idx, void *arg)
6398 {
6399   if (nullptr != data) {
6400     PluginUserArgsMixin *user_args = dynamic_cast<PluginUserArgsMixin *>(static_cast<Continuation *>(data));
6401     sdk_assert(user_args);
6402 
6403     user_args->set_user_arg(arg_idx, arg);
6404   } else {
6405     global_user_args.set_user_arg(arg_idx, arg);
6406   }
6407 }
6408 
6409 void *
TSUserArgGet(void * data,int arg_idx)6410 TSUserArgGet(void *data, int arg_idx)
6411 {
6412   if (nullptr != data) {
6413     PluginUserArgsMixin *user_args = dynamic_cast<PluginUserArgsMixin *>(static_cast<Continuation *>(data));
6414     sdk_assert(user_args);
6415 
6416     return user_args->get_user_arg(arg_idx);
6417   } else {
6418     return global_user_args.get_user_arg(arg_idx);
6419   }
6420 }
6421 
6422 // -------------
6423 TSReturnCode
TSHttpTxnArgIndexReserve(const char * name,const char * description,int * arg_idx)6424 TSHttpTxnArgIndexReserve(const char *name, const char *description, int *arg_idx)
6425 {
6426   return TSUserArgIndexReserve(TS_USER_ARGS_TXN, name, description, arg_idx);
6427 }
6428 
6429 TSReturnCode
TSHttpTxnArgIndexLookup(int arg_idx,const char ** name,const char ** description)6430 TSHttpTxnArgIndexLookup(int arg_idx, const char **name, const char **description)
6431 {
6432   return TSUserArgIndexLookup(TS_USER_ARGS_TXN, arg_idx, name, description);
6433 }
6434 
6435 TSReturnCode
TSHttpTxnArgIndexNameLookup(const char * name,int * arg_idx,const char ** description)6436 TSHttpTxnArgIndexNameLookup(const char *name, int *arg_idx, const char **description)
6437 {
6438   return TSUserArgIndexNameLookup(TS_USER_ARGS_TXN, name, arg_idx, description);
6439 }
6440 
6441 TSReturnCode
TSHttpSsnArgIndexReserve(const char * name,const char * description,int * arg_idx)6442 TSHttpSsnArgIndexReserve(const char *name, const char *description, int *arg_idx)
6443 {
6444   return TSUserArgIndexReserve(TS_USER_ARGS_SSN, name, description, arg_idx);
6445 }
6446 
6447 TSReturnCode
TSHttpSsnArgIndexLookup(int arg_idx,const char ** name,const char ** description)6448 TSHttpSsnArgIndexLookup(int arg_idx, const char **name, const char **description)
6449 {
6450   return TSUserArgIndexLookup(TS_USER_ARGS_SSN, arg_idx, name, description);
6451 }
6452 
6453 TSReturnCode
TSHttpSsnArgIndexNameLookup(const char * name,int * arg_idx,const char ** description)6454 TSHttpSsnArgIndexNameLookup(const char *name, int *arg_idx, const char **description)
6455 {
6456   return TSUserArgIndexNameLookup(TS_USER_ARGS_SSN, name, arg_idx, description);
6457 }
6458 
6459 TSReturnCode
TSVConnArgIndexReserve(const char * name,const char * description,int * arg_idx)6460 TSVConnArgIndexReserve(const char *name, const char *description, int *arg_idx)
6461 {
6462   return TSUserArgIndexReserve(TS_USER_ARGS_VCONN, name, description, arg_idx);
6463 }
6464 
6465 TSReturnCode
TSVConnArgIndexLookup(int arg_idx,const char ** name,const char ** description)6466 TSVConnArgIndexLookup(int arg_idx, const char **name, const char **description)
6467 {
6468   return TSUserArgIndexLookup(TS_USER_ARGS_VCONN, arg_idx, name, description);
6469 }
6470 
6471 TSReturnCode
TSVConnArgIndexNameLookup(const char * name,int * arg_idx,const char ** description)6472 TSVConnArgIndexNameLookup(const char *name, int *arg_idx, const char **description)
6473 {
6474   return TSUserArgIndexNameLookup(TS_USER_ARGS_VCONN, name, arg_idx, description);
6475 }
6476 
6477 void
TSHttpTxnArgSet(TSHttpTxn txnp,int arg_idx,void * arg)6478 TSHttpTxnArgSet(TSHttpTxn txnp, int arg_idx, void *arg)
6479 {
6480   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6481   sdk_assert(arg_idx >= 0 && static_cast<size_t>(arg_idx) < MAX_USER_ARGS[TS_USER_ARGS_TXN]);
6482 
6483   HttpSM *sm = reinterpret_cast<HttpSM *>(txnp);
6484 
6485   sm->set_user_arg(arg_idx, arg);
6486 }
6487 
6488 void *
TSHttpTxnArgGet(TSHttpTxn txnp,int arg_idx)6489 TSHttpTxnArgGet(TSHttpTxn txnp, int arg_idx)
6490 {
6491   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6492   sdk_assert(arg_idx >= 0 && static_cast<size_t>(arg_idx) < MAX_USER_ARGS[TS_USER_ARGS_TXN]);
6493 
6494   HttpSM *sm = reinterpret_cast<HttpSM *>(txnp);
6495   return sm->get_user_arg(arg_idx);
6496 }
6497 
6498 void
TSHttpSsnArgSet(TSHttpSsn ssnp,int arg_idx,void * arg)6499 TSHttpSsnArgSet(TSHttpSsn ssnp, int arg_idx, void *arg)
6500 {
6501   sdk_assert(sdk_sanity_check_http_ssn(ssnp) == TS_SUCCESS);
6502   sdk_assert(arg_idx >= 0 && static_cast<size_t>(arg_idx) < MAX_USER_ARGS[TS_USER_ARGS_SSN]);
6503 
6504   ProxySession *cs = reinterpret_cast<ProxySession *>(ssnp);
6505 
6506   cs->set_user_arg(arg_idx, arg);
6507 }
6508 
6509 void *
TSHttpSsnArgGet(TSHttpSsn ssnp,int arg_idx)6510 TSHttpSsnArgGet(TSHttpSsn ssnp, int arg_idx)
6511 {
6512   sdk_assert(sdk_sanity_check_http_ssn(ssnp) == TS_SUCCESS);
6513   sdk_assert(arg_idx >= 0 && static_cast<size_t>(arg_idx) < MAX_USER_ARGS[TS_USER_ARGS_SSN]);
6514 
6515   ProxySession *cs = reinterpret_cast<ProxySession *>(ssnp);
6516   return cs->get_user_arg(arg_idx);
6517 }
6518 
6519 void
TSVConnArgSet(TSVConn connp,int arg_idx,void * arg)6520 TSVConnArgSet(TSVConn connp, int arg_idx, void *arg)
6521 {
6522   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
6523   sdk_assert(arg_idx >= 0 && static_cast<size_t>(arg_idx) < MAX_USER_ARGS[TS_USER_ARGS_VCONN]);
6524   PluginUserArgsMixin *user_args = dynamic_cast<PluginUserArgsMixin *>(reinterpret_cast<VConnection *>(connp));
6525   sdk_assert(user_args);
6526 
6527   user_args->set_user_arg(arg_idx, arg);
6528 }
6529 
6530 void *
TSVConnArgGet(TSVConn connp,int arg_idx)6531 TSVConnArgGet(TSVConn connp, int arg_idx)
6532 {
6533   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
6534   sdk_assert(arg_idx >= 0 && static_cast<size_t>(arg_idx) < MAX_USER_ARGS[TS_USER_ARGS_VCONN]);
6535   PluginUserArgsMixin *user_args = dynamic_cast<PluginUserArgsMixin *>(reinterpret_cast<VConnection *>(connp));
6536   sdk_assert(user_args);
6537 
6538   return user_args->get_user_arg(arg_idx);
6539 }
6540 
6541 void
TSHttpTxnStatusSet(TSHttpTxn txnp,TSHttpStatus status)6542 TSHttpTxnStatusSet(TSHttpTxn txnp, TSHttpStatus status)
6543 {
6544   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6545 
6546   HttpSM *sm                   = reinterpret_cast<HttpSM *>(txnp);
6547   sm->t_state.http_return_code = static_cast<HTTPStatus>(status);
6548 }
6549 
6550 TSHttpStatus
TSHttpTxnStatusGet(TSHttpTxn txnp)6551 TSHttpTxnStatusGet(TSHttpTxn txnp)
6552 {
6553   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6554 
6555   HttpSM *sm = reinterpret_cast<HttpSM *>(txnp);
6556   return static_cast<TSHttpStatus>(sm->t_state.http_return_code);
6557 }
6558 
6559 /* control channel for HTTP */
6560 TSReturnCode
TSHttpTxnCntl(TSHttpTxn txnp,TSHttpCntlType cntl,void * data)6561 TSHttpTxnCntl(TSHttpTxn txnp, TSHttpCntlType cntl, void *data)
6562 {
6563   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6564 
6565   HttpSM *sm = (HttpSM *)txnp;
6566 
6567   switch (cntl) {
6568   case TS_HTTP_CNTL_GET_LOGGING_MODE: {
6569     if (data == nullptr) {
6570       return TS_ERROR;
6571     }
6572 
6573     intptr_t *rptr = static_cast<intptr_t *>(data);
6574 
6575     if (sm->t_state.api_info.logging_enabled) {
6576       *rptr = (intptr_t)TS_HTTP_CNTL_ON;
6577     } else {
6578       *rptr = (intptr_t)TS_HTTP_CNTL_OFF;
6579     }
6580 
6581     return TS_SUCCESS;
6582   }
6583 
6584   case TS_HTTP_CNTL_SET_LOGGING_MODE:
6585     if (data != TS_HTTP_CNTL_ON && data != TS_HTTP_CNTL_OFF) {
6586       return TS_ERROR;
6587     } else {
6588       sm->t_state.api_info.logging_enabled = (bool)data;
6589       return TS_SUCCESS;
6590     }
6591     break;
6592 
6593   case TS_HTTP_CNTL_GET_INTERCEPT_RETRY_MODE: {
6594     if (data == nullptr) {
6595       return TS_ERROR;
6596     }
6597 
6598     intptr_t *rptr = static_cast<intptr_t *>(data);
6599 
6600     if (sm->t_state.api_info.retry_intercept_failures) {
6601       *rptr = (intptr_t)TS_HTTP_CNTL_ON;
6602     } else {
6603       *rptr = (intptr_t)TS_HTTP_CNTL_OFF;
6604     }
6605 
6606     return TS_SUCCESS;
6607   }
6608 
6609   case TS_HTTP_CNTL_SET_INTERCEPT_RETRY_MODE:
6610     if (data != TS_HTTP_CNTL_ON && data != TS_HTTP_CNTL_OFF) {
6611       return TS_ERROR;
6612     } else {
6613       sm->t_state.api_info.retry_intercept_failures = (bool)data;
6614       return TS_SUCCESS;
6615     }
6616   default:
6617     return TS_ERROR;
6618   }
6619 
6620   return TS_ERROR;
6621 }
6622 
6623 /* This is kinda horky, we have to use TSServerState instead of
6624    HttpTransact::ServerState_t, otherwise we have a prototype
6625    mismatch in the public ts/ts.h interfaces. */
6626 TSServerState
TSHttpTxnServerStateGet(TSHttpTxn txnp)6627 TSHttpTxnServerStateGet(TSHttpTxn txnp)
6628 {
6629   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6630 
6631   HttpTransact::State *s = &(((HttpSM *)txnp)->t_state);
6632   return (TSServerState)s->current.state;
6633 }
6634 
6635 void
TSHttpTxnDebugSet(TSHttpTxn txnp,int on)6636 TSHttpTxnDebugSet(TSHttpTxn txnp, int on)
6637 {
6638   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6639   ((HttpSM *)txnp)->debug_on = on;
6640 }
6641 
6642 int
TSHttpTxnDebugGet(TSHttpTxn txnp)6643 TSHttpTxnDebugGet(TSHttpTxn txnp)
6644 {
6645   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6646   return ((HttpSM *)txnp)->debug_on;
6647 }
6648 
6649 void
TSHttpSsnDebugSet(TSHttpSsn ssnp,int on)6650 TSHttpSsnDebugSet(TSHttpSsn ssnp, int on)
6651 {
6652   sdk_assert(sdk_sanity_check_http_ssn(ssnp) == TS_SUCCESS);
6653   (reinterpret_cast<ProxySession *>(ssnp))->set_debug(0 != on);
6654 }
6655 
6656 int
TSHttpSsnDebugGet(TSHttpSsn ssnp)6657 TSHttpSsnDebugGet(TSHttpSsn ssnp)
6658 {
6659   sdk_assert(sdk_sanity_check_http_ssn(ssnp) == TS_SUCCESS);
6660   return (reinterpret_cast<ProxySession *>(ssnp))->debug();
6661 }
6662 
6663 int
TSHttpTxnClientReqHdrBytesGet(TSHttpTxn txnp)6664 TSHttpTxnClientReqHdrBytesGet(TSHttpTxn txnp)
6665 {
6666   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6667 
6668   HttpSM *sm = (HttpSM *)txnp;
6669   return sm->client_request_hdr_bytes;
6670 }
6671 
6672 int64_t
TSHttpTxnClientReqBodyBytesGet(TSHttpTxn txnp)6673 TSHttpTxnClientReqBodyBytesGet(TSHttpTxn txnp)
6674 {
6675   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6676 
6677   HttpSM *sm = (HttpSM *)txnp;
6678   return sm->client_request_body_bytes;
6679 }
6680 
6681 int
TSHttpTxnServerReqHdrBytesGet(TSHttpTxn txnp)6682 TSHttpTxnServerReqHdrBytesGet(TSHttpTxn txnp)
6683 {
6684   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6685 
6686   HttpSM *sm = (HttpSM *)txnp;
6687   return sm->server_request_hdr_bytes;
6688 }
6689 
6690 int64_t
TSHttpTxnServerReqBodyBytesGet(TSHttpTxn txnp)6691 TSHttpTxnServerReqBodyBytesGet(TSHttpTxn txnp)
6692 {
6693   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6694 
6695   HttpSM *sm = (HttpSM *)txnp;
6696   return sm->server_request_body_bytes;
6697 }
6698 
6699 int
TSHttpTxnServerRespHdrBytesGet(TSHttpTxn txnp)6700 TSHttpTxnServerRespHdrBytesGet(TSHttpTxn txnp)
6701 {
6702   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6703 
6704   HttpSM *sm = (HttpSM *)txnp;
6705   return sm->server_response_hdr_bytes;
6706 }
6707 
6708 int64_t
TSHttpTxnServerRespBodyBytesGet(TSHttpTxn txnp)6709 TSHttpTxnServerRespBodyBytesGet(TSHttpTxn txnp)
6710 {
6711   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6712 
6713   HttpSM *sm = (HttpSM *)txnp;
6714   return sm->server_response_body_bytes;
6715 }
6716 
6717 int
TSHttpTxnClientRespHdrBytesGet(TSHttpTxn txnp)6718 TSHttpTxnClientRespHdrBytesGet(TSHttpTxn txnp)
6719 {
6720   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6721 
6722   HttpSM *sm = (HttpSM *)txnp;
6723   return sm->client_response_hdr_bytes;
6724 }
6725 
6726 int64_t
TSHttpTxnClientRespBodyBytesGet(TSHttpTxn txnp)6727 TSHttpTxnClientRespBodyBytesGet(TSHttpTxn txnp)
6728 {
6729   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6730 
6731   HttpSM *sm = (HttpSM *)txnp;
6732   return sm->client_response_body_bytes;
6733 }
6734 
6735 int
TSVConnIsSslReused(TSVConn sslp)6736 TSVConnIsSslReused(TSVConn sslp)
6737 {
6738   NetVConnection *vc        = reinterpret_cast<NetVConnection *>(sslp);
6739   SSLNetVConnection *ssl_vc = dynamic_cast<SSLNetVConnection *>(vc);
6740 
6741   return ssl_vc ? ssl_vc->getSSLSessionCacheHit() : 0;
6742 }
6743 
6744 const char *
TSVConnSslCipherGet(TSVConn sslp)6745 TSVConnSslCipherGet(TSVConn sslp)
6746 {
6747   NetVConnection *vc        = reinterpret_cast<NetVConnection *>(sslp);
6748   SSLNetVConnection *ssl_vc = dynamic_cast<SSLNetVConnection *>(vc);
6749 
6750   return ssl_vc ? ssl_vc->getSSLCipherSuite() : nullptr;
6751 }
6752 
6753 const char *
TSVConnSslProtocolGet(TSVConn sslp)6754 TSVConnSslProtocolGet(TSVConn sslp)
6755 {
6756   NetVConnection *vc        = reinterpret_cast<NetVConnection *>(sslp);
6757   SSLNetVConnection *ssl_vc = dynamic_cast<SSLNetVConnection *>(vc);
6758 
6759   return ssl_vc ? ssl_vc->getSSLProtocol() : nullptr;
6760 }
6761 
6762 const char *
TSVConnSslCurveGet(TSVConn sslp)6763 TSVConnSslCurveGet(TSVConn sslp)
6764 {
6765   NetVConnection *vc        = reinterpret_cast<NetVConnection *>(sslp);
6766   SSLNetVConnection *ssl_vc = dynamic_cast<SSLNetVConnection *>(vc);
6767 
6768   return ssl_vc ? ssl_vc->getSSLCurve() : nullptr;
6769 }
6770 
6771 int
TSHttpTxnPushedRespHdrBytesGet(TSHttpTxn txnp)6772 TSHttpTxnPushedRespHdrBytesGet(TSHttpTxn txnp)
6773 {
6774   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6775 
6776   HttpSM *sm = (HttpSM *)txnp;
6777   return sm->pushed_response_hdr_bytes;
6778 }
6779 
6780 int64_t
TSHttpTxnPushedRespBodyBytesGet(TSHttpTxn txnp)6781 TSHttpTxnPushedRespBodyBytesGet(TSHttpTxn txnp)
6782 {
6783   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6784 
6785   HttpSM *sm = (HttpSM *)txnp;
6786   return sm->pushed_response_body_bytes;
6787 }
6788 
6789 // Get a particular milestone hrtime'r. Note that this can return 0, which means it has not
6790 // been set yet.
6791 TSReturnCode
TSHttpTxnMilestoneGet(TSHttpTxn txnp,TSMilestonesType milestone,ink_hrtime * time)6792 TSHttpTxnMilestoneGet(TSHttpTxn txnp, TSMilestonesType milestone, ink_hrtime *time)
6793 {
6794   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6795   sdk_assert(sdk_sanity_check_null_ptr(time) == TS_SUCCESS);
6796   HttpSM *sm       = (HttpSM *)txnp;
6797   TSReturnCode ret = TS_SUCCESS;
6798 
6799   if ((milestone < TS_MILESTONE_UA_BEGIN) || (milestone >= TS_MILESTONE_LAST_ENTRY)) {
6800     *time = -1;
6801     ret   = TS_ERROR;
6802   } else {
6803     *time = sm->milestones[milestone];
6804   }
6805 
6806   return ret;
6807 }
6808 
6809 TSReturnCode
TSHttpTxnCachedRespTimeGet(TSHttpTxn txnp,time_t * resp_time)6810 TSHttpTxnCachedRespTimeGet(TSHttpTxn txnp, time_t *resp_time)
6811 {
6812   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6813 
6814   HttpSM *sm           = (HttpSM *)txnp;
6815   HTTPInfo *cached_obj = sm->t_state.cache_info.object_read;
6816 
6817   if (cached_obj == nullptr || !cached_obj->valid()) {
6818     return TS_ERROR;
6819   }
6820 
6821   *resp_time = cached_obj->response_received_time_get();
6822   return TS_SUCCESS;
6823 }
6824 
6825 int
TSHttpTxnLookingUpTypeGet(TSHttpTxn txnp)6826 TSHttpTxnLookingUpTypeGet(TSHttpTxn txnp)
6827 {
6828   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6829 
6830   HttpSM *sm             = (HttpSM *)txnp;
6831   HttpTransact::State *s = &(sm->t_state);
6832 
6833   return (int)(s->current.request_to);
6834 }
6835 
6836 int
TSHttpCurrentClientConnectionsGet()6837 TSHttpCurrentClientConnectionsGet()
6838 {
6839   int64_t S;
6840 
6841   HTTP_READ_DYN_SUM(http_current_client_connections_stat, S);
6842   return static_cast<int>(S);
6843 }
6844 
6845 int
TSHttpCurrentActiveClientConnectionsGet()6846 TSHttpCurrentActiveClientConnectionsGet()
6847 {
6848   int64_t S;
6849 
6850   HTTP_READ_DYN_SUM(http_current_active_client_connections_stat, S);
6851   return static_cast<int>(S);
6852 }
6853 
6854 int
TSHttpCurrentIdleClientConnectionsGet()6855 TSHttpCurrentIdleClientConnectionsGet()
6856 {
6857   int64_t total  = 0;
6858   int64_t active = 0;
6859 
6860   HTTP_READ_DYN_SUM(http_current_client_connections_stat, total);
6861   HTTP_READ_DYN_SUM(http_current_active_client_connections_stat, active);
6862 
6863   if (total >= active) {
6864     return static_cast<int>(total - active);
6865   }
6866 
6867   return 0;
6868 }
6869 
6870 int
TSHttpCurrentCacheConnectionsGet()6871 TSHttpCurrentCacheConnectionsGet()
6872 {
6873   int64_t S;
6874 
6875   HTTP_READ_DYN_SUM(http_current_cache_connections_stat, S);
6876   return static_cast<int>(S);
6877 }
6878 
6879 int
TSHttpCurrentServerConnectionsGet()6880 TSHttpCurrentServerConnectionsGet()
6881 {
6882   int64_t S;
6883 
6884   HTTP_READ_GLOBAL_DYN_SUM(http_current_server_connections_stat, S);
6885   return static_cast<int>(S);
6886 }
6887 
6888 /* HTTP alternate selection */
6889 TSReturnCode
TSHttpAltInfoClientReqGet(TSHttpAltInfo infop,TSMBuffer * bufp,TSMLoc * obj)6890 TSHttpAltInfoClientReqGet(TSHttpAltInfo infop, TSMBuffer *bufp, TSMLoc *obj)
6891 {
6892   sdk_assert(sdk_sanity_check_alt_info(infop) == TS_SUCCESS);
6893 
6894   HttpAltInfo *info = (HttpAltInfo *)infop;
6895 
6896   *(reinterpret_cast<HTTPHdr **>(bufp)) = &info->m_client_req;
6897   *obj                                  = reinterpret_cast<TSMLoc>(info->m_client_req.m_http);
6898 
6899   return sdk_sanity_check_mbuffer(*bufp);
6900 }
6901 
6902 TSReturnCode
TSHttpAltInfoCachedReqGet(TSHttpAltInfo infop,TSMBuffer * bufp,TSMLoc * obj)6903 TSHttpAltInfoCachedReqGet(TSHttpAltInfo infop, TSMBuffer *bufp, TSMLoc *obj)
6904 {
6905   sdk_assert(sdk_sanity_check_alt_info(infop) == TS_SUCCESS);
6906 
6907   HttpAltInfo *info = (HttpAltInfo *)infop;
6908 
6909   *(reinterpret_cast<HTTPHdr **>(bufp)) = &info->m_cached_req;
6910   *obj                                  = reinterpret_cast<TSMLoc>(info->m_cached_req.m_http);
6911 
6912   return sdk_sanity_check_mbuffer(*bufp);
6913 }
6914 
6915 TSReturnCode
TSHttpAltInfoCachedRespGet(TSHttpAltInfo infop,TSMBuffer * bufp,TSMLoc * obj)6916 TSHttpAltInfoCachedRespGet(TSHttpAltInfo infop, TSMBuffer *bufp, TSMLoc *obj)
6917 {
6918   sdk_assert(sdk_sanity_check_alt_info(infop) == TS_SUCCESS);
6919 
6920   HttpAltInfo *info = (HttpAltInfo *)infop;
6921 
6922   *(reinterpret_cast<HTTPHdr **>(bufp)) = &info->m_cached_resp;
6923   *obj                                  = reinterpret_cast<TSMLoc>(info->m_cached_resp.m_http);
6924 
6925   return sdk_sanity_check_mbuffer(*bufp);
6926 }
6927 
6928 void
TSHttpAltInfoQualitySet(TSHttpAltInfo infop,float quality)6929 TSHttpAltInfoQualitySet(TSHttpAltInfo infop, float quality)
6930 {
6931   sdk_assert(sdk_sanity_check_alt_info(infop) == TS_SUCCESS);
6932 
6933   HttpAltInfo *info = (HttpAltInfo *)infop;
6934   info->m_qvalue    = quality;
6935 }
6936 
6937 extern HttpSessionAccept *plugin_http_accept;
6938 extern HttpSessionAccept *plugin_http_transparent_accept;
6939 
6940 const char *
TSHttpTxnPluginTagGet(TSHttpTxn txnp)6941 TSHttpTxnPluginTagGet(TSHttpTxn txnp)
6942 {
6943   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
6944 
6945   HttpSM *sm = reinterpret_cast<HttpSM *>(txnp);
6946   return sm->plugin_tag;
6947 }
6948 
6949 TSVConn
TSHttpConnectWithPluginId(sockaddr const * addr,const char * tag,int64_t id)6950 TSHttpConnectWithPluginId(sockaddr const *addr, const char *tag, int64_t id)
6951 {
6952   sdk_assert(addr);
6953 
6954   sdk_assert(ats_is_ip(addr));
6955   sdk_assert(ats_ip_port_cast(addr));
6956 
6957   if (plugin_http_accept) {
6958     PluginVCCore *new_pvc = PluginVCCore::alloc(plugin_http_accept);
6959 
6960     new_pvc->set_active_addr(addr);
6961     new_pvc->set_plugin_id(id);
6962     new_pvc->set_plugin_tag(tag);
6963 
6964     PluginVC *return_vc = new_pvc->connect();
6965 
6966     if (return_vc != nullptr) {
6967       PluginVC *other_side = return_vc->get_other_side();
6968 
6969       if (other_side != nullptr) {
6970         other_side->set_is_internal_request(true);
6971       }
6972     }
6973 
6974     return reinterpret_cast<TSVConn>(return_vc);
6975   }
6976 
6977   return nullptr;
6978 }
6979 
6980 TSVConn
TSHttpConnect(sockaddr const * addr)6981 TSHttpConnect(sockaddr const *addr)
6982 {
6983   return TSHttpConnectWithPluginId(addr, "plugin", 0);
6984 }
6985 
6986 TSVConn
TSHttpConnectTransparent(sockaddr const * client_addr,sockaddr const * server_addr)6987 TSHttpConnectTransparent(sockaddr const *client_addr, sockaddr const *server_addr)
6988 {
6989   sdk_assert(ats_is_ip(client_addr));
6990   sdk_assert(ats_is_ip(server_addr));
6991   sdk_assert(!ats_is_ip_any(client_addr));
6992   sdk_assert(ats_ip_port_cast(client_addr));
6993   sdk_assert(!ats_is_ip_any(server_addr));
6994   sdk_assert(ats_ip_port_cast(server_addr));
6995 
6996   if (plugin_http_transparent_accept) {
6997     PluginVCCore *new_pvc = PluginVCCore::alloc(plugin_http_transparent_accept);
6998 
6999     // set active address expects host ordering and the above casts do not
7000     // swap when it is required
7001     new_pvc->set_active_addr(client_addr);
7002     new_pvc->set_passive_addr(server_addr);
7003     new_pvc->set_transparent(true, true);
7004 
7005     PluginVC *return_vc = new_pvc->connect();
7006 
7007     if (return_vc != nullptr) {
7008       PluginVC *other_side = return_vc->get_other_side();
7009 
7010       if (other_side != nullptr) {
7011         other_side->set_is_internal_request(true);
7012       }
7013     }
7014 
7015     return reinterpret_cast<TSVConn>(return_vc);
7016   }
7017 
7018   return nullptr;
7019 }
7020 
7021 /* Actions */
7022 void
TSActionCancel(TSAction actionp)7023 TSActionCancel(TSAction actionp)
7024 {
7025   Action *thisaction;
7026   INKContInternal *i;
7027 
7028   // Nothing to cancel
7029   if (actionp == nullptr) {
7030     return;
7031   }
7032 
7033   /* This is a hack. Should be handled in ink_types */
7034   if ((uintptr_t)actionp & 0x1) {
7035     thisaction = (Action *)((uintptr_t)actionp - 1);
7036     if (thisaction) {
7037       i = (INKContInternal *)thisaction->continuation;
7038       i->handle_event_count(EVENT_IMMEDIATE);
7039     } else { // The action pointer for an INKContInternal was effectively null, just go away
7040       return;
7041     }
7042   } else {
7043     thisaction = (Action *)actionp;
7044   }
7045 
7046   thisaction->cancel();
7047 }
7048 
7049 // Currently no error handling necessary, actionp can be anything.
7050 int
TSActionDone(TSAction actionp)7051 TSActionDone(TSAction actionp)
7052 {
7053   return ((Action *)actionp == ACTION_RESULT_DONE) ? 1 : 0;
7054 }
7055 
7056 /* Connections */
7057 
7058 TSVConn
TSVConnCreate(TSEventFunc event_funcp,TSMutex mutexp)7059 TSVConnCreate(TSEventFunc event_funcp, TSMutex mutexp)
7060 {
7061   if (mutexp == nullptr) {
7062     mutexp = (TSMutex)new_ProxyMutex();
7063   }
7064 
7065   // TODO: probably don't need this if memory allocations fails properly
7066   sdk_assert(sdk_sanity_check_mutex(mutexp) == TS_SUCCESS);
7067 
7068   if (pluginThreadContext) {
7069     pluginThreadContext->acquire();
7070   }
7071 
7072   INKVConnInternal *i = THREAD_ALLOC(INKVConnAllocator, this_thread());
7073 
7074   sdk_assert(sdk_sanity_check_null_ptr((void *)i) == TS_SUCCESS);
7075 
7076   i->init(event_funcp, mutexp, pluginThreadContext);
7077   return reinterpret_cast<TSVConn>(i);
7078 }
7079 
7080 struct ActionSink : public Continuation {
ActionSinkActionSink7081   ActionSink() : Continuation(nullptr) { SET_HANDLER(&ActionSink::mainEvent); }
7082   int
mainEventActionSink7083   mainEvent(int event, void *edata)
7084   {
7085     // Just sink the event ...
7086     Debug("iocore_net", "sinking event=%d (%s), edata=%p", event, HttpDebugNames::get_event_name(event), edata);
7087     return EVENT_CONT;
7088   }
7089 };
7090 
7091 static ActionSink a;
7092 
7093 TSVConn
TSVConnFdCreate(int fd)7094 TSVConnFdCreate(int fd)
7095 {
7096   UnixNetVConnection *vc;
7097   EThread *t = this_ethread();
7098 
7099   if (unlikely(fd == NO_FD)) {
7100     return nullptr;
7101   }
7102 
7103   vc = (UnixNetVConnection *)netProcessor.allocate_vc(t);
7104   if (vc == nullptr) {
7105     return nullptr;
7106   }
7107 
7108   // We need to set an Action to handle NET_EVENT_OPEN* events. Since we have a
7109   // socket already, we don't need to do anything in those events, so we can just
7110   // sink them. It's better to sink them here, than to make the NetVC code more
7111   // complex.
7112   vc->action_ = &a;
7113 
7114   vc->id          = net_next_connection_number();
7115   vc->submit_time = Thread::get_hrtime();
7116   vc->mutex       = new_ProxyMutex();
7117   vc->set_is_transparent(false);
7118   vc->set_context(NET_VCONNECTION_OUT);
7119 
7120   // We should take the nh's lock and vc's lock before we get into the connectUp
7121   SCOPED_MUTEX_LOCK(lock, get_NetHandler(t)->mutex, t);
7122   SCOPED_MUTEX_LOCK(lock2, vc->mutex, t);
7123 
7124   if (vc->connectUp(t, fd) != CONNECT_SUCCESS) {
7125     return nullptr;
7126   }
7127 
7128   return reinterpret_cast<TSVConn>(vc);
7129 }
7130 
7131 TSVIO
TSVConnReadVIOGet(TSVConn connp)7132 TSVConnReadVIOGet(TSVConn connp)
7133 {
7134   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
7135 
7136   VConnection *vc = (VConnection *)connp;
7137   TSVIO data;
7138 
7139   if (vc->get_data(TS_API_DATA_READ_VIO, &data)) {
7140     return data;
7141   }
7142 
7143   return nullptr;
7144 }
7145 
7146 TSVIO
TSVConnWriteVIOGet(TSVConn connp)7147 TSVConnWriteVIOGet(TSVConn connp)
7148 {
7149   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
7150 
7151   VConnection *vc = (VConnection *)connp;
7152   TSVIO data;
7153 
7154   if (vc->get_data(TS_API_DATA_WRITE_VIO, &data)) {
7155     return data;
7156   }
7157 
7158   return nullptr;
7159 }
7160 
7161 int
TSVConnClosedGet(TSVConn connp)7162 TSVConnClosedGet(TSVConn connp)
7163 {
7164   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
7165 
7166   VConnection *vc = (VConnection *)connp;
7167   int data        = 0;
7168   bool f          = vc->get_data(TS_API_DATA_CLOSED, &data);
7169   ink_assert(f); // This can fail in some cases, we need to track those down.
7170   return data;
7171 }
7172 
7173 TSVIO
TSVConnRead(TSVConn connp,TSCont contp,TSIOBuffer bufp,int64_t nbytes)7174 TSVConnRead(TSVConn connp, TSCont contp, TSIOBuffer bufp, int64_t nbytes)
7175 {
7176   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
7177   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
7178   sdk_assert(sdk_sanity_check_iocore_structure(bufp) == TS_SUCCESS);
7179   sdk_assert(nbytes >= 0);
7180 
7181   FORCE_PLUGIN_SCOPED_MUTEX(contp);
7182   VConnection *vc = (VConnection *)connp;
7183 
7184   return reinterpret_cast<TSVIO>(vc->do_io_read((INKContInternal *)contp, nbytes, (MIOBuffer *)bufp));
7185 }
7186 
7187 TSVIO
TSVConnWrite(TSVConn connp,TSCont contp,TSIOBufferReader readerp,int64_t nbytes)7188 TSVConnWrite(TSVConn connp, TSCont contp, TSIOBufferReader readerp, int64_t nbytes)
7189 {
7190   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
7191   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
7192   sdk_assert(sdk_sanity_check_iocore_structure(readerp) == TS_SUCCESS);
7193   sdk_assert(nbytes >= 0);
7194 
7195   FORCE_PLUGIN_SCOPED_MUTEX(contp);
7196   VConnection *vc = (VConnection *)connp;
7197 
7198   return reinterpret_cast<TSVIO>(vc->do_io_write((INKContInternal *)contp, nbytes, (IOBufferReader *)readerp));
7199 }
7200 
7201 void
TSVConnClose(TSVConn connp)7202 TSVConnClose(TSVConn connp)
7203 {
7204   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
7205 
7206   VConnection *vc = (VConnection *)connp;
7207   vc->do_io_close();
7208 }
7209 
7210 void
TSVConnAbort(TSVConn connp,int error)7211 TSVConnAbort(TSVConn connp, int error)
7212 {
7213   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
7214 
7215   VConnection *vc = (VConnection *)connp;
7216   vc->do_io_close(error);
7217 }
7218 
7219 void
TSVConnShutdown(TSVConn connp,int read,int write)7220 TSVConnShutdown(TSVConn connp, int read, int write)
7221 {
7222   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
7223 
7224   VConnection *vc = (VConnection *)connp;
7225 
7226   if (read && write) {
7227     vc->do_io_shutdown(IO_SHUTDOWN_READWRITE);
7228   } else if (read) {
7229     vc->do_io_shutdown(IO_SHUTDOWN_READ);
7230   } else if (write) {
7231     vc->do_io_shutdown(IO_SHUTDOWN_WRITE);
7232   }
7233 }
7234 
7235 int64_t
TSVConnCacheObjectSizeGet(TSVConn connp)7236 TSVConnCacheObjectSizeGet(TSVConn connp)
7237 {
7238   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
7239 
7240   CacheVC *vc = (CacheVC *)connp;
7241   return vc->get_object_size();
7242 }
7243 
7244 void
TSVConnCacheHttpInfoSet(TSVConn connp,TSCacheHttpInfo infop)7245 TSVConnCacheHttpInfoSet(TSVConn connp, TSCacheHttpInfo infop)
7246 {
7247   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
7248 
7249   CacheVC *vc = (CacheVC *)connp;
7250   if (vc->base_stat == cache_scan_active_stat) {
7251     vc->set_http_info((CacheHTTPInfo *)infop);
7252   }
7253 }
7254 
7255 /* Transformations */
7256 
7257 TSVConn
TSTransformCreate(TSEventFunc event_funcp,TSHttpTxn txnp)7258 TSTransformCreate(TSEventFunc event_funcp, TSHttpTxn txnp)
7259 {
7260   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
7261 
7262   return TSVConnCreate(event_funcp,
7263                        reinterpret_cast<TSMutex>(static_cast<Continuation *>(reinterpret_cast<HttpSM *>(txnp))->getMutex()));
7264 }
7265 
7266 TSVConn
TSTransformOutputVConnGet(TSVConn connp)7267 TSTransformOutputVConnGet(TSVConn connp)
7268 {
7269   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
7270 
7271   VConnection *vc = (VConnection *)connp;
7272   TSVConn data;
7273 
7274   vc->get_data(TS_API_DATA_OUTPUT_VC, &data); // This case can't fail.
7275   return data;
7276 }
7277 
7278 void
TSHttpTxnServerIntercept(TSCont contp,TSHttpTxn txnp)7279 TSHttpTxnServerIntercept(TSCont contp, TSHttpTxn txnp)
7280 {
7281   HttpSM *http_sm = (HttpSM *)txnp;
7282 
7283   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
7284   sdk_assert(sdk_sanity_check_continuation(contp) == TS_SUCCESS);
7285 
7286   http_sm->plugin_tunnel_type = HTTP_PLUGIN_AS_SERVER;
7287   http_sm->plugin_tunnel      = PluginVCCore::alloc((INKContInternal *)contp);
7288 }
7289 
7290 void
TSHttpTxnIntercept(TSCont contp,TSHttpTxn txnp)7291 TSHttpTxnIntercept(TSCont contp, TSHttpTxn txnp)
7292 {
7293   HttpSM *http_sm = (HttpSM *)txnp;
7294 
7295   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
7296   sdk_assert(sdk_sanity_check_continuation(contp) == TS_SUCCESS);
7297 
7298   http_sm->plugin_tunnel_type = HTTP_PLUGIN_AS_INTERCEPT;
7299   http_sm->plugin_tunnel      = PluginVCCore::alloc((INKContInternal *)contp);
7300 }
7301 
7302 // The API below require timer values as TSHRTime parameters
7303 // which are in nanoseconds. Use the TS_HRTIME macros defined
7304 // in ts/experimental.h until they are promoted to stable
7305 // api.
7306 /* Net VConnections */
7307 void
TSVConnInactivityTimeoutSet(TSVConn connp,TSHRTime timeout)7308 TSVConnInactivityTimeoutSet(TSVConn connp, TSHRTime timeout)
7309 {
7310   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
7311 
7312   NetVConnection *vc = (NetVConnection *)connp;
7313   vc->set_inactivity_timeout(timeout);
7314 }
7315 
7316 void
TSVConnInactivityTimeoutCancel(TSVConn connp)7317 TSVConnInactivityTimeoutCancel(TSVConn connp)
7318 {
7319   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
7320 
7321   NetVConnection *vc = (NetVConnection *)connp;
7322   vc->cancel_inactivity_timeout();
7323 }
7324 
7325 void
TSVConnActiveTimeoutSet(TSVConn connp,TSHRTime timeout)7326 TSVConnActiveTimeoutSet(TSVConn connp, TSHRTime timeout)
7327 {
7328   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
7329 
7330   NetVConnection *vc = (NetVConnection *)connp;
7331   vc->set_active_timeout(timeout);
7332 }
7333 
7334 void
TSVConnActiveTimeoutCancel(TSVConn connp)7335 TSVConnActiveTimeoutCancel(TSVConn connp)
7336 {
7337   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
7338 
7339   NetVConnection *vc = (NetVConnection *)connp;
7340   vc->cancel_active_timeout();
7341 }
7342 
7343 sockaddr const *
TSNetVConnLocalAddrGet(TSVConn connp)7344 TSNetVConnLocalAddrGet(TSVConn connp)
7345 {
7346   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
7347   NetVConnection *vc = reinterpret_cast<NetVConnection *>(connp);
7348   return vc->get_local_addr();
7349 }
7350 
7351 sockaddr const *
TSNetVConnRemoteAddrGet(TSVConn connp)7352 TSNetVConnRemoteAddrGet(TSVConn connp)
7353 {
7354   sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS);
7355   NetVConnection *vc = reinterpret_cast<NetVConnection *>(connp);
7356   return vc->get_remote_addr();
7357 }
7358 
7359 TSAction
TSNetConnect(TSCont contp,sockaddr const * addr)7360 TSNetConnect(TSCont contp, sockaddr const *addr)
7361 {
7362   sdk_assert(sdk_sanity_check_continuation(contp) == TS_SUCCESS);
7363   sdk_assert(ats_is_ip(addr));
7364 
7365   HttpConfigParams *http_config_param = HttpConfig::acquire();
7366   NetVCOptions opt;
7367   if (http_config_param) {
7368     opt.set_sock_param(http_config_param->oride.sock_recv_buffer_size_out, http_config_param->oride.sock_send_buffer_size_out,
7369                        http_config_param->oride.sock_option_flag_out, http_config_param->oride.sock_packet_mark_out,
7370                        http_config_param->oride.sock_packet_tos_out);
7371     HttpConfig::release(http_config_param);
7372   }
7373 
7374   FORCE_PLUGIN_SCOPED_MUTEX(contp);
7375 
7376   return reinterpret_cast<TSAction>(netProcessor.connect_re(reinterpret_cast<INKContInternal *>(contp), addr, &opt));
7377 }
7378 
7379 TSAction
TSNetConnectTransparent(TSCont contp,sockaddr const * client_addr,sockaddr const * server_addr)7380 TSNetConnectTransparent(TSCont contp, sockaddr const *client_addr, sockaddr const *server_addr)
7381 {
7382   sdk_assert(sdk_sanity_check_continuation(contp) == TS_SUCCESS);
7383   sdk_assert(ats_is_ip(server_addr));
7384   sdk_assert(ats_ip_are_compatible(client_addr, server_addr));
7385 
7386   NetVCOptions opt;
7387   opt.addr_binding = NetVCOptions::FOREIGN_ADDR;
7388   opt.local_ip.assign(client_addr);
7389   opt.local_port = ats_ip_port_host_order(client_addr);
7390 
7391   FORCE_PLUGIN_SCOPED_MUTEX(contp);
7392 
7393   return reinterpret_cast<TSAction>(netProcessor.connect_re(reinterpret_cast<INKContInternal *>(contp), server_addr, &opt));
7394 }
7395 
7396 TSCont
TSNetInvokingContGet(TSVConn conn)7397 TSNetInvokingContGet(TSVConn conn)
7398 {
7399   NetVConnection *vc         = reinterpret_cast<NetVConnection *>(conn);
7400   UnixNetVConnection *net_vc = dynamic_cast<UnixNetVConnection *>(vc);
7401   TSCont ret                 = nullptr;
7402   if (net_vc) {
7403     const Action *action = net_vc->get_action();
7404     ret                  = reinterpret_cast<TSCont>(action->continuation);
7405   }
7406   return ret;
7407 }
7408 
7409 TSHttpTxn
TSNetInvokingTxnGet(TSVConn conn)7410 TSNetInvokingTxnGet(TSVConn conn)
7411 {
7412   TSCont cont   = TSNetInvokingContGet(conn);
7413   TSHttpTxn ret = nullptr;
7414   if (cont) {
7415     Continuation *contobj = reinterpret_cast<Continuation *>(cont);
7416     HttpSM *sm            = dynamic_cast<HttpSM *>(contobj);
7417     if (sm) {
7418       ret = reinterpret_cast<TSHttpTxn>(sm);
7419     }
7420   }
7421   return ret;
7422 }
7423 
7424 TSAction
TSNetAccept(TSCont contp,int port,int domain,int accept_threads)7425 TSNetAccept(TSCont contp, int port, int domain, int accept_threads)
7426 {
7427   NetProcessor::AcceptOptions opt;
7428 
7429   sdk_assert(sdk_sanity_check_continuation(contp) == TS_SUCCESS);
7430   sdk_assert(port > 0);
7431   sdk_assert(accept_threads >= -1);
7432 
7433   // TODO: Does this imply that only one "accept thread" could be
7434   // doing an accept at any time?
7435   FORCE_PLUGIN_SCOPED_MUTEX(contp);
7436 
7437   opt = make_net_accept_options(nullptr, accept_threads);
7438 
7439   // If it's not IPv6, force to IPv4.
7440   opt.ip_family       = domain == AF_INET6 ? AF_INET6 : AF_INET;
7441   opt.local_port      = port;
7442   opt.frequent_accept = false;
7443 
7444   INKContInternal *i = reinterpret_cast<INKContInternal *>(contp);
7445   return reinterpret_cast<TSAction>(netProcessor.accept(i, opt));
7446 }
7447 
7448 /* From proxy/http/HttpProxyServerMain.c: */
7449 extern bool ssl_register_protocol(const char *, Continuation *);
7450 
7451 TSReturnCode
TSNetAcceptNamedProtocol(TSCont contp,const char * protocol)7452 TSNetAcceptNamedProtocol(TSCont contp, const char *protocol)
7453 {
7454   sdk_assert(protocol != nullptr);
7455   sdk_assert(contp != nullptr);
7456   sdk_assert(sdk_sanity_check_continuation(contp) == TS_SUCCESS);
7457 
7458   if (!ssl_register_protocol(protocol, (INKContInternal *)contp)) {
7459     return TS_ERROR;
7460   }
7461 
7462   return TS_SUCCESS;
7463 }
7464 
7465 /* DNS Lookups */
7466 TSAction
TSHostLookup(TSCont contp,const char * hostname,size_t namelen)7467 TSHostLookup(TSCont contp, const char *hostname, size_t namelen)
7468 {
7469   sdk_assert(sdk_sanity_check_continuation(contp) == TS_SUCCESS);
7470   sdk_assert(sdk_sanity_check_null_ptr((void *)hostname) == TS_SUCCESS);
7471   sdk_assert(namelen > 0);
7472 
7473   FORCE_PLUGIN_SCOPED_MUTEX(contp);
7474 
7475   INKContInternal *i = (INKContInternal *)contp;
7476   return (TSAction)hostDBProcessor.getbyname_re(i, hostname, namelen);
7477 }
7478 
7479 sockaddr const *
TSHostLookupResultAddrGet(TSHostLookupResult lookup_result)7480 TSHostLookupResultAddrGet(TSHostLookupResult lookup_result)
7481 {
7482   sdk_assert(sdk_sanity_check_hostlookup_structure(lookup_result) == TS_SUCCESS);
7483   HostDBInfo *di = reinterpret_cast<HostDBInfo *>(lookup_result);
7484   return di->ip();
7485 }
7486 
7487 /*
7488  * checks if the cache is ready
7489  */
7490 
7491 /* Only TSCacheReady exposed in SDK. No need of TSCacheDataTypeReady */
7492 /* because SDK cache API supports only the data type: NONE */
7493 TSReturnCode
TSCacheReady(int * is_ready)7494 TSCacheReady(int *is_ready)
7495 {
7496   sdk_assert(sdk_sanity_check_null_ptr((void *)is_ready) == TS_SUCCESS);
7497   return TSCacheDataTypeReady(TS_CACHE_DATA_TYPE_NONE, is_ready);
7498 }
7499 
7500 /* Private API (used by Mixt) */
7501 TSReturnCode
TSCacheDataTypeReady(TSCacheDataType type,int * is_ready)7502 TSCacheDataTypeReady(TSCacheDataType type, int *is_ready)
7503 {
7504   sdk_assert(sdk_sanity_check_null_ptr((void *)is_ready) == TS_SUCCESS);
7505 
7506   CacheFragType frag_type;
7507 
7508   switch (type) {
7509   case TS_CACHE_DATA_TYPE_NONE:
7510     frag_type = CACHE_FRAG_TYPE_NONE;
7511     break;
7512   case TS_CACHE_DATA_TYPE_OTHER: /* other maps to http */
7513   case TS_CACHE_DATA_TYPE_HTTP:
7514     frag_type = CACHE_FRAG_TYPE_HTTP;
7515     break;
7516   default:
7517     *is_ready = 0;
7518     return TS_ERROR;
7519   }
7520 
7521   *is_ready = cacheProcessor.IsCacheReady(frag_type);
7522   return TS_SUCCESS;
7523 }
7524 
7525 /* Cache VConnections */
7526 TSAction
TSCacheRead(TSCont contp,TSCacheKey key)7527 TSCacheRead(TSCont contp, TSCacheKey key)
7528 {
7529   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
7530   sdk_assert(sdk_sanity_check_cachekey(key) == TS_SUCCESS);
7531 
7532   FORCE_PLUGIN_SCOPED_MUTEX(contp);
7533 
7534   CacheInfo *info = (CacheInfo *)key;
7535   Continuation *i = (INKContInternal *)contp;
7536 
7537   return (TSAction)cacheProcessor.open_read(i, &info->cache_key, info->frag_type, info->hostname, info->len);
7538 }
7539 
7540 TSAction
TSCacheWrite(TSCont contp,TSCacheKey key)7541 TSCacheWrite(TSCont contp, TSCacheKey key)
7542 {
7543   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
7544   sdk_assert(sdk_sanity_check_cachekey(key) == TS_SUCCESS);
7545 
7546   FORCE_PLUGIN_SCOPED_MUTEX(contp);
7547 
7548   CacheInfo *info = (CacheInfo *)key;
7549   Continuation *i = (INKContInternal *)contp;
7550 
7551   return (TSAction)cacheProcessor.open_write(i, &info->cache_key, info->frag_type, 0, false, info->pin_in_cache, info->hostname,
7552                                              info->len);
7553 }
7554 
7555 TSAction
TSCacheRemove(TSCont contp,TSCacheKey key)7556 TSCacheRemove(TSCont contp, TSCacheKey key)
7557 {
7558   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
7559   sdk_assert(sdk_sanity_check_cachekey(key) == TS_SUCCESS);
7560 
7561   FORCE_PLUGIN_SCOPED_MUTEX(contp);
7562 
7563   CacheInfo *info    = (CacheInfo *)key;
7564   INKContInternal *i = (INKContInternal *)contp;
7565 
7566   return (TSAction)cacheProcessor.remove(i, &info->cache_key, info->frag_type, info->hostname, info->len);
7567 }
7568 
7569 TSAction
TSCacheScan(TSCont contp,TSCacheKey key,int KB_per_second)7570 TSCacheScan(TSCont contp, TSCacheKey key, int KB_per_second)
7571 {
7572   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
7573   // NOTE: key can be NULl here, so don't check for it.
7574 
7575   FORCE_PLUGIN_SCOPED_MUTEX(contp);
7576 
7577   INKContInternal *i = (INKContInternal *)contp;
7578 
7579   if (key) {
7580     CacheInfo *info = (CacheInfo *)key;
7581     return (TSAction)cacheProcessor.scan(i, info->hostname, info->len, KB_per_second);
7582   }
7583   return reinterpret_cast<TSAction>(cacheProcessor.scan(i, nullptr, 0, KB_per_second));
7584 }
7585 
7586 /************************   REC Stats API    **************************/
7587 int
TSStatCreate(const char * the_name,TSRecordDataType the_type,TSStatPersistence persist,TSStatSync sync)7588 TSStatCreate(const char *the_name, TSRecordDataType the_type, TSStatPersistence persist, TSStatSync sync)
7589 {
7590   int id                  = ink_atomic_increment(&api_rsb_index, 1);
7591   RecRawStatSyncCb syncer = RecRawStatSyncCount;
7592 
7593   // TODO: This only supports "int" data types at this point, since the "Raw" stats
7594   // interfaces only supports integers. Going forward, we could extend either the "Raw"
7595   // stats APIs, or make non-int use the direct (synchronous) stats APIs (slower).
7596   if ((sdk_sanity_check_null_ptr((void *)the_name) != TS_SUCCESS) || (sdk_sanity_check_null_ptr((void *)api_rsb) != TS_SUCCESS) ||
7597       (id >= api_rsb->max_stats)) {
7598     return TS_ERROR;
7599   }
7600 
7601   switch (sync) {
7602   case TS_STAT_SYNC_SUM:
7603     syncer = RecRawStatSyncSum;
7604     break;
7605   case TS_STAT_SYNC_AVG:
7606     syncer = RecRawStatSyncAvg;
7607     break;
7608   case TS_STAT_SYNC_TIMEAVG:
7609     syncer = RecRawStatSyncHrTimeAvg;
7610     break;
7611   default:
7612     syncer = RecRawStatSyncCount;
7613     break;
7614   }
7615 
7616   switch (persist) {
7617   case TS_STAT_PERSISTENT:
7618     RecRegisterRawStat(api_rsb, RECT_PLUGIN, the_name, (RecDataT)the_type, RECP_PERSISTENT, id, syncer);
7619     break;
7620   case TS_STAT_NON_PERSISTENT:
7621     RecRegisterRawStat(api_rsb, RECT_PLUGIN, the_name, (RecDataT)the_type, RECP_NON_PERSISTENT, id, syncer);
7622     break;
7623   default:
7624     return TS_ERROR;
7625   }
7626 
7627   return id;
7628 }
7629 
7630 void
TSStatIntIncrement(int id,TSMgmtInt amount)7631 TSStatIntIncrement(int id, TSMgmtInt amount)
7632 {
7633   sdk_assert(sdk_sanity_check_stat_id(id) == TS_SUCCESS);
7634   RecIncrRawStat(api_rsb, nullptr, id, amount);
7635 }
7636 
7637 void
TSStatIntDecrement(int id,TSMgmtInt amount)7638 TSStatIntDecrement(int id, TSMgmtInt amount)
7639 {
7640   RecDecrRawStat(api_rsb, nullptr, id, amount);
7641 }
7642 
7643 TSMgmtInt
TSStatIntGet(int id)7644 TSStatIntGet(int id)
7645 {
7646   TSMgmtInt value;
7647 
7648   sdk_assert(sdk_sanity_check_stat_id(id) == TS_SUCCESS);
7649   RecGetGlobalRawStatSum(api_rsb, id, &value);
7650   return value;
7651 }
7652 
7653 void
TSStatIntSet(int id,TSMgmtInt value)7654 TSStatIntSet(int id, TSMgmtInt value)
7655 {
7656   sdk_assert(sdk_sanity_check_stat_id(id) == TS_SUCCESS);
7657   RecSetGlobalRawStatSum(api_rsb, id, value);
7658 }
7659 
7660 TSReturnCode
TSStatFindName(const char * name,int * idp)7661 TSStatFindName(const char *name, int *idp)
7662 {
7663   int id;
7664 
7665   sdk_assert(sdk_sanity_check_null_ptr((void *)name) == TS_SUCCESS);
7666 
7667   if (RecGetRecordOrderAndId(name, nullptr, &id, true, true) != REC_ERR_OKAY) {
7668     return TS_ERROR;
7669   }
7670 
7671   if (RecGetGlobalRawStatPtr(api_rsb, id) == nullptr) {
7672     return TS_ERROR;
7673   }
7674 
7675   *idp = id;
7676   return TS_SUCCESS;
7677 }
7678 
7679 /**************************    Stats API    ****************************/
7680 // THESE APIS ARE DEPRECATED, USE THE REC APIs INSTEAD
7681 // #define ink_sanity_check_stat_structure(_x) TS_SUCCESS
7682 
7683 inline TSReturnCode
ink_sanity_check_stat_structure(void * obj)7684 ink_sanity_check_stat_structure(void *obj)
7685 {
7686   if (obj == nullptr) {
7687     return TS_ERROR;
7688   }
7689 
7690   return TS_SUCCESS;
7691 }
7692 
7693 /**************************   Tracing API   ****************************/
7694 // returns 1 or 0 to indicate whether TS is being run with a debug tag.
7695 int
TSIsDebugTagSet(const char * t)7696 TSIsDebugTagSet(const char *t)
7697 {
7698   return is_debug_tag_set(t);
7699 }
7700 
7701 void
TSDebugSpecific(int debug_flag,const char * tag,const char * format_str,...)7702 TSDebugSpecific(int debug_flag, const char *tag, const char *format_str, ...)
7703 {
7704   if ((debug_flag && diags->on()) || is_debug_tag_set(tag)) {
7705     va_list ap;
7706 
7707     va_start(ap, format_str);
7708     diags->print_va(tag, DL_Diag, nullptr, format_str, ap);
7709     va_end(ap);
7710   }
7711 }
7712 
7713 // Plugins would use TSDebug just as the TS internal uses Debug
7714 // e.g. TSDebug("plugin-cool", "Snoopy is a cool guy even after %d requests.", num_reqs);
7715 void
TSDebug(const char * tag,const char * format_str,...)7716 TSDebug(const char *tag, const char *format_str, ...)
7717 {
7718   if (is_debug_tag_set(tag)) {
7719     va_list ap;
7720 
7721     va_start(ap, format_str);
7722     diags->print_va(tag, DL_Diag, nullptr, format_str, ap);
7723     va_end(ap);
7724   }
7725 }
7726 
7727 /**************************   Logging API   ****************************/
7728 
7729 TSReturnCode
TSTextLogObjectCreate(const char * filename,int mode,TSTextLogObject * new_object)7730 TSTextLogObjectCreate(const char *filename, int mode, TSTextLogObject *new_object)
7731 {
7732   sdk_assert(sdk_sanity_check_null_ptr((void *)filename) == TS_SUCCESS);
7733   sdk_assert(sdk_sanity_check_null_ptr((void *)new_object) == TS_SUCCESS);
7734 
7735   if (mode < 0 || mode >= TS_LOG_MODE_INVALID_FLAG) {
7736     *new_object = nullptr;
7737     return TS_ERROR;
7738   }
7739 
7740   TextLogObject *tlog = new TextLogObject(
7741     filename, Log::config->logfile_dir, (bool)mode & TS_LOG_MODE_ADD_TIMESTAMP, nullptr, Log::config->rolling_enabled,
7742     Log::config->preproc_threads, Log::config->rolling_interval_sec, Log::config->rolling_offset_hr, Log::config->rolling_size_mb,
7743     Log::config->rolling_max_count, Log::config->rolling_min_count, Log::config->rolling_allow_empty);
7744   if (tlog == nullptr) {
7745     *new_object = nullptr;
7746     return TS_ERROR;
7747   }
7748 
7749   int err = (mode & TS_LOG_MODE_DO_NOT_RENAME ? Log::config->log_object_manager.manage_api_object(tlog, 0) :
7750                                                 Log::config->log_object_manager.manage_api_object(tlog));
7751   if (err != LogObjectManager::NO_FILENAME_CONFLICTS) {
7752     delete tlog;
7753     *new_object = nullptr;
7754     return TS_ERROR;
7755   }
7756 
7757   *new_object = (TSTextLogObject)tlog;
7758   return TS_SUCCESS;
7759 }
7760 
7761 TSReturnCode
TSTextLogObjectWrite(TSTextLogObject the_object,const char * format,...)7762 TSTextLogObjectWrite(TSTextLogObject the_object, const char *format, ...)
7763 {
7764   sdk_assert(sdk_sanity_check_iocore_structure(the_object) == TS_SUCCESS);
7765   sdk_assert(sdk_sanity_check_null_ptr((void *)format) == TS_SUCCESS);
7766 
7767   TSReturnCode retVal = TS_SUCCESS;
7768 
7769   va_list ap;
7770   va_start(ap, format);
7771   switch (((TextLogObject *)the_object)->va_write(format, ap)) {
7772   case (Log::LOG_OK):
7773   case (Log::SKIP):
7774   case (Log::AGGR):
7775     break;
7776   case (Log::FULL):
7777     retVal = TS_ERROR;
7778     break;
7779   case (Log::FAIL):
7780     retVal = TS_ERROR;
7781     break;
7782   default:
7783     ink_assert(!"invalid return code");
7784   }
7785   va_end(ap);
7786 
7787   return retVal;
7788 }
7789 
7790 void
TSTextLogObjectFlush(TSTextLogObject the_object)7791 TSTextLogObjectFlush(TSTextLogObject the_object)
7792 {
7793   sdk_assert(sdk_sanity_check_iocore_structure(the_object) == TS_SUCCESS);
7794 
7795   ((TextLogObject *)the_object)->force_new_buffer();
7796 }
7797 
7798 TSReturnCode
TSTextLogObjectDestroy(TSTextLogObject the_object)7799 TSTextLogObjectDestroy(TSTextLogObject the_object)
7800 {
7801   sdk_assert(sdk_sanity_check_iocore_structure(the_object) == TS_SUCCESS);
7802 
7803   if (Log::config->log_object_manager.unmanage_api_object((TextLogObject *)the_object)) {
7804     return TS_SUCCESS;
7805   }
7806 
7807   return TS_ERROR;
7808 }
7809 
7810 void
TSTextLogObjectHeaderSet(TSTextLogObject the_object,const char * header)7811 TSTextLogObjectHeaderSet(TSTextLogObject the_object, const char *header)
7812 {
7813   sdk_assert(sdk_sanity_check_iocore_structure(the_object) == TS_SUCCESS);
7814 
7815   ((TextLogObject *)the_object)->set_log_file_header(header);
7816 }
7817 
7818 TSReturnCode
TSTextLogObjectRollingEnabledSet(TSTextLogObject the_object,int rolling_enabled)7819 TSTextLogObjectRollingEnabledSet(TSTextLogObject the_object, int rolling_enabled)
7820 {
7821   sdk_assert(sdk_sanity_check_iocore_structure(the_object) == TS_SUCCESS);
7822 
7823   if (LogRollingEnabledIsValid(rolling_enabled)) {
7824     ((TextLogObject *)the_object)->set_rolling_enabled((Log::RollingEnabledValues)rolling_enabled);
7825     return TS_SUCCESS;
7826   }
7827 
7828   return TS_ERROR;
7829 }
7830 
7831 void
TSTextLogObjectRollingIntervalSecSet(TSTextLogObject the_object,int rolling_interval_sec)7832 TSTextLogObjectRollingIntervalSecSet(TSTextLogObject the_object, int rolling_interval_sec)
7833 {
7834   sdk_assert(sdk_sanity_check_iocore_structure(the_object) == TS_SUCCESS);
7835 
7836   ((TextLogObject *)the_object)->set_rolling_interval_sec(rolling_interval_sec);
7837 }
7838 
7839 void
TSTextLogObjectRollingOffsetHrSet(TSTextLogObject the_object,int rolling_offset_hr)7840 TSTextLogObjectRollingOffsetHrSet(TSTextLogObject the_object, int rolling_offset_hr)
7841 {
7842   sdk_assert(sdk_sanity_check_iocore_structure(the_object) == TS_SUCCESS);
7843 
7844   ((TextLogObject *)the_object)->set_rolling_offset_hr(rolling_offset_hr);
7845 }
7846 
7847 void
TSTextLogObjectRollingSizeMbSet(TSTextLogObject the_object,int rolling_size_mb)7848 TSTextLogObjectRollingSizeMbSet(TSTextLogObject the_object, int rolling_size_mb)
7849 {
7850   sdk_assert(sdk_sanity_check_iocore_structure(the_object) == TS_SUCCESS);
7851 
7852   ((TextLogObject *)the_object)->set_rolling_size_mb(rolling_size_mb);
7853 }
7854 
7855 TSReturnCode
TSHttpSsnClientFdGet(TSHttpSsn ssnp,int * fdp)7856 TSHttpSsnClientFdGet(TSHttpSsn ssnp, int *fdp)
7857 {
7858   sdk_assert(sdk_sanity_check_null_ptr((void *)fdp) == TS_SUCCESS);
7859 
7860   VConnection *basecs = reinterpret_cast<VConnection *>(ssnp);
7861   ProxySession *cs    = dynamic_cast<ProxySession *>(basecs);
7862 
7863   if (cs == nullptr) {
7864     return TS_ERROR;
7865   }
7866 
7867   NetVConnection *vc = cs->get_netvc();
7868   if (vc == nullptr) {
7869     return TS_ERROR;
7870   }
7871 
7872   *fdp = vc->get_socket();
7873   return TS_SUCCESS;
7874 }
7875 TSReturnCode
TSHttpTxnClientFdGet(TSHttpTxn txnp,int * fdp)7876 TSHttpTxnClientFdGet(TSHttpTxn txnp, int *fdp)
7877 {
7878   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
7879   sdk_assert(sdk_sanity_check_null_ptr((void *)fdp) == TS_SUCCESS);
7880 
7881   TSHttpSsn ssnp = TSHttpTxnSsnGet(txnp);
7882   return TSHttpSsnClientFdGet(ssnp, fdp);
7883 }
7884 
7885 TSReturnCode
TSHttpTxnServerFdGet(TSHttpTxn txnp,int * fdp)7886 TSHttpTxnServerFdGet(TSHttpTxn txnp, int *fdp)
7887 {
7888   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
7889   sdk_assert(sdk_sanity_check_null_ptr((void *)fdp) == TS_SUCCESS);
7890 
7891   HttpSM *sm = reinterpret_cast<HttpSM *>(txnp);
7892   *fdp       = -1;
7893 
7894   PoolableSession *ss = sm->get_server_session();
7895   if (ss == nullptr) {
7896     return TS_ERROR;
7897   }
7898 
7899   NetVConnection *vc = ss->get_netvc();
7900   if (vc == nullptr) {
7901     return TS_ERROR;
7902   }
7903 
7904   *fdp = vc->get_socket();
7905   return TS_SUCCESS;
7906 }
7907 
7908 /* Matcher Utils */
7909 char *
TSMatcherReadIntoBuffer(char * file_name,int * file_len)7910 TSMatcherReadIntoBuffer(char *file_name, int *file_len)
7911 {
7912   sdk_assert(sdk_sanity_check_null_ptr((void *)file_name) == TS_SUCCESS);
7913   return readIntoBuffer(file_name, "TSMatcher", file_len);
7914 }
7915 
7916 char *
TSMatcherTokLine(char * buffer,char ** last)7917 TSMatcherTokLine(char *buffer, char **last)
7918 {
7919   sdk_assert(sdk_sanity_check_null_ptr((void *)buffer) == TS_SUCCESS);
7920   return tokLine(buffer, last);
7921 }
7922 
7923 char *
TSMatcherExtractIPRange(char * match_str,uint32_t * addr1,uint32_t * addr2)7924 TSMatcherExtractIPRange(char *match_str, uint32_t *addr1, uint32_t *addr2)
7925 {
7926   sdk_assert(sdk_sanity_check_null_ptr((void *)match_str) == TS_SUCCESS);
7927   return (char *)ExtractIpRange(match_str, addr1, addr2);
7928 }
7929 // Conflict in header due to overload (must be C compatible).
7930 char *
TSMatcherExtractIPRange(char * match_str,sockaddr * addr1,sockaddr * addr2)7931 TSMatcherExtractIPRange(char *match_str, sockaddr *addr1, sockaddr *addr2)
7932 {
7933   sdk_assert(sdk_sanity_check_null_ptr((void *)match_str) == TS_SUCCESS);
7934   return (char *)ExtractIpRange(match_str, addr1, addr2);
7935 }
7936 
7937 TSMatcherLine
TSMatcherLineCreate()7938 TSMatcherLineCreate()
7939 {
7940   return reinterpret_cast<TSMatcherLine>(ats_malloc(sizeof(matcher_line)));
7941 }
7942 
7943 void
TSMatcherLineDestroy(TSMatcherLine ml)7944 TSMatcherLineDestroy(TSMatcherLine ml)
7945 {
7946   sdk_assert(sdk_sanity_check_null_ptr((void *)ml) == TS_SUCCESS);
7947   ats_free(ml);
7948 }
7949 
7950 const char *
TSMatcherParseSrcIPConfigLine(char * line,TSMatcherLine ml)7951 TSMatcherParseSrcIPConfigLine(char *line, TSMatcherLine ml)
7952 {
7953   sdk_assert(sdk_sanity_check_null_ptr((void *)line) == TS_SUCCESS);
7954   return parseConfigLine(line, (matcher_line *)ml, &ip_allow_src_tags);
7955 }
7956 
7957 char *
TSMatcherLineName(TSMatcherLine ml,int element)7958 TSMatcherLineName(TSMatcherLine ml, int element)
7959 {
7960   sdk_assert(sdk_sanity_check_null_ptr((void *)ml) == TS_SUCCESS);
7961   return (((matcher_line *)ml)->line)[0][element];
7962 }
7963 
7964 char *
TSMatcherLineValue(TSMatcherLine ml,int element)7965 TSMatcherLineValue(TSMatcherLine ml, int element)
7966 {
7967   sdk_assert(sdk_sanity_check_null_ptr((void *)ml) == TS_SUCCESS);
7968   return (((matcher_line *)ml)->line)[1][element];
7969 }
7970 
7971 /* Configuration Setting */
7972 TSReturnCode
TSMgmtConfigIntSet(const char * var_name,TSMgmtInt value)7973 TSMgmtConfigIntSet(const char *var_name, TSMgmtInt value)
7974 {
7975   TSMgmtInt result;
7976   char *buffer;
7977 
7978   // is this a valid integer?
7979   if (TSMgmtIntGet(var_name, &result) != TS_SUCCESS) {
7980     return TS_ERROR;
7981   }
7982 
7983   // construct a buffer
7984   int buffer_size = strlen(var_name) + 1 + 32 + 1 + 64 + 1;
7985 
7986   buffer = static_cast<char *>(alloca(buffer_size));
7987   snprintf(buffer, buffer_size, "%s %d %" PRId64 "", var_name, MGMT_INT, value);
7988 
7989   // tell manager to set the configuration; note that this is not
7990   // transactional (e.g. we return control to the plugin before the
7991   // value is committed to disk by the manager)
7992   RecSignalManager(MGMT_SIGNAL_PLUGIN_SET_CONFIG, buffer);
7993 
7994   return TS_SUCCESS;
7995 }
7996 
7997 extern void load_config_file_callback(const char *parent, const char *remap_file);
7998 
7999 /* Config file name setting */
8000 TSReturnCode
TSMgmtConfigFileAdd(const char * parent,const char * fileName)8001 TSMgmtConfigFileAdd(const char *parent, const char *fileName)
8002 {
8003   load_config_file_callback(parent, fileName);
8004   return TS_SUCCESS;
8005 }
8006 
8007 TSReturnCode
TSCacheUrlSet(TSHttpTxn txnp,const char * url,int length)8008 TSCacheUrlSet(TSHttpTxn txnp, const char *url, int length)
8009 {
8010   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
8011 
8012   HttpSM *sm = (HttpSM *)txnp;
8013   Debug("cache_url", "[TSCacheUrlSet]");
8014 
8015   if (sm->t_state.cache_info.lookup_url == nullptr) {
8016     Debug("cache_url", "[TSCacheUrlSet] changing the cache url to: %s", url);
8017 
8018     if (length == -1) {
8019       length = strlen(url);
8020     }
8021 
8022     sm->t_state.cache_info.lookup_url_storage.create(nullptr);
8023     sm->t_state.cache_info.lookup_url = &(sm->t_state.cache_info.lookup_url_storage);
8024     sm->t_state.cache_info.lookup_url->parse(url, length);
8025     return TS_SUCCESS;
8026   }
8027 
8028   return TS_ERROR;
8029 }
8030 
8031 void
TSCacheHttpInfoKeySet(TSCacheHttpInfo infop,TSCacheKey keyp)8032 TSCacheHttpInfoKeySet(TSCacheHttpInfo infop, TSCacheKey keyp)
8033 {
8034   // TODO: Check input ?
8035   CacheHTTPInfo *info = (CacheHTTPInfo *)infop;
8036   CryptoHash *key     = (CryptoHash *)keyp;
8037 
8038   info->object_key_set(*key);
8039 }
8040 
8041 void
TSCacheHttpInfoSizeSet(TSCacheHttpInfo infop,int64_t size)8042 TSCacheHttpInfoSizeSet(TSCacheHttpInfo infop, int64_t size)
8043 {
8044   // TODO: Check input ?
8045   CacheHTTPInfo *info = (CacheHTTPInfo *)infop;
8046 
8047   info->object_size_set(size);
8048 }
8049 
8050 // this function should be called at TS_EVENT_HTTP_READ_RESPONSE_HDR
8051 void
TSHttpTxnRedirectUrlSet(TSHttpTxn txnp,const char * url,const int url_len)8052 TSHttpTxnRedirectUrlSet(TSHttpTxn txnp, const char *url, const int url_len)
8053 {
8054   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
8055   sdk_assert(sdk_sanity_check_null_ptr((void *)url) == TS_SUCCESS);
8056 
8057   HttpSM *sm = (HttpSM *)txnp;
8058 
8059   if (sm->redirect_url != nullptr) {
8060     ats_free(sm->redirect_url);
8061     sm->redirect_url     = nullptr;
8062     sm->redirect_url_len = 0;
8063   }
8064 
8065   sm->redirect_url       = (char *)url;
8066   sm->redirect_url_len   = url_len;
8067   sm->enable_redirection = true;
8068   sm->redirection_tries  = 0;
8069 
8070   // Make sure we allow for at least one redirection.
8071   if (sm->t_state.txn_conf->number_of_redirections <= 0) {
8072     sm->t_state.setup_per_txn_configs();
8073     sm->t_state.my_txn_conf().number_of_redirections = 1;
8074   }
8075 }
8076 
8077 const char *
TSHttpTxnRedirectUrlGet(TSHttpTxn txnp,int * url_len_ptr)8078 TSHttpTxnRedirectUrlGet(TSHttpTxn txnp, int *url_len_ptr)
8079 {
8080   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
8081 
8082   HttpSM *sm = (HttpSM *)txnp;
8083 
8084   *url_len_ptr = sm->redirect_url_len;
8085   return sm->redirect_url;
8086 }
8087 
8088 int
TSHttpTxnRedirectRetries(TSHttpTxn txnp)8089 TSHttpTxnRedirectRetries(TSHttpTxn txnp)
8090 {
8091   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
8092 
8093   HttpSM *sm = (HttpSM *)txnp;
8094 
8095   return sm->redirection_tries;
8096 }
8097 
8098 char *
TSFetchRespGet(TSHttpTxn txnp,int * length)8099 TSFetchRespGet(TSHttpTxn txnp, int *length)
8100 {
8101   sdk_assert(sdk_sanity_check_null_ptr((void *)length) == TS_SUCCESS);
8102   FetchSM *fetch_sm = reinterpret_cast<FetchSM *>(txnp);
8103   return fetch_sm->resp_get(length);
8104 }
8105 
8106 TSReturnCode
TSFetchPageRespGet(TSHttpTxn txnp,TSMBuffer * bufp,TSMLoc * obj)8107 TSFetchPageRespGet(TSHttpTxn txnp, TSMBuffer *bufp, TSMLoc *obj)
8108 {
8109   sdk_assert(sdk_sanity_check_null_ptr((void *)bufp) == TS_SUCCESS);
8110   sdk_assert(sdk_sanity_check_null_ptr((void *)obj) == TS_SUCCESS);
8111 
8112   HTTPHdr *hptr = (HTTPHdr *)txnp;
8113 
8114   if (hptr->valid()) {
8115     *(reinterpret_cast<HTTPHdr **>(bufp)) = hptr;
8116     *obj                                  = reinterpret_cast<TSMLoc>(hptr->m_http);
8117     return sdk_sanity_check_mbuffer(*bufp);
8118   }
8119 
8120   return TS_ERROR;
8121 }
8122 
8123 // Fetchpages SM
8124 extern ClassAllocator<FetchSM> FetchSMAllocator;
8125 
8126 void
TSFetchPages(TSFetchUrlParams_t * params)8127 TSFetchPages(TSFetchUrlParams_t *params)
8128 {
8129   TSFetchUrlParams_t *myparams = params;
8130 
8131   while (myparams != nullptr) {
8132     FetchSM *fetch_sm = FetchSMAllocator.alloc();
8133     sockaddr *addr    = ats_ip_sa_cast(&myparams->ip);
8134 
8135     fetch_sm->init((Continuation *)myparams->contp, myparams->options, myparams->events, myparams->request, myparams->request_len,
8136                    addr);
8137     fetch_sm->httpConnect();
8138     myparams = myparams->next;
8139   }
8140 }
8141 
8142 TSFetchSM
TSFetchUrl(const char * headers,int request_len,sockaddr const * ip,TSCont contp,TSFetchWakeUpOptions callback_options,TSFetchEvent events)8143 TSFetchUrl(const char *headers, int request_len, sockaddr const *ip, TSCont contp, TSFetchWakeUpOptions callback_options,
8144            TSFetchEvent events)
8145 {
8146   if (callback_options != NO_CALLBACK) {
8147     sdk_assert(sdk_sanity_check_continuation(contp) == TS_SUCCESS);
8148   }
8149 
8150   FetchSM *fetch_sm = FetchSMAllocator.alloc();
8151 
8152   fetch_sm->init((Continuation *)contp, callback_options, events, headers, request_len, ip);
8153   fetch_sm->httpConnect();
8154 
8155   return reinterpret_cast<TSFetchSM>(fetch_sm);
8156 }
8157 
8158 void
TSFetchFlagSet(TSFetchSM fetch_sm,int flags)8159 TSFetchFlagSet(TSFetchSM fetch_sm, int flags)
8160 {
8161   sdk_assert(sdk_sanity_check_fetch_sm(fetch_sm) == TS_SUCCESS);
8162   (reinterpret_cast<FetchSM *>(fetch_sm))->set_fetch_flags(flags);
8163 }
8164 
8165 TSFetchSM
TSFetchCreate(TSCont contp,const char * method,const char * url,const char * version,struct sockaddr const * client_addr,int flags)8166 TSFetchCreate(TSCont contp, const char *method, const char *url, const char *version, struct sockaddr const *client_addr, int flags)
8167 {
8168   sdk_assert(sdk_sanity_check_continuation(contp) == TS_SUCCESS);
8169   sdk_assert(ats_is_ip(client_addr));
8170 
8171   FetchSM *fetch_sm = FetchSMAllocator.alloc();
8172 
8173   fetch_sm->ext_init((Continuation *)contp, method, url, version, client_addr, flags);
8174 
8175   return reinterpret_cast<TSFetchSM>(fetch_sm);
8176 }
8177 
8178 void
TSFetchHeaderAdd(TSFetchSM fetch_sm,const char * name,int name_len,const char * value,int value_len)8179 TSFetchHeaderAdd(TSFetchSM fetch_sm, const char *name, int name_len, const char *value, int value_len)
8180 {
8181   sdk_assert(sdk_sanity_check_fetch_sm(fetch_sm) == TS_SUCCESS);
8182 
8183   (reinterpret_cast<FetchSM *>(fetch_sm))->ext_add_header(name, name_len, value, value_len);
8184 }
8185 
8186 void
TSFetchWriteData(TSFetchSM fetch_sm,const void * data,size_t len)8187 TSFetchWriteData(TSFetchSM fetch_sm, const void *data, size_t len)
8188 {
8189   sdk_assert(sdk_sanity_check_fetch_sm(fetch_sm) == TS_SUCCESS);
8190 
8191   (reinterpret_cast<FetchSM *>(fetch_sm))->ext_write_data(data, len);
8192 }
8193 
8194 ssize_t
TSFetchReadData(TSFetchSM fetch_sm,void * buf,size_t len)8195 TSFetchReadData(TSFetchSM fetch_sm, void *buf, size_t len)
8196 {
8197   sdk_assert(sdk_sanity_check_fetch_sm(fetch_sm) == TS_SUCCESS);
8198 
8199   return (reinterpret_cast<FetchSM *>(fetch_sm))->ext_read_data(static_cast<char *>(buf), len);
8200 }
8201 
8202 void
TSFetchLaunch(TSFetchSM fetch_sm)8203 TSFetchLaunch(TSFetchSM fetch_sm)
8204 {
8205   sdk_assert(sdk_sanity_check_fetch_sm(fetch_sm) == TS_SUCCESS);
8206 
8207   (reinterpret_cast<FetchSM *>(fetch_sm))->ext_launch();
8208 }
8209 
8210 void
TSFetchDestroy(TSFetchSM fetch_sm)8211 TSFetchDestroy(TSFetchSM fetch_sm)
8212 {
8213   sdk_assert(sdk_sanity_check_fetch_sm(fetch_sm) == TS_SUCCESS);
8214 
8215   (reinterpret_cast<FetchSM *>(fetch_sm))->ext_destroy();
8216 }
8217 
8218 void
TSFetchUserDataSet(TSFetchSM fetch_sm,void * data)8219 TSFetchUserDataSet(TSFetchSM fetch_sm, void *data)
8220 {
8221   sdk_assert(sdk_sanity_check_fetch_sm(fetch_sm) == TS_SUCCESS);
8222 
8223   (reinterpret_cast<FetchSM *>(fetch_sm))->ext_set_user_data(data);
8224 }
8225 
8226 void *
TSFetchUserDataGet(TSFetchSM fetch_sm)8227 TSFetchUserDataGet(TSFetchSM fetch_sm)
8228 {
8229   sdk_assert(sdk_sanity_check_fetch_sm(fetch_sm) == TS_SUCCESS);
8230 
8231   return (reinterpret_cast<FetchSM *>(fetch_sm))->ext_get_user_data();
8232 }
8233 
8234 TSMBuffer
TSFetchRespHdrMBufGet(TSFetchSM fetch_sm)8235 TSFetchRespHdrMBufGet(TSFetchSM fetch_sm)
8236 {
8237   sdk_assert(sdk_sanity_check_fetch_sm(fetch_sm) == TS_SUCCESS);
8238 
8239   return ((FetchSM *)fetch_sm)->resp_hdr_bufp();
8240 }
8241 
8242 TSMLoc
TSFetchRespHdrMLocGet(TSFetchSM fetch_sm)8243 TSFetchRespHdrMLocGet(TSFetchSM fetch_sm)
8244 {
8245   sdk_assert(sdk_sanity_check_fetch_sm(fetch_sm) == TS_SUCCESS);
8246 
8247   return ((FetchSM *)fetch_sm)->resp_hdr_mloc();
8248 }
8249 
8250 int
TSHttpSsnIsInternal(TSHttpSsn ssnp)8251 TSHttpSsnIsInternal(TSHttpSsn ssnp)
8252 {
8253   ProxySession *cs = reinterpret_cast<ProxySession *>(ssnp);
8254 
8255   if (!cs) {
8256     return 0;
8257   }
8258 
8259   NetVConnection *vc = cs->get_netvc();
8260   if (!vc) {
8261     return 0;
8262   }
8263 
8264   return vc->get_is_internal_request() ? 1 : 0;
8265 }
8266 
8267 int
TSHttpTxnIsInternal(TSHttpTxn txnp)8268 TSHttpTxnIsInternal(TSHttpTxn txnp)
8269 {
8270   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
8271   return TSHttpSsnIsInternal(TSHttpTxnSsnGet(txnp));
8272 }
8273 
8274 TSReturnCode
TSHttpTxnServerPush(TSHttpTxn txnp,const char * url,int url_len)8275 TSHttpTxnServerPush(TSHttpTxn txnp, const char *url, int url_len)
8276 {
8277   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
8278 
8279   URL url_obj;
8280   url_obj.create(nullptr);
8281   if (url_obj.parse(url, url_len) == PARSE_RESULT_ERROR) {
8282     url_obj.destroy();
8283     return TS_ERROR;
8284   }
8285 
8286   HttpSM *sm          = reinterpret_cast<HttpSM *>(txnp);
8287   Http2Stream *stream = dynamic_cast<Http2Stream *>(sm->ua_txn);
8288   if (stream == nullptr) {
8289     url_obj.destroy();
8290     return TS_ERROR;
8291   }
8292 
8293   Http2ClientSession *ua_session = static_cast<Http2ClientSession *>(stream->get_proxy_ssn());
8294   SCOPED_MUTEX_LOCK(lock, ua_session->mutex, this_ethread());
8295   if (ua_session->connection_state.is_state_closed() || ua_session->is_url_pushed(url, url_len)) {
8296     url_obj.destroy();
8297     return TS_ERROR;
8298   }
8299 
8300   HTTPHdr *hptr = &(sm->t_state.hdr_info.client_request);
8301   TSMLoc obj    = reinterpret_cast<TSMLoc>(hptr->m_http);
8302 
8303   MIMEHdrImpl *mh = _hdr_mloc_to_mime_hdr_impl(obj);
8304   MIMEField *f    = mime_hdr_field_find(mh, MIME_FIELD_ACCEPT_ENCODING, MIME_LEN_ACCEPT_ENCODING);
8305   if (!stream->push_promise(url_obj, f)) {
8306     url_obj.destroy();
8307     return TS_ERROR;
8308   }
8309 
8310   ua_session->add_url_to_pushed_table(url, url_len);
8311 
8312   url_obj.destroy();
8313   return TS_SUCCESS;
8314 }
8315 
8316 TSReturnCode
TSHttpTxnClientStreamIdGet(TSHttpTxn txnp,uint64_t * stream_id)8317 TSHttpTxnClientStreamIdGet(TSHttpTxn txnp, uint64_t *stream_id)
8318 {
8319   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
8320   sdk_assert(stream_id != nullptr);
8321 
8322   auto *sm     = reinterpret_cast<HttpSM *>(txnp);
8323   auto *stream = dynamic_cast<Http2Stream *>(sm->ua_txn);
8324   if (stream == nullptr) {
8325     return TS_ERROR;
8326   }
8327   *stream_id = stream->get_id();
8328   return TS_SUCCESS;
8329 }
8330 
8331 TSReturnCode
TSHttpTxnClientStreamPriorityGet(TSHttpTxn txnp,TSHttpPriority * priority)8332 TSHttpTxnClientStreamPriorityGet(TSHttpTxn txnp, TSHttpPriority *priority)
8333 {
8334   static_assert(sizeof(TSHttpPriority) >= sizeof(TSHttp2Priority),
8335                 "TSHttpPriorityType is incorrectly smaller than TSHttp2Priority.");
8336   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
8337   sdk_assert(priority != nullptr);
8338 
8339   auto *sm     = reinterpret_cast<HttpSM *>(txnp);
8340   auto *stream = dynamic_cast<Http2Stream *>(sm->ua_txn);
8341   if (stream == nullptr) {
8342     return TS_ERROR;
8343   }
8344 
8345   auto *priority_out              = reinterpret_cast<TSHttp2Priority *>(priority);
8346   priority_out->priority_type     = HTTP_PRIORITY_TYPE_HTTP_2;
8347   priority_out->stream_dependency = stream->get_transaction_priority_dependence();
8348   priority_out->weight            = stream->get_transaction_priority_weight();
8349 
8350   return TS_SUCCESS;
8351 }
8352 
8353 TSReturnCode
TSAIORead(int fd,off_t offset,char * buf,size_t buffSize,TSCont contp)8354 TSAIORead(int fd, off_t offset, char *buf, size_t buffSize, TSCont contp)
8355 {
8356   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
8357 
8358   Continuation *pCont = (Continuation *)contp;
8359   AIOCallback *pAIO   = new_AIOCallback();
8360 
8361   if (pAIO == nullptr) {
8362     return TS_ERROR;
8363   }
8364 
8365   pAIO->aiocb.aio_fildes = fd;
8366   pAIO->aiocb.aio_offset = offset;
8367   pAIO->aiocb.aio_nbytes = buffSize;
8368 
8369   pAIO->aiocb.aio_buf = buf;
8370   pAIO->action        = pCont;
8371   pAIO->thread        = pCont->mutex->thread_holding;
8372 
8373   if (ink_aio_read(pAIO, 1) == 1) {
8374     return TS_SUCCESS;
8375   }
8376 
8377   return TS_ERROR;
8378 }
8379 
8380 char *
TSAIOBufGet(TSAIOCallback data)8381 TSAIOBufGet(TSAIOCallback data)
8382 {
8383   AIOCallback *pAIO = (AIOCallback *)data;
8384   return (char *)pAIO->aiocb.aio_buf;
8385 }
8386 
8387 int
TSAIONBytesGet(TSAIOCallback data)8388 TSAIONBytesGet(TSAIOCallback data)
8389 {
8390   AIOCallback *pAIO = (AIOCallback *)data;
8391   return (int)pAIO->aio_result;
8392 }
8393 
8394 TSReturnCode
TSAIOWrite(int fd,off_t offset,char * buf,const size_t bufSize,TSCont contp)8395 TSAIOWrite(int fd, off_t offset, char *buf, const size_t bufSize, TSCont contp)
8396 {
8397   sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS);
8398 
8399   Continuation *pCont = (Continuation *)contp;
8400   AIOCallback *pAIO   = new_AIOCallback();
8401 
8402   // TODO: Might be able to remove this when allocations can never fail.
8403   sdk_assert(sdk_sanity_check_null_ptr((void *)pAIO) == TS_SUCCESS);
8404 
8405   pAIO->aiocb.aio_fildes = fd;
8406   pAIO->aiocb.aio_offset = offset;
8407   pAIO->aiocb.aio_buf    = buf;
8408   pAIO->aiocb.aio_nbytes = bufSize;
8409   pAIO->action           = pCont;
8410   pAIO->thread           = pCont->mutex->thread_holding;
8411 
8412   if (ink_aio_write(pAIO, 1) == 1) {
8413     return TS_SUCCESS;
8414   }
8415 
8416   return TS_ERROR;
8417 }
8418 
8419 TSReturnCode
TSAIOThreadNumSet(int thread_num)8420 TSAIOThreadNumSet(int thread_num)
8421 {
8422 #if AIO_MODE == AIO_MODE_NATIVE
8423   (void)thread_num;
8424   return TS_SUCCESS;
8425 #else
8426   if (ink_aio_thread_num_set(thread_num)) {
8427     return TS_SUCCESS;
8428   }
8429 
8430   return TS_ERROR;
8431 #endif
8432 }
8433 
8434 void
TSRecordDump(int rec_type,TSRecordDumpCb callback,void * edata)8435 TSRecordDump(int rec_type, TSRecordDumpCb callback, void *edata)
8436 {
8437   RecDumpRecords((RecT)rec_type, (RecDumpEntryCb)callback, edata);
8438 }
8439 
8440 /* ability to skip the remap phase of the State Machine
8441    this only really makes sense in TS_HTTP_READ_REQUEST_HDR_HOOK
8442 */
8443 void
TSSkipRemappingSet(TSHttpTxn txnp,int flag)8444 TSSkipRemappingSet(TSHttpTxn txnp, int flag)
8445 {
8446   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
8447 
8448   HttpSM *sm                         = (HttpSM *)txnp;
8449   sm->t_state.api_skip_all_remapping = (flag != 0);
8450 }
8451 
8452 /* These are the default converter function sets for management data types. If those are used the
8453  * proper converters can be determined here. For other types the converters must be explicitly
8454  * specified.
8455  *
8456  * The purpose of these are to allow configuration elements to not be management types but more
8457  * natural types (e.g., an enumeration can be the actual enumeration, not an @c MgmtInt that needs
8458  * frequent casting). In effect the converter does the casting for the plugin API, isolating that
8459  * to this API handling, with the rest of the code base using the natural types.
8460  */
8461 
8462 /// Unhandled API conversions.
8463 /// Because the code around the specially handled types still uses this in the default case,
8464 /// it must compile for those cases. To indicate unhandled, return @c nullptr for @a conv.
8465 /// @internal This should be a temporary state, eventually the other cases should be handled
8466 /// via specializations here.
8467 /// @internal C++ note - THIS MUST BE FIRST IN THE DECLARATIONS or it might be falsely used.
8468 template <typename T>
8469 inline void *
_memberp_to_generic(T * ptr,MgmtConverter const * & conv)8470 _memberp_to_generic(T *ptr, MgmtConverter const *&conv)
8471 {
8472   conv = nullptr;
8473   return ptr;
8474 }
8475 
8476 /// API conversion for @c MgmtInt, identify conversion as integer.
8477 inline void *
_memberp_to_generic(MgmtInt * ptr,MgmtConverter const * & conv)8478 _memberp_to_generic(MgmtInt *ptr, MgmtConverter const *&conv)
8479 {
8480   static const MgmtConverter converter([](const void *data) -> MgmtInt { return *static_cast<const MgmtInt *>(data); },
8481                                        [](void *data, MgmtInt i) -> void { *static_cast<MgmtInt *>(data) = i; });
8482 
8483   conv = &converter;
8484   return ptr;
8485 }
8486 
8487 /// API conversion for @c MgmtByte, handles integer / byte size differences.
8488 inline void *
_memberp_to_generic(MgmtByte * ptr,MgmtConverter const * & conv)8489 _memberp_to_generic(MgmtByte *ptr, MgmtConverter const *&conv)
8490 {
8491   static const MgmtConverter converter{[](const void *data) -> MgmtInt { return *static_cast<const MgmtByte *>(data); },
8492                                        [](void *data, MgmtInt i) -> void { *static_cast<MgmtByte *>(data) = i; }};
8493 
8494   conv = &converter;
8495   return ptr;
8496 }
8497 
8498 /// API conversion for @c MgmtFloat, identity conversion as float.
8499 inline void *
_memberp_to_generic(MgmtFloat * ptr,MgmtConverter const * & conv)8500 _memberp_to_generic(MgmtFloat *ptr, MgmtConverter const *&conv)
8501 {
8502   static const MgmtConverter converter{[](const void *data) -> MgmtFloat { return *static_cast<const MgmtFloat *>(data); },
8503                                        [](void *data, MgmtFloat f) -> void { *static_cast<MgmtFloat *>(data) = f; }};
8504 
8505   conv = &converter;
8506   return ptr;
8507 }
8508 
8509 /// API conversion for arbitrary enum.
8510 /// Handle casting to and from the enum type @a E.
8511 template <typename E>
8512 inline auto
_memberp_to_generic(MgmtFloat * ptr,MgmtConverter const * & conv)8513 _memberp_to_generic(MgmtFloat *ptr, MgmtConverter const *&conv) -> typename std::enable_if<std::is_enum<E>::value, void *>::type
8514 {
8515   static const MgmtConverter converter{
8516     [](const void *data) -> MgmtInt { return static_cast<MgmtInt>(*static_cast<const E *>(data)); },
8517     [](void *data, MgmtInt i) -> void { *static_cast<E *>(data) = static_cast<E>(i); }};
8518 
8519   conv = &converter;
8520   return ptr;
8521 }
8522 
8523 // Little helper function to find the struct member
8524 static void *
_conf_to_memberp(TSOverridableConfigKey conf,OverridableHttpConfigParams * overridableHttpConfig,MgmtConverter const * & conv)8525 _conf_to_memberp(TSOverridableConfigKey conf, OverridableHttpConfigParams *overridableHttpConfig, MgmtConverter const *&conv)
8526 {
8527   void *ret = nullptr;
8528   conv      = nullptr;
8529 
8530   switch (conf) {
8531   case TS_CONFIG_URL_REMAP_PRISTINE_HOST_HDR:
8532     ret = _memberp_to_generic(&overridableHttpConfig->maintain_pristine_host_hdr, conv);
8533     break;
8534   case TS_CONFIG_HTTP_CHUNKING_ENABLED:
8535     ret = _memberp_to_generic(&overridableHttpConfig->chunking_enabled, conv);
8536     break;
8537   case TS_CONFIG_HTTP_NEGATIVE_CACHING_ENABLED:
8538     ret = _memberp_to_generic(&overridableHttpConfig->negative_caching_enabled, conv);
8539     break;
8540   case TS_CONFIG_HTTP_NEGATIVE_CACHING_LIFETIME:
8541     ret = _memberp_to_generic(&overridableHttpConfig->negative_caching_lifetime, conv);
8542     break;
8543   case TS_CONFIG_HTTP_CACHE_WHEN_TO_REVALIDATE:
8544     ret = _memberp_to_generic(&overridableHttpConfig->cache_when_to_revalidate, conv);
8545     break;
8546   case TS_CONFIG_HTTP_KEEP_ALIVE_ENABLED_IN:
8547     ret = _memberp_to_generic(&overridableHttpConfig->keep_alive_enabled_in, conv);
8548     break;
8549   case TS_CONFIG_HTTP_KEEP_ALIVE_ENABLED_OUT:
8550     ret = _memberp_to_generic(&overridableHttpConfig->keep_alive_enabled_out, conv);
8551     break;
8552   case TS_CONFIG_HTTP_KEEP_ALIVE_POST_OUT:
8553     ret = _memberp_to_generic(&overridableHttpConfig->keep_alive_post_out, conv);
8554     break;
8555   case TS_CONFIG_HTTP_SERVER_SESSION_SHARING_MATCH:
8556     ret = _memberp_to_generic(&overridableHttpConfig->server_session_sharing_match, conv);
8557     break;
8558   case TS_CONFIG_NET_SOCK_RECV_BUFFER_SIZE_OUT:
8559     ret = _memberp_to_generic(&overridableHttpConfig->sock_recv_buffer_size_out, conv);
8560     break;
8561   case TS_CONFIG_NET_SOCK_SEND_BUFFER_SIZE_OUT:
8562     ret = _memberp_to_generic(&overridableHttpConfig->sock_send_buffer_size_out, conv);
8563     break;
8564   case TS_CONFIG_NET_SOCK_OPTION_FLAG_OUT:
8565     ret = _memberp_to_generic(&overridableHttpConfig->sock_option_flag_out, conv);
8566     break;
8567   case TS_CONFIG_HTTP_FORWARD_PROXY_AUTH_TO_PARENT:
8568     ret = _memberp_to_generic(&overridableHttpConfig->fwd_proxy_auth_to_parent, conv);
8569     break;
8570   case TS_CONFIG_HTTP_ANONYMIZE_REMOVE_FROM:
8571     ret = _memberp_to_generic(&overridableHttpConfig->anonymize_remove_from, conv);
8572     break;
8573   case TS_CONFIG_HTTP_ANONYMIZE_REMOVE_REFERER:
8574     ret = _memberp_to_generic(&overridableHttpConfig->anonymize_remove_referer, conv);
8575     break;
8576   case TS_CONFIG_HTTP_ANONYMIZE_REMOVE_USER_AGENT:
8577     ret = _memberp_to_generic(&overridableHttpConfig->anonymize_remove_user_agent, conv);
8578     break;
8579   case TS_CONFIG_HTTP_ANONYMIZE_REMOVE_COOKIE:
8580     ret = _memberp_to_generic(&overridableHttpConfig->anonymize_remove_cookie, conv);
8581     break;
8582   case TS_CONFIG_HTTP_ANONYMIZE_REMOVE_CLIENT_IP:
8583     ret = _memberp_to_generic(&overridableHttpConfig->anonymize_remove_client_ip, conv);
8584     break;
8585   case TS_CONFIG_HTTP_ANONYMIZE_INSERT_CLIENT_IP:
8586     ret = _memberp_to_generic(&overridableHttpConfig->anonymize_insert_client_ip, conv);
8587     break;
8588   case TS_CONFIG_HTTP_RESPONSE_SERVER_ENABLED:
8589     ret = _memberp_to_generic(&overridableHttpConfig->proxy_response_server_enabled, conv);
8590     break;
8591   case TS_CONFIG_HTTP_INSERT_SQUID_X_FORWARDED_FOR:
8592     ret = _memberp_to_generic(&overridableHttpConfig->insert_squid_x_forwarded_for, conv);
8593     break;
8594   case TS_CONFIG_HTTP_INSERT_FORWARDED:
8595     ret = _memberp_to_generic(&overridableHttpConfig->insert_forwarded, conv);
8596     break;
8597   case TS_CONFIG_HTTP_PROXY_PROTOCOL_OUT:
8598     ret = _memberp_to_generic(&overridableHttpConfig->proxy_protocol_out, conv);
8599     break;
8600   case TS_CONFIG_HTTP_SEND_HTTP11_REQUESTS:
8601     ret = _memberp_to_generic(&overridableHttpConfig->send_http11_requests, conv);
8602     break;
8603   case TS_CONFIG_HTTP_CACHE_HTTP:
8604     ret = _memberp_to_generic(&overridableHttpConfig->cache_http, conv);
8605     break;
8606   case TS_CONFIG_HTTP_CACHE_IGNORE_CLIENT_NO_CACHE:
8607     ret = _memberp_to_generic(&overridableHttpConfig->cache_ignore_client_no_cache, conv);
8608     break;
8609   case TS_CONFIG_HTTP_CACHE_IGNORE_CLIENT_CC_MAX_AGE:
8610     ret = _memberp_to_generic(&overridableHttpConfig->cache_ignore_client_cc_max_age, conv);
8611     break;
8612   case TS_CONFIG_HTTP_CACHE_IMS_ON_CLIENT_NO_CACHE:
8613     ret = _memberp_to_generic(&overridableHttpConfig->cache_ims_on_client_no_cache, conv);
8614     break;
8615   case TS_CONFIG_HTTP_CACHE_IGNORE_SERVER_NO_CACHE:
8616     ret = _memberp_to_generic(&overridableHttpConfig->cache_ignore_server_no_cache, conv);
8617     break;
8618   case TS_CONFIG_HTTP_CACHE_CACHE_RESPONSES_TO_COOKIES:
8619     ret = _memberp_to_generic(&overridableHttpConfig->cache_responses_to_cookies, conv);
8620     break;
8621   case TS_CONFIG_HTTP_CACHE_IGNORE_AUTHENTICATION:
8622     ret = _memberp_to_generic(&overridableHttpConfig->cache_ignore_auth, conv);
8623     break;
8624   case TS_CONFIG_HTTP_CACHE_CACHE_URLS_THAT_LOOK_DYNAMIC:
8625     ret = _memberp_to_generic(&overridableHttpConfig->cache_urls_that_look_dynamic, conv);
8626     break;
8627   case TS_CONFIG_HTTP_CACHE_REQUIRED_HEADERS:
8628     ret = _memberp_to_generic(&overridableHttpConfig->cache_required_headers, conv);
8629     break;
8630   case TS_CONFIG_HTTP_INSERT_REQUEST_VIA_STR:
8631     ret = _memberp_to_generic(&overridableHttpConfig->insert_request_via_string, conv);
8632     break;
8633   case TS_CONFIG_HTTP_INSERT_RESPONSE_VIA_STR:
8634     ret = _memberp_to_generic(&overridableHttpConfig->insert_response_via_string, conv);
8635     break;
8636   case TS_CONFIG_HTTP_CACHE_HEURISTIC_MIN_LIFETIME:
8637     ret = _memberp_to_generic(&overridableHttpConfig->cache_heuristic_min_lifetime, conv);
8638     break;
8639   case TS_CONFIG_HTTP_CACHE_HEURISTIC_MAX_LIFETIME:
8640     ret = _memberp_to_generic(&overridableHttpConfig->cache_heuristic_max_lifetime, conv);
8641     break;
8642   case TS_CONFIG_HTTP_CACHE_GUARANTEED_MIN_LIFETIME:
8643     ret = _memberp_to_generic(&overridableHttpConfig->cache_guaranteed_min_lifetime, conv);
8644     break;
8645   case TS_CONFIG_HTTP_CACHE_GUARANTEED_MAX_LIFETIME:
8646     ret = _memberp_to_generic(&overridableHttpConfig->cache_guaranteed_max_lifetime, conv);
8647     break;
8648   case TS_CONFIG_HTTP_CACHE_MAX_STALE_AGE:
8649     ret = _memberp_to_generic(&overridableHttpConfig->cache_max_stale_age, conv);
8650     break;
8651   case TS_CONFIG_HTTP_KEEP_ALIVE_NO_ACTIVITY_TIMEOUT_IN:
8652     ret = _memberp_to_generic(&overridableHttpConfig->keep_alive_no_activity_timeout_in, conv);
8653     break;
8654   case TS_CONFIG_HTTP_KEEP_ALIVE_NO_ACTIVITY_TIMEOUT_OUT:
8655     ret = _memberp_to_generic(&overridableHttpConfig->keep_alive_no_activity_timeout_out, conv);
8656     break;
8657   case TS_CONFIG_HTTP_TRANSACTION_NO_ACTIVITY_TIMEOUT_IN:
8658     ret = _memberp_to_generic(&overridableHttpConfig->transaction_no_activity_timeout_in, conv);
8659     break;
8660   case TS_CONFIG_HTTP_TRANSACTION_NO_ACTIVITY_TIMEOUT_OUT:
8661     ret = _memberp_to_generic(&overridableHttpConfig->transaction_no_activity_timeout_out, conv);
8662     break;
8663   case TS_CONFIG_HTTP_TRANSACTION_ACTIVE_TIMEOUT_OUT:
8664     ret = _memberp_to_generic(&overridableHttpConfig->transaction_active_timeout_out, conv);
8665     break;
8666   case TS_CONFIG_HTTP_CONNECT_ATTEMPTS_MAX_RETRIES:
8667     ret = _memberp_to_generic(&overridableHttpConfig->connect_attempts_max_retries, conv);
8668     break;
8669   case TS_CONFIG_HTTP_CONNECT_ATTEMPTS_MAX_RETRIES_DEAD_SERVER:
8670     ret = _memberp_to_generic(&overridableHttpConfig->connect_attempts_max_retries_dead_server, conv);
8671     break;
8672   case TS_CONFIG_HTTP_CONNECT_DEAD_POLICY:
8673     ret = _memberp_to_generic(&overridableHttpConfig->connect_dead_policy, conv);
8674     break;
8675   case TS_CONFIG_HTTP_CONNECT_ATTEMPTS_RR_RETRIES:
8676     ret = _memberp_to_generic(&overridableHttpConfig->connect_attempts_rr_retries, conv);
8677     break;
8678   case TS_CONFIG_HTTP_CONNECT_ATTEMPTS_TIMEOUT:
8679     ret = _memberp_to_generic(&overridableHttpConfig->connect_attempts_timeout, conv);
8680     break;
8681   case TS_CONFIG_HTTP_POST_CONNECT_ATTEMPTS_TIMEOUT:
8682     ret = _memberp_to_generic(&overridableHttpConfig->post_connect_attempts_timeout, conv);
8683     break;
8684   case TS_CONFIG_HTTP_DOWN_SERVER_CACHE_TIME:
8685     ret = _memberp_to_generic(&overridableHttpConfig->down_server_timeout, conv);
8686     break;
8687   case TS_CONFIG_HTTP_DOWN_SERVER_ABORT_THRESHOLD:
8688     ret = _memberp_to_generic(&overridableHttpConfig->client_abort_threshold, conv);
8689     break;
8690   case TS_CONFIG_HTTP_DOC_IN_CACHE_SKIP_DNS:
8691     ret = _memberp_to_generic(&overridableHttpConfig->doc_in_cache_skip_dns, conv);
8692     break;
8693   case TS_CONFIG_HTTP_BACKGROUND_FILL_ACTIVE_TIMEOUT:
8694     ret = _memberp_to_generic(&overridableHttpConfig->background_fill_active_timeout, conv);
8695     break;
8696   case TS_CONFIG_HTTP_RESPONSE_SERVER_STR:
8697     ret = _memberp_to_generic(&overridableHttpConfig->proxy_response_server_string, conv);
8698     break;
8699   case TS_CONFIG_HTTP_CACHE_HEURISTIC_LM_FACTOR:
8700     ret = _memberp_to_generic(&overridableHttpConfig->cache_heuristic_lm_factor, conv);
8701     break;
8702   case TS_CONFIG_HTTP_BACKGROUND_FILL_COMPLETED_THRESHOLD:
8703     ret = _memberp_to_generic(&overridableHttpConfig->background_fill_threshold, conv);
8704     break;
8705   case TS_CONFIG_NET_SOCK_PACKET_MARK_OUT:
8706     ret = _memberp_to_generic(&overridableHttpConfig->sock_packet_mark_out, conv);
8707     break;
8708   case TS_CONFIG_NET_SOCK_PACKET_TOS_OUT:
8709     ret = _memberp_to_generic(&overridableHttpConfig->sock_packet_tos_out, conv);
8710     break;
8711   case TS_CONFIG_HTTP_INSERT_AGE_IN_RESPONSE:
8712     ret = _memberp_to_generic(&overridableHttpConfig->insert_age_in_response, conv);
8713     break;
8714   case TS_CONFIG_HTTP_CHUNKING_SIZE:
8715     ret = _memberp_to_generic(&overridableHttpConfig->http_chunking_size, conv);
8716     break;
8717   case TS_CONFIG_HTTP_FLOW_CONTROL_ENABLED:
8718     ret = _memberp_to_generic(&overridableHttpConfig->flow_control_enabled, conv);
8719     break;
8720   case TS_CONFIG_HTTP_FLOW_CONTROL_LOW_WATER_MARK:
8721     ret = _memberp_to_generic(&overridableHttpConfig->flow_low_water_mark, conv);
8722     break;
8723   case TS_CONFIG_HTTP_FLOW_CONTROL_HIGH_WATER_MARK:
8724     ret = _memberp_to_generic(&overridableHttpConfig->flow_high_water_mark, conv);
8725     break;
8726   case TS_CONFIG_HTTP_CACHE_RANGE_LOOKUP:
8727     ret = _memberp_to_generic(&overridableHttpConfig->cache_range_lookup, conv);
8728     break;
8729   case TS_CONFIG_HTTP_NORMALIZE_AE:
8730     ret = _memberp_to_generic(&overridableHttpConfig->normalize_ae, conv);
8731     break;
8732   case TS_CONFIG_HTTP_DEFAULT_BUFFER_SIZE:
8733     ret = _memberp_to_generic(&overridableHttpConfig->default_buffer_size_index, conv);
8734     break;
8735   case TS_CONFIG_HTTP_DEFAULT_BUFFER_WATER_MARK:
8736     ret = _memberp_to_generic(&overridableHttpConfig->default_buffer_water_mark, conv);
8737     break;
8738   case TS_CONFIG_HTTP_REQUEST_HEADER_MAX_SIZE:
8739     ret = _memberp_to_generic(&overridableHttpConfig->request_hdr_max_size, conv);
8740     break;
8741   case TS_CONFIG_HTTP_RESPONSE_HEADER_MAX_SIZE:
8742     ret = _memberp_to_generic(&overridableHttpConfig->response_hdr_max_size, conv);
8743     break;
8744   case TS_CONFIG_HTTP_NEGATIVE_REVALIDATING_ENABLED:
8745     ret = _memberp_to_generic(&overridableHttpConfig->negative_revalidating_enabled, conv);
8746     break;
8747   case TS_CONFIG_HTTP_NEGATIVE_REVALIDATING_LIFETIME:
8748     ret = _memberp_to_generic(&overridableHttpConfig->negative_revalidating_lifetime, conv);
8749     break;
8750   case TS_CONFIG_SSL_HSTS_MAX_AGE:
8751     ret = _memberp_to_generic(&overridableHttpConfig->proxy_response_hsts_max_age, conv);
8752     break;
8753   case TS_CONFIG_SSL_HSTS_INCLUDE_SUBDOMAINS:
8754     ret = _memberp_to_generic(&overridableHttpConfig->proxy_response_hsts_include_subdomains, conv);
8755     break;
8756   case TS_CONFIG_HTTP_CACHE_OPEN_READ_RETRY_TIME:
8757     ret = _memberp_to_generic(&overridableHttpConfig->cache_open_read_retry_time, conv);
8758     break;
8759   case TS_CONFIG_HTTP_CACHE_MAX_OPEN_READ_RETRIES:
8760     ret = _memberp_to_generic(&overridableHttpConfig->max_cache_open_read_retries, conv);
8761     break;
8762   case TS_CONFIG_HTTP_CACHE_RANGE_WRITE:
8763     ret = _memberp_to_generic(&overridableHttpConfig->cache_range_write, conv);
8764     break;
8765   case TS_CONFIG_HTTP_POST_CHECK_CONTENT_LENGTH_ENABLED:
8766     ret = _memberp_to_generic(&overridableHttpConfig->post_check_content_length_enabled, conv);
8767     break;
8768   case TS_CONFIG_HTTP_REQUEST_BUFFER_ENABLED:
8769     ret = _memberp_to_generic(&overridableHttpConfig->request_buffer_enabled, conv);
8770     break;
8771   case TS_CONFIG_HTTP_GLOBAL_USER_AGENT_HEADER:
8772     ret = _memberp_to_generic(&overridableHttpConfig->global_user_agent_header, conv);
8773     break;
8774   case TS_CONFIG_HTTP_AUTH_SERVER_SESSION_PRIVATE:
8775     ret = _memberp_to_generic(&overridableHttpConfig->auth_server_session_private, conv);
8776     break;
8777   case TS_CONFIG_HTTP_SLOW_LOG_THRESHOLD:
8778     ret = _memberp_to_generic(&overridableHttpConfig->slow_log_threshold, conv);
8779     break;
8780   case TS_CONFIG_HTTP_CACHE_GENERATION:
8781     ret = _memberp_to_generic(&overridableHttpConfig->cache_generation_number, conv);
8782     break;
8783   case TS_CONFIG_BODY_FACTORY_TEMPLATE_BASE:
8784     ret = _memberp_to_generic(&overridableHttpConfig->body_factory_template_base, conv);
8785     break;
8786   case TS_CONFIG_HTTP_CACHE_OPEN_WRITE_FAIL_ACTION:
8787     ret = _memberp_to_generic(&overridableHttpConfig->cache_open_write_fail_action, conv);
8788     break;
8789   case TS_CONFIG_HTTP_NUMBER_OF_REDIRECTIONS:
8790     ret = _memberp_to_generic(&overridableHttpConfig->number_of_redirections, conv);
8791     break;
8792   case TS_CONFIG_HTTP_CACHE_MAX_OPEN_WRITE_RETRIES:
8793     ret = _memberp_to_generic(&overridableHttpConfig->max_cache_open_write_retries, conv);
8794     break;
8795   case TS_CONFIG_HTTP_REDIRECT_USE_ORIG_CACHE_KEY:
8796     ret = _memberp_to_generic(&overridableHttpConfig->redirect_use_orig_cache_key, conv);
8797     break;
8798   case TS_CONFIG_HTTP_ATTACH_SERVER_SESSION_TO_CLIENT:
8799     ret = _memberp_to_generic(&overridableHttpConfig->attach_server_session_to_client, conv);
8800     break;
8801   case TS_CONFIG_WEBSOCKET_NO_ACTIVITY_TIMEOUT:
8802     ret = _memberp_to_generic(&overridableHttpConfig->websocket_inactive_timeout, conv);
8803     break;
8804   case TS_CONFIG_WEBSOCKET_ACTIVE_TIMEOUT:
8805     ret = _memberp_to_generic(&overridableHttpConfig->websocket_active_timeout, conv);
8806     break;
8807   case TS_CONFIG_HTTP_UNCACHEABLE_REQUESTS_BYPASS_PARENT:
8808     ret = _memberp_to_generic(&overridableHttpConfig->uncacheable_requests_bypass_parent, conv);
8809     break;
8810   case TS_CONFIG_HTTP_PARENT_PROXY_TOTAL_CONNECT_ATTEMPTS:
8811     ret = _memberp_to_generic(&overridableHttpConfig->parent_connect_attempts, conv);
8812     break;
8813   case TS_CONFIG_HTTP_TRANSACTION_ACTIVE_TIMEOUT_IN:
8814     ret = _memberp_to_generic(&overridableHttpConfig->transaction_active_timeout_in, conv);
8815     break;
8816   case TS_CONFIG_SRV_ENABLED:
8817     ret = _memberp_to_generic(&overridableHttpConfig->srv_enabled, conv);
8818     break;
8819   case TS_CONFIG_HTTP_FORWARD_CONNECT_METHOD:
8820     ret = _memberp_to_generic(&overridableHttpConfig->forward_connect_method, conv);
8821     break;
8822   case TS_CONFIG_SSL_CLIENT_VERIFY_SERVER:
8823     ret = _memberp_to_generic(&overridableHttpConfig->ssl_client_verify_server, conv);
8824     break;
8825   case TS_CONFIG_SSL_CLIENT_VERIFY_SERVER_POLICY:
8826   case TS_CONFIG_SSL_CLIENT_VERIFY_SERVER_PROPERTIES:
8827   case TS_CONFIG_SSL_CLIENT_SNI_POLICY:
8828   case TS_CONFIG_SSL_CLIENT_CERT_FILENAME:
8829   case TS_CONFIG_SSL_CERT_FILEPATH:
8830   case TS_CONFIG_SSL_CLIENT_PRIVATE_KEY_FILENAME:
8831   case TS_CONFIG_SSL_CLIENT_CA_CERT_FILENAME:
8832     // String, must be handled elsewhere
8833     break;
8834   case TS_CONFIG_PARENT_FAILURES_UPDATE_HOSTDB:
8835     ret = _memberp_to_generic(&overridableHttpConfig->parent_failures_update_hostdb, conv);
8836     break;
8837   case TS_CONFIG_HTTP_CACHE_IGNORE_ACCEPT_MISMATCH:
8838     ret = _memberp_to_generic(&overridableHttpConfig->ignore_accept_mismatch, conv);
8839     break;
8840   case TS_CONFIG_HTTP_CACHE_IGNORE_ACCEPT_LANGUAGE_MISMATCH:
8841     ret = _memberp_to_generic(&overridableHttpConfig->ignore_accept_language_mismatch, conv);
8842     break;
8843   case TS_CONFIG_HTTP_CACHE_IGNORE_ACCEPT_ENCODING_MISMATCH:
8844     ret = _memberp_to_generic(&overridableHttpConfig->ignore_accept_encoding_mismatch, conv);
8845     break;
8846   case TS_CONFIG_HTTP_CACHE_IGNORE_ACCEPT_CHARSET_MISMATCH:
8847     ret = _memberp_to_generic(&overridableHttpConfig->ignore_accept_charset_mismatch, conv);
8848     break;
8849   case TS_CONFIG_HTTP_PARENT_PROXY_FAIL_THRESHOLD:
8850     ret = _memberp_to_generic(&overridableHttpConfig->parent_fail_threshold, conv);
8851     break;
8852   case TS_CONFIG_HTTP_PARENT_PROXY_RETRY_TIME:
8853     ret = _memberp_to_generic(&overridableHttpConfig->parent_retry_time, conv);
8854     break;
8855   case TS_CONFIG_HTTP_PER_PARENT_CONNECT_ATTEMPTS:
8856     ret = _memberp_to_generic(&overridableHttpConfig->per_parent_connect_attempts, conv);
8857     break;
8858   case TS_CONFIG_HTTP_PARENT_CONNECT_ATTEMPT_TIMEOUT:
8859     ret = _memberp_to_generic(&overridableHttpConfig->parent_connect_timeout, conv);
8860     break;
8861   case TS_CONFIG_HTTP_ALLOW_MULTI_RANGE:
8862     ret = _memberp_to_generic(&overridableHttpConfig->allow_multi_range, conv);
8863     break;
8864   case TS_CONFIG_HTTP_ALLOW_HALF_OPEN:
8865     ret = _memberp_to_generic(&overridableHttpConfig->allow_half_open, conv);
8866     break;
8867   case TS_CONFIG_HTTP_PER_SERVER_CONNECTION_MAX:
8868     ret  = &overridableHttpConfig->outbound_conntrack.max;
8869     conv = &OutboundConnTrack::MAX_CONV;
8870     break;
8871   case TS_CONFIG_HTTP_SERVER_MIN_KEEP_ALIVE_CONNS:
8872     ret  = &overridableHttpConfig->outbound_conntrack.min;
8873     conv = &OutboundConnTrack::MIN_CONV;
8874     break;
8875   case TS_CONFIG_HTTP_PER_SERVER_CONNECTION_MATCH:
8876     ret  = &overridableHttpConfig->outbound_conntrack.match;
8877     conv = &OutboundConnTrack::MATCH_CONV;
8878     break;
8879   case TS_CONFIG_HTTP_HOST_RESOLUTION_PREFERENCE:
8880     ret  = &overridableHttpConfig->host_res_data;
8881     conv = &HttpTransact::HOST_RES_CONV;
8882     break;
8883   // This helps avoiding compiler warnings, yet detect unhandled enum members.
8884   case TS_CONFIG_NULL:
8885   case TS_CONFIG_LAST_ENTRY:
8886     break;
8887   }
8888 
8889   return ret;
8890 }
8891 
8892 // 2nd little helper function to find the struct member for getting.
8893 static const void *
_conf_to_memberp(TSOverridableConfigKey conf,const OverridableHttpConfigParams * overridableHttpConfig,MgmtConverter const * & conv)8894 _conf_to_memberp(TSOverridableConfigKey conf, const OverridableHttpConfigParams *overridableHttpConfig, MgmtConverter const *&conv)
8895 {
8896   return _conf_to_memberp(conf, const_cast<OverridableHttpConfigParams *>(overridableHttpConfig), conv);
8897 }
8898 
8899 /* APIs to manipulate the overridable configuration options.
8900  */
8901 TSReturnCode
TSHttpTxnConfigIntSet(TSHttpTxn txnp,TSOverridableConfigKey conf,TSMgmtInt value)8902 TSHttpTxnConfigIntSet(TSHttpTxn txnp, TSOverridableConfigKey conf, TSMgmtInt value)
8903 {
8904   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
8905 
8906   HttpSM *s = reinterpret_cast<HttpSM *>(txnp);
8907   MgmtConverter const *conv;
8908 
8909   s->t_state.setup_per_txn_configs();
8910 
8911   void *dest = _conf_to_memberp(conf, &(s->t_state.my_txn_conf()), conv);
8912 
8913   if (!dest || !conv->store_int) {
8914     return TS_ERROR;
8915   }
8916 
8917   conv->store_int(dest, value);
8918 
8919   return TS_SUCCESS;
8920 }
8921 
8922 TSReturnCode
TSHttpTxnConfigIntGet(TSHttpTxn txnp,TSOverridableConfigKey conf,TSMgmtInt * value)8923 TSHttpTxnConfigIntGet(TSHttpTxn txnp, TSOverridableConfigKey conf, TSMgmtInt *value)
8924 {
8925   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
8926   sdk_assert(sdk_sanity_check_null_ptr((void *)value) == TS_SUCCESS);
8927 
8928   HttpSM *s = reinterpret_cast<HttpSM *>(txnp);
8929   MgmtConverter const *conv;
8930   const void *src = _conf_to_memberp(conf, s->t_state.txn_conf, conv);
8931 
8932   if (!src || !conv->load_int) {
8933     return TS_ERROR;
8934   }
8935 
8936   *value = conv->load_int(src);
8937 
8938   return TS_SUCCESS;
8939 }
8940 
8941 TSReturnCode
TSHttpTxnConfigFloatSet(TSHttpTxn txnp,TSOverridableConfigKey conf,TSMgmtFloat value)8942 TSHttpTxnConfigFloatSet(TSHttpTxn txnp, TSOverridableConfigKey conf, TSMgmtFloat value)
8943 {
8944   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
8945 
8946   HttpSM *s = reinterpret_cast<HttpSM *>(txnp);
8947   MgmtConverter const *conv;
8948 
8949   s->t_state.setup_per_txn_configs();
8950 
8951   void *dest = _conf_to_memberp(conf, &(s->t_state.my_txn_conf()), conv);
8952 
8953   if (!dest || !conv->store_float) {
8954     return TS_ERROR;
8955   }
8956 
8957   conv->store_float(dest, value);
8958 
8959   return TS_SUCCESS;
8960 }
8961 
8962 TSReturnCode
TSHttpTxnConfigFloatGet(TSHttpTxn txnp,TSOverridableConfigKey conf,TSMgmtFloat * value)8963 TSHttpTxnConfigFloatGet(TSHttpTxn txnp, TSOverridableConfigKey conf, TSMgmtFloat *value)
8964 {
8965   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
8966   sdk_assert(sdk_sanity_check_null_ptr(static_cast<void *>(value)) == TS_SUCCESS);
8967 
8968   MgmtConverter const *conv;
8969   const void *src = _conf_to_memberp(conf, reinterpret_cast<HttpSM *>(txnp)->t_state.txn_conf, conv);
8970 
8971   if (!src || !conv->load_float) {
8972     return TS_ERROR;
8973   }
8974   *value = conv->load_float(src);
8975 
8976   return TS_SUCCESS;
8977 }
8978 
8979 TSReturnCode
TSHttpTxnConfigStringSet(TSHttpTxn txnp,TSOverridableConfigKey conf,const char * value,int length)8980 TSHttpTxnConfigStringSet(TSHttpTxn txnp, TSOverridableConfigKey conf, const char *value, int length)
8981 {
8982   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
8983 
8984   if (length == -1) {
8985     length = strlen(value);
8986   }
8987 
8988   HttpSM *s = reinterpret_cast<HttpSM *>(txnp);
8989 
8990   s->t_state.setup_per_txn_configs();
8991 
8992   switch (conf) {
8993   case TS_CONFIG_HTTP_RESPONSE_SERVER_STR:
8994     if (value && length > 0) {
8995       s->t_state.my_txn_conf().proxy_response_server_string     = const_cast<char *>(value); // The "core" likes non-const char*
8996       s->t_state.my_txn_conf().proxy_response_server_string_len = length;
8997     } else {
8998       s->t_state.my_txn_conf().proxy_response_server_string     = nullptr;
8999       s->t_state.my_txn_conf().proxy_response_server_string_len = 0;
9000     }
9001     break;
9002   case TS_CONFIG_HTTP_GLOBAL_USER_AGENT_HEADER:
9003     if (value && length > 0) {
9004       s->t_state.my_txn_conf().global_user_agent_header      = const_cast<char *>(value); // The "core" likes non-const char*
9005       s->t_state.my_txn_conf().global_user_agent_header_size = length;
9006     } else {
9007       s->t_state.my_txn_conf().global_user_agent_header      = nullptr;
9008       s->t_state.my_txn_conf().global_user_agent_header_size = 0;
9009     }
9010     break;
9011   case TS_CONFIG_BODY_FACTORY_TEMPLATE_BASE:
9012     if (value && length > 0) {
9013       s->t_state.my_txn_conf().body_factory_template_base     = const_cast<char *>(value);
9014       s->t_state.my_txn_conf().body_factory_template_base_len = length;
9015     } else {
9016       s->t_state.my_txn_conf().body_factory_template_base     = nullptr;
9017       s->t_state.my_txn_conf().body_factory_template_base_len = 0;
9018     }
9019     break;
9020   case TS_CONFIG_HTTP_INSERT_FORWARDED:
9021     if (value && length > 0) {
9022       ts::LocalBufferWriter<1024> error;
9023       HttpForwarded::OptionBitSet bs = HttpForwarded::optStrToBitset(std::string_view(value, length), error);
9024       if (!error.size()) {
9025         s->t_state.my_txn_conf().insert_forwarded = bs;
9026       } else {
9027         Error("HTTP %.*s", static_cast<int>(error.size()), error.data());
9028       }
9029     }
9030     break;
9031   case TS_CONFIG_HTTP_SERVER_SESSION_SHARING_MATCH:
9032     if (value && length > 0) {
9033       HttpConfig::load_server_session_sharing_match(value, s->t_state.my_txn_conf().server_session_sharing_match);
9034       s->t_state.my_txn_conf().server_session_sharing_match_str = const_cast<char *>(value);
9035     }
9036     break;
9037   case TS_CONFIG_SSL_CLIENT_VERIFY_SERVER_POLICY:
9038     if (value && length > 0) {
9039       s->t_state.my_txn_conf().ssl_client_verify_server_policy = const_cast<char *>(value);
9040     }
9041     break;
9042   case TS_CONFIG_SSL_CLIENT_VERIFY_SERVER_PROPERTIES:
9043     if (value && length > 0) {
9044       s->t_state.my_txn_conf().ssl_client_verify_server_properties = const_cast<char *>(value);
9045     }
9046     break;
9047   case TS_CONFIG_SSL_CLIENT_SNI_POLICY:
9048     if (value && length > 0) {
9049       s->t_state.my_txn_conf().ssl_client_sni_policy = const_cast<char *>(value);
9050     }
9051     break;
9052   case TS_CONFIG_SSL_CLIENT_CERT_FILENAME:
9053     if (value && length > 0) {
9054       s->t_state.my_txn_conf().ssl_client_cert_filename = const_cast<char *>(value);
9055     }
9056     break;
9057   case TS_CONFIG_SSL_CLIENT_PRIVATE_KEY_FILENAME:
9058     if (value && length > 0) {
9059       s->t_state.my_txn_conf().ssl_client_private_key_filename = const_cast<char *>(value);
9060     }
9061     break;
9062   case TS_CONFIG_SSL_CLIENT_CA_CERT_FILENAME:
9063     if (value && length > 0) {
9064       s->t_state.my_txn_conf().ssl_client_ca_cert_filename = const_cast<char *>(value);
9065     }
9066     break;
9067   case TS_CONFIG_SSL_CERT_FILEPATH:
9068     /* noop */
9069     break;
9070   case TS_CONFIG_HTTP_HOST_RESOLUTION_PREFERENCE:
9071     if (value && length > 0) {
9072       s->t_state.my_txn_conf().host_res_data.conf_value = const_cast<char *>(value);
9073     }
9074     [[fallthrough]];
9075   default: {
9076     MgmtConverter const *conv;
9077     void *dest = _conf_to_memberp(conf, &(s->t_state.my_txn_conf()), conv);
9078     if (dest != nullptr && conv != nullptr && conv->store_string) {
9079       conv->store_string(dest, std::string_view(value, length));
9080     } else {
9081       return TS_ERROR;
9082     }
9083     break;
9084   }
9085   }
9086 
9087   return TS_SUCCESS;
9088 }
9089 
9090 TSReturnCode
TSHttpTxnConfigStringGet(TSHttpTxn txnp,TSOverridableConfigKey conf,const char ** value,int * length)9091 TSHttpTxnConfigStringGet(TSHttpTxn txnp, TSOverridableConfigKey conf, const char **value, int *length)
9092 {
9093   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
9094   sdk_assert(sdk_sanity_check_null_ptr((void **)value) == TS_SUCCESS);
9095   sdk_assert(sdk_sanity_check_null_ptr((void *)length) == TS_SUCCESS);
9096 
9097   HttpSM *sm = reinterpret_cast<HttpSM *>(txnp);
9098 
9099   switch (conf) {
9100   case TS_CONFIG_HTTP_RESPONSE_SERVER_STR:
9101     *value  = sm->t_state.txn_conf->proxy_response_server_string;
9102     *length = sm->t_state.txn_conf->proxy_response_server_string_len;
9103     break;
9104   case TS_CONFIG_HTTP_GLOBAL_USER_AGENT_HEADER:
9105     *value  = sm->t_state.txn_conf->global_user_agent_header;
9106     *length = sm->t_state.txn_conf->global_user_agent_header_size;
9107     break;
9108   case TS_CONFIG_BODY_FACTORY_TEMPLATE_BASE:
9109     *value  = sm->t_state.txn_conf->body_factory_template_base;
9110     *length = sm->t_state.txn_conf->body_factory_template_base_len;
9111     break;
9112   case TS_CONFIG_HTTP_SERVER_SESSION_SHARING_MATCH:
9113     *value  = sm->t_state.txn_conf->server_session_sharing_match_str;
9114     *length = *value ? strlen(*value) : 0;
9115     break;
9116   default: {
9117     MgmtConverter const *conv;
9118     const void *src = _conf_to_memberp(conf, sm->t_state.txn_conf, conv);
9119     if (src != nullptr && conv != nullptr && conv->load_string) {
9120       auto sv = conv->load_string(src);
9121       *value  = sv.data();
9122       *length = sv.size();
9123     } else {
9124       return TS_ERROR;
9125     }
9126     break;
9127   }
9128   }
9129 
9130   return TS_SUCCESS;
9131 }
9132 
9133 TSReturnCode
TSHttpTxnConfigFind(const char * name,int length,TSOverridableConfigKey * conf,TSRecordDataType * type)9134 TSHttpTxnConfigFind(const char *name, int length, TSOverridableConfigKey *conf, TSRecordDataType *type)
9135 {
9136   sdk_assert(sdk_sanity_check_null_ptr(name) == TS_SUCCESS);
9137   sdk_assert(sdk_sanity_check_null_ptr(conf) == TS_SUCCESS);
9138 
9139   std::string_view name_sv(name, length < 0 ? strlen(name) : length);
9140   if (auto config = ts::Overridable_Txn_Vars.find(name_sv); config != ts::Overridable_Txn_Vars.end()) {
9141     std::tie(*conf, *type) = config->second;
9142     return TS_SUCCESS;
9143   }
9144 
9145   return TS_ERROR;
9146 }
9147 
9148 TSReturnCode
TSHttpTxnPrivateSessionSet(TSHttpTxn txnp,int private_session)9149 TSHttpTxnPrivateSessionSet(TSHttpTxn txnp, int private_session)
9150 {
9151   if (sdk_sanity_check_txn(txnp) != TS_SUCCESS) {
9152     return TS_ERROR;
9153   }
9154   HttpSM *sm = (HttpSM *)txnp;
9155   if (sm->set_server_session_private(private_session)) {
9156     return TS_SUCCESS;
9157   }
9158   return TS_ERROR;
9159 }
9160 
9161 // APIs to register new Mgmt (records.config) entries.
9162 TSReturnCode
TSMgmtStringCreate(TSRecordType rec_type,const char * name,const TSMgmtString data_default,TSRecordUpdateType update_type,TSRecordCheckType check_type,const char * check_regex,TSRecordAccessType access_type)9163 TSMgmtStringCreate(TSRecordType rec_type, const char *name, const TSMgmtString data_default, TSRecordUpdateType update_type,
9164                    TSRecordCheckType check_type, const char *check_regex, TSRecordAccessType access_type)
9165 {
9166   if (check_regex == nullptr && check_type != TS_RECORDCHECK_NULL) {
9167     return TS_ERROR;
9168   }
9169   if (REC_ERR_OKAY != RecRegisterConfigString((enum RecT)rec_type, name, data_default, (enum RecUpdateT)update_type,
9170                                               (enum RecCheckT)check_type, check_regex, REC_SOURCE_PLUGIN,
9171                                               (enum RecAccessT)access_type)) {
9172     return TS_ERROR;
9173   }
9174 
9175   return TS_SUCCESS;
9176 }
9177 
9178 TSReturnCode
TSMgmtIntCreate(TSRecordType rec_type,const char * name,TSMgmtInt data_default,TSRecordUpdateType update_type,TSRecordCheckType check_type,const char * check_regex,TSRecordAccessType access_type)9179 TSMgmtIntCreate(TSRecordType rec_type, const char *name, TSMgmtInt data_default, TSRecordUpdateType update_type,
9180                 TSRecordCheckType check_type, const char *check_regex, TSRecordAccessType access_type)
9181 {
9182   if (check_regex == nullptr && check_type != TS_RECORDCHECK_NULL) {
9183     return TS_ERROR;
9184   }
9185   if (REC_ERR_OKAY != RecRegisterConfigInt((enum RecT)rec_type, name, (RecInt)data_default, (enum RecUpdateT)update_type,
9186                                            (enum RecCheckT)check_type, check_regex, REC_SOURCE_PLUGIN,
9187                                            (enum RecAccessT)access_type)) {
9188     return TS_ERROR;
9189   }
9190 
9191   return TS_SUCCESS;
9192 }
9193 
9194 TSReturnCode
TSHttpTxnCloseAfterResponse(TSHttpTxn txnp,int should_close)9195 TSHttpTxnCloseAfterResponse(TSHttpTxn txnp, int should_close)
9196 {
9197   if (sdk_sanity_check_txn(txnp) != TS_SUCCESS) {
9198     return TS_ERROR;
9199   }
9200 
9201   HttpSM *sm = (HttpSM *)txnp;
9202   if (should_close) {
9203     sm->t_state.client_info.keep_alive = HTTP_NO_KEEPALIVE;
9204     if (sm->ua_txn) {
9205       sm->set_ua_half_close_flag();
9206     }
9207   }
9208   // Don't change if PIPELINE is set...
9209   else if (sm->t_state.client_info.keep_alive == HTTP_NO_KEEPALIVE) {
9210     sm->t_state.client_info.keep_alive = HTTP_KEEPALIVE;
9211   }
9212 
9213   return TS_SUCCESS;
9214 }
9215 
9216 // Parse a port descriptor for the proxy.config.http.server_ports descriptor format.
9217 TSPortDescriptor
TSPortDescriptorParse(const char * descriptor)9218 TSPortDescriptorParse(const char *descriptor)
9219 {
9220   HttpProxyPort *port = new HttpProxyPort();
9221 
9222   if (descriptor && port->processOptions(descriptor)) {
9223     return (TSPortDescriptor)port;
9224   }
9225 
9226   delete port;
9227   return nullptr;
9228 }
9229 
9230 TSReturnCode
TSPortDescriptorAccept(TSPortDescriptor descp,TSCont contp)9231 TSPortDescriptorAccept(TSPortDescriptor descp, TSCont contp)
9232 {
9233   Action *action      = nullptr;
9234   HttpProxyPort *port = (HttpProxyPort *)descp;
9235   NetProcessor::AcceptOptions net(make_net_accept_options(port, -1 /* nthreads */));
9236 
9237   if (port->isSSL()) {
9238     action = sslNetProcessor.main_accept((INKContInternal *)contp, port->m_fd, net);
9239   } else {
9240     action = netProcessor.main_accept((INKContInternal *)contp, port->m_fd, net);
9241   }
9242 
9243   return action ? TS_SUCCESS : TS_ERROR;
9244 }
9245 
9246 TSReturnCode
TSPluginDescriptorAccept(TSCont contp)9247 TSPluginDescriptorAccept(TSCont contp)
9248 {
9249   Action *action = nullptr;
9250 
9251   HttpProxyPort::Group &proxy_ports = HttpProxyPort::global();
9252   for (auto &port : proxy_ports) {
9253     if (port.isPlugin()) {
9254       NetProcessor::AcceptOptions net(make_net_accept_options(&port, -1 /* nthreads */));
9255       action = netProcessor.main_accept((INKContInternal *)contp, port.m_fd, net);
9256     }
9257   }
9258   return action ? TS_SUCCESS : TS_ERROR;
9259 }
9260 
9261 int
TSHttpTxnBackgroundFillStarted(TSHttpTxn txnp)9262 TSHttpTxnBackgroundFillStarted(TSHttpTxn txnp)
9263 {
9264   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
9265   HttpSM *s = (HttpSM *)txnp;
9266 
9267   return (s->background_fill == BACKGROUND_FILL_STARTED);
9268 }
9269 
9270 int
TSHttpTxnIsCacheable(TSHttpTxn txnp,TSMBuffer request,TSMBuffer response)9271 TSHttpTxnIsCacheable(TSHttpTxn txnp, TSMBuffer request, TSMBuffer response)
9272 {
9273   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
9274   HttpSM *sm = (HttpSM *)txnp;
9275   HTTPHdr *req, *resp;
9276 
9277   // We allow for either request or response to be empty (or both), in
9278   // which case we default to the transactions request or response.
9279   if (request) {
9280     sdk_assert(sdk_sanity_check_mbuffer(request) == TS_SUCCESS);
9281     req = reinterpret_cast<HTTPHdr *>(request);
9282   } else {
9283     req = &(sm->t_state.hdr_info.client_request);
9284   }
9285   if (response) {
9286     sdk_assert(sdk_sanity_check_mbuffer(response) == TS_SUCCESS);
9287     resp = reinterpret_cast<HTTPHdr *>(response);
9288   } else {
9289     resp = &(sm->t_state.hdr_info.server_response);
9290   }
9291 
9292   // Make sure these are valid response / requests, then verify if it's cacheable.
9293   return (req->valid() && resp->valid() && HttpTransact::is_response_cacheable(&(sm->t_state), req, resp)) ? 1 : 0;
9294 }
9295 
9296 int
TSHttpTxnGetMaxAge(TSHttpTxn txnp,TSMBuffer response)9297 TSHttpTxnGetMaxAge(TSHttpTxn txnp, TSMBuffer response)
9298 {
9299   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
9300   HttpSM *sm = (HttpSM *)txnp;
9301   HTTPHdr *resp;
9302 
9303   if (response) {
9304     // Make sure the response we got as a parameter is valid
9305     sdk_assert(sdk_sanity_check_mbuffer(response) == TS_SUCCESS);
9306     resp = reinterpret_cast<HTTPHdr *>(response);
9307   } else {
9308     // Use the transactions origin response if the user passed NULL
9309     resp = &(sm->t_state.hdr_info.server_response);
9310   }
9311 
9312   if (!resp || !resp->valid()) {
9313     return -1;
9314   }
9315 
9316   // We have a valid response, return max_age
9317   return HttpTransact::get_max_age(resp);
9318 }
9319 
9320 // Lookup various debug names for common HTTP types.
9321 const char *
TSHttpServerStateNameLookup(TSServerState state)9322 TSHttpServerStateNameLookup(TSServerState state)
9323 {
9324   return HttpDebugNames::get_server_state_name(static_cast<HttpTransact::ServerState_t>(state));
9325 }
9326 
9327 const char *
TSHttpHookNameLookup(TSHttpHookID hook)9328 TSHttpHookNameLookup(TSHttpHookID hook)
9329 {
9330   return HttpDebugNames::get_api_hook_name(static_cast<TSHttpHookID>(hook));
9331 }
9332 
9333 const char *
TSHttpEventNameLookup(TSEvent event)9334 TSHttpEventNameLookup(TSEvent event)
9335 {
9336   return HttpDebugNames::get_event_name(static_cast<int>(event));
9337 }
9338 
9339 /// Re-enable SSL VC.
9340 class TSSslCallback : public Continuation
9341 {
9342 public:
TSSslCallback(SSLNetVConnection * vc,TSEvent event)9343   TSSslCallback(SSLNetVConnection *vc, TSEvent event) : Continuation(vc->nh->mutex), m_vc(vc), m_event(event)
9344   {
9345     SET_HANDLER(&TSSslCallback::event_handler);
9346   }
9347   int
event_handler(int event,void *)9348   event_handler(int event, void *)
9349   {
9350     m_vc->reenable(m_vc->nh, m_event);
9351     delete this;
9352     return 0;
9353   }
9354 
9355 private:
9356   SSLNetVConnection *m_vc;
9357   TSEvent m_event;
9358 };
9359 
9360 /// SSL Hooks
9361 TSReturnCode
TSVConnTunnel(TSVConn sslp)9362 TSVConnTunnel(TSVConn sslp)
9363 {
9364   NetVConnection *vc        = reinterpret_cast<NetVConnection *>(sslp);
9365   SSLNetVConnection *ssl_vc = dynamic_cast<SSLNetVConnection *>(vc);
9366   TSReturnCode zret         = TS_SUCCESS;
9367   if (nullptr != ssl_vc) {
9368     ssl_vc->hookOpRequested = SSL_HOOK_OP_TUNNEL;
9369   } else {
9370     zret = TS_ERROR;
9371   }
9372   return zret;
9373 }
9374 
9375 TSSslConnection
TSVConnSslConnectionGet(TSVConn sslp)9376 TSVConnSslConnectionGet(TSVConn sslp)
9377 {
9378   TSSslConnection ssl       = nullptr;
9379   NetVConnection *vc        = reinterpret_cast<NetVConnection *>(sslp);
9380   SSLNetVConnection *ssl_vc = dynamic_cast<SSLNetVConnection *>(vc);
9381   if (ssl_vc != nullptr) {
9382     ssl = reinterpret_cast<TSSslConnection>(ssl_vc->ssl);
9383   }
9384   return ssl;
9385 }
9386 
9387 tsapi TSSslVerifyCTX
TSVConnSslVerifyCTXGet(TSVConn sslp)9388 TSVConnSslVerifyCTXGet(TSVConn sslp)
9389 {
9390   NetVConnection *vc        = reinterpret_cast<NetVConnection *>(sslp);
9391   SSLNetVConnection *ssl_vc = dynamic_cast<SSLNetVConnection *>(vc);
9392   if (ssl_vc != nullptr) {
9393     return reinterpret_cast<TSSslVerifyCTX>(ssl_vc->get_verify_cert());
9394   }
9395   return nullptr;
9396 }
9397 
9398 tsapi TSSslContext
TSSslContextFindByName(const char * name)9399 TSSslContextFindByName(const char *name)
9400 {
9401   if (nullptr == name || 0 == strlen(name)) {
9402     // an empty name is an invalid input
9403     return nullptr;
9404   }
9405   TSSslContext ret      = nullptr;
9406   SSLCertLookup *lookup = SSLCertificateConfig::acquire();
9407   if (lookup != nullptr) {
9408     SSLCertContext *cc = lookup->find(name);
9409     if (cc) {
9410       shared_SSL_CTX ctx = cc->getCtx();
9411       if (ctx) {
9412         ret = reinterpret_cast<TSSslContext>(ctx.get());
9413       }
9414     }
9415     SSLCertificateConfig::release(lookup);
9416   }
9417   return ret;
9418 }
9419 tsapi TSSslContext
TSSslContextFindByAddr(struct sockaddr const * addr)9420 TSSslContextFindByAddr(struct sockaddr const *addr)
9421 {
9422   TSSslContext ret      = nullptr;
9423   SSLCertLookup *lookup = SSLCertificateConfig::acquire();
9424   if (lookup != nullptr) {
9425     IpEndpoint ip;
9426     ip.assign(addr);
9427     SSLCertContext *cc = lookup->find(ip);
9428     if (cc) {
9429       shared_SSL_CTX ctx = cc->getCtx();
9430       if (ctx) {
9431         ret = reinterpret_cast<TSSslContext>(ctx.get());
9432       }
9433     }
9434     SSLCertificateConfig::release(lookup);
9435   }
9436   return ret;
9437 }
9438 
9439 /**
9440  * This function retrieves an array of lookup keys for client contexts loaded in
9441  * traffic server. Given a 2-level mapping for client contexts, every 2 lookup keys
9442  * can be used to locate and identify 1 context.
9443  * @param n Allocated size for result array.
9444  * @param result Const char pointer arrays to be filled with lookup keys.
9445  * @param actual Total number of lookup keys.
9446  */
9447 tsapi TSReturnCode
TSSslClientContextsNamesGet(int n,const char ** result,int * actual)9448 TSSslClientContextsNamesGet(int n, const char **result, int *actual)
9449 {
9450   sdk_assert(n == 0 || result != nullptr);
9451   int idx = 0, count = 0;
9452   SSLConfigParams *params = SSLConfig::acquire();
9453 
9454   if (params) {
9455     auto &ctx_map_lock = params->ctxMapLock;
9456     auto &ca_map       = params->top_level_ctx_map;
9457     auto mem           = static_cast<std::string_view *>(alloca(sizeof(std::string_view) * n));
9458     ink_mutex_acquire(&ctx_map_lock);
9459     for (auto &ca_pair : ca_map) {
9460       // Populate mem array with 2 strings each time
9461       for (auto &ctx_pair : ca_pair.second) {
9462         if (idx + 1 < n) {
9463           mem[idx++] = ca_pair.first;
9464           mem[idx++] = ctx_pair.first;
9465         }
9466         count += 2;
9467       }
9468     }
9469     ink_mutex_release(&ctx_map_lock);
9470     for (int i = 0; i < idx; i++) {
9471       result[i] = mem[i].data();
9472     }
9473   }
9474   if (actual) {
9475     *actual = count;
9476   }
9477   SSLConfig::release(params);
9478   return TS_SUCCESS;
9479 }
9480 
9481 /**
9482  * This function returns the client context corresponding to the lookup keys provided.
9483  * User should call TSSslClientContextsGet() first to determine which lookup keys are
9484  * present before querying for them. User will need to release the context returned
9485  * from this function.
9486  * Returns valid TSSslContext on success and nullptr on failure.
9487  * @param first_key Key string for the top level.
9488  * @param second_key Key string for the second level.
9489  */
9490 tsapi TSSslContext
TSSslClientContextFindByName(const char * ca_paths,const char * ck_paths)9491 TSSslClientContextFindByName(const char *ca_paths, const char *ck_paths)
9492 {
9493   if (!ca_paths || !ck_paths || ca_paths[0] == '\0' || ck_paths[0] == '\0') {
9494     return nullptr;
9495   }
9496   SSLConfigParams *params = SSLConfig::acquire();
9497   TSSslContext retval     = nullptr;
9498   if (params) {
9499     ink_mutex_acquire(&params->ctxMapLock);
9500     auto ca_iter = params->top_level_ctx_map.find(ca_paths);
9501     if (ca_iter != params->top_level_ctx_map.end()) {
9502       auto ctx_iter = ca_iter->second.find(ck_paths);
9503       if (ctx_iter != ca_iter->second.end()) {
9504         SSL_CTX_up_ref(ctx_iter->second.get());
9505         retval = reinterpret_cast<TSSslContext>(ctx_iter->second.get());
9506       }
9507     }
9508     ink_mutex_release(&params->ctxMapLock);
9509   }
9510   SSLConfig::release(params);
9511   return retval;
9512 }
9513 
9514 tsapi TSSslContext
TSSslServerContextCreate(TSSslX509 cert,const char * certname,const char * rsp_file)9515 TSSslServerContextCreate(TSSslX509 cert, const char *certname, const char *rsp_file)
9516 {
9517   TSSslContext ret        = nullptr;
9518   SSLConfigParams *config = SSLConfig::acquire();
9519   if (config != nullptr) {
9520     ret = reinterpret_cast<TSSslContext>(SSLCreateServerContext(config, nullptr));
9521 #if TS_USE_TLS_OCSP
9522     if (ret && SSLConfigParams::ssl_ocsp_enabled && cert && certname) {
9523       if (SSL_CTX_set_tlsext_status_cb(reinterpret_cast<SSL_CTX *>(ret), ssl_callback_ocsp_stapling)) {
9524         if (!ssl_stapling_init_cert(reinterpret_cast<SSL_CTX *>(ret), reinterpret_cast<X509 *>(cert), certname, rsp_file)) {
9525           Warning("failed to configure SSL_CTX for OCSP Stapling info for certificate at %s", (const char *)certname);
9526         }
9527       }
9528     }
9529 #endif
9530     SSLConfig::release(config);
9531   }
9532   return ret;
9533 }
9534 
9535 tsapi void
TSSslContextDestroy(TSSslContext ctx)9536 TSSslContextDestroy(TSSslContext ctx)
9537 {
9538   SSLReleaseContext(reinterpret_cast<SSL_CTX *>(ctx));
9539 }
9540 
9541 TSReturnCode
TSSslClientCertUpdate(const char * cert_path,const char * key_path)9542 TSSslClientCertUpdate(const char *cert_path, const char *key_path)
9543 {
9544   if (nullptr == cert_path) {
9545     return TS_ERROR;
9546   }
9547 
9548   std::string key;
9549   shared_SSL_CTX client_ctx = nullptr;
9550   SSLConfigParams *params   = SSLConfig::acquire();
9551 
9552   // Generate second level key for client context lookup
9553   ts::bwprint(key, "{}:{}", cert_path, key_path);
9554   Debug("ssl.cert_update", "TSSslClientCertUpdate(): Use %.*s as key for lookup", static_cast<int>(key.size()), key.data());
9555 
9556   if (nullptr != params) {
9557     // Try to update client contexts maps
9558     auto &ca_paths_map = params->top_level_ctx_map;
9559     auto &map_lock     = params->ctxMapLock;
9560     std::string ca_paths_key;
9561     // First try to locate the client context and its CA path (by top level)
9562     ink_mutex_acquire(&map_lock);
9563     for (auto &ca_paths_pair : ca_paths_map) {
9564       auto &ctx_map = ca_paths_pair.second;
9565       auto iter     = ctx_map.find(key);
9566       if (iter != ctx_map.end() && iter->second != nullptr) {
9567         ca_paths_key = ca_paths_pair.first;
9568         break;
9569       }
9570     }
9571     ink_mutex_release(&map_lock);
9572 
9573     // Only update on existing
9574     if (ca_paths_key.empty()) {
9575       return TS_ERROR;
9576     }
9577 
9578     // Extract CA related paths
9579     size_t sep                 = ca_paths_key.find(':');
9580     std::string ca_bundle_file = ca_paths_key.substr(0, sep);
9581     std::string ca_bundle_path = ca_paths_key.substr(sep + 1);
9582 
9583     // Build new client context
9584     client_ctx =
9585       shared_SSL_CTX(SSLCreateClientContext(params, ca_bundle_path.empty() ? nullptr : ca_bundle_path.c_str(),
9586                                             ca_bundle_file.empty() ? nullptr : ca_bundle_file.c_str(), cert_path, key_path),
9587                      SSL_CTX_free);
9588 
9589     // Successfully generates a client context, update in the map
9590     ink_mutex_acquire(&map_lock);
9591     auto iter = ca_paths_map.find(ca_paths_key);
9592     if (iter != ca_paths_map.end() && iter->second.count(key)) {
9593       iter->second[key] = client_ctx;
9594     } else {
9595       client_ctx = nullptr;
9596     }
9597     ink_mutex_release(&map_lock);
9598   }
9599 
9600   return client_ctx ? TS_SUCCESS : TS_ERROR;
9601 }
9602 
9603 TSReturnCode
TSSslServerCertUpdate(const char * cert_path,const char * key_path)9604 TSSslServerCertUpdate(const char *cert_path, const char *key_path)
9605 {
9606   if (nullptr == cert_path) {
9607     return TS_ERROR;
9608   }
9609 
9610   if (!key_path || key_path[0] == '\0') {
9611     key_path = cert_path;
9612   }
9613 
9614   SSLCertContext *cc         = nullptr;
9615   shared_SSL_CTX test_ctx    = nullptr;
9616   std::shared_ptr<X509> cert = nullptr;
9617 
9618   SSLConfig::scoped_config config;
9619   SSLCertificateConfig::scoped_config lookup;
9620 
9621   if (lookup && config) {
9622     // Read cert from path to extract lookup key (common name)
9623     scoped_BIO bio(BIO_new_file(cert_path, "r"));
9624     if (bio) {
9625       cert = std::shared_ptr<X509>(PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr), X509_free);
9626     }
9627     if (!bio || !cert) {
9628       SSLError("Failed to load certificate/key from %s", cert_path);
9629       return TS_ERROR;
9630     }
9631 
9632     // Extract common name
9633     int pos                       = X509_NAME_get_index_by_NID(X509_get_subject_name(cert.get()), NID_commonName, -1);
9634     X509_NAME_ENTRY *common_name  = X509_NAME_get_entry(X509_get_subject_name(cert.get()), pos);
9635     ASN1_STRING *common_name_asn1 = X509_NAME_ENTRY_get_data(common_name);
9636     char *common_name_str         = reinterpret_cast<char *>(const_cast<unsigned char *>(ASN1_STRING_get0_data(common_name_asn1)));
9637     if (ASN1_STRING_length(common_name_asn1) != static_cast<int>(strlen(common_name_str))) {
9638       // Embedded NULL char
9639       return TS_ERROR;
9640     }
9641     Debug("ssl.cert_update", "Updating from %s with common name %s", cert_path, common_name_str);
9642 
9643     // Update context to use cert
9644     cc = lookup->find(common_name_str);
9645     if (cc && cc->getCtx()) {
9646       test_ctx = shared_SSL_CTX(SSLCreateServerContext(config, cc->userconfig.get(), cert_path, key_path), SSLReleaseContext);
9647       if (!test_ctx) {
9648         return TS_ERROR;
9649       }
9650       // Atomic Swap
9651       cc->setCtx(test_ctx);
9652       return TS_SUCCESS;
9653     }
9654   }
9655 
9656   return TS_ERROR;
9657 }
9658 
9659 tsapi void
TSSslTicketKeyUpdate(char * ticketData,int ticketDataLen)9660 TSSslTicketKeyUpdate(char *ticketData, int ticketDataLen)
9661 {
9662   SSLTicketKeyConfig::reconfigure_data(ticketData, ticketDataLen);
9663 }
9664 
9665 TSReturnCode
TSVConnProtocolEnable(TSVConn connp,const char * protocol_name)9666 TSVConnProtocolEnable(TSVConn connp, const char *protocol_name)
9667 {
9668   TSReturnCode retval = TS_ERROR;
9669   int protocol_idx    = globalSessionProtocolNameRegistry.toIndexConst(std::string_view{protocol_name});
9670   auto net_vc         = reinterpret_cast<UnixNetVConnection *>(connp);
9671   auto alpn_vc        = dynamic_cast<ALPNSupport *>(net_vc);
9672   if (alpn_vc) {
9673     alpn_vc->enableProtocol(protocol_idx);
9674     retval = TS_SUCCESS;
9675   }
9676   return retval;
9677 }
9678 
9679 TSReturnCode
TSVConnProtocolDisable(TSVConn connp,const char * protocol_name)9680 TSVConnProtocolDisable(TSVConn connp, const char *protocol_name)
9681 {
9682   TSReturnCode retval = TS_ERROR;
9683   int protocol_idx    = globalSessionProtocolNameRegistry.toIndexConst(std::string_view{protocol_name});
9684   auto net_vc         = reinterpret_cast<UnixNetVConnection *>(connp);
9685   auto alpn_vc        = dynamic_cast<ALPNSupport *>(net_vc);
9686   if (alpn_vc) {
9687     alpn_vc->disableProtocol(protocol_idx);
9688     retval = TS_SUCCESS;
9689   }
9690   return retval;
9691 }
9692 
9693 TSAcceptor
TSAcceptorGet(TSVConn sslp)9694 TSAcceptorGet(TSVConn sslp)
9695 {
9696   NetVConnection *vc        = reinterpret_cast<NetVConnection *>(sslp);
9697   SSLNetVConnection *ssl_vc = dynamic_cast<SSLNetVConnection *>(vc);
9698   return ssl_vc ? reinterpret_cast<TSAcceptor>(ssl_vc->accept_object) : nullptr;
9699 }
9700 
9701 TSAcceptor
TSAcceptorGetbyID(int ID)9702 TSAcceptorGetbyID(int ID)
9703 {
9704   SCOPED_MUTEX_LOCK(lock, naVecMutex, this_ethread());
9705   auto ret = naVec.at(ID);
9706   Debug("ssl", "getNetAccept in INK API.cc %p", ret);
9707   return reinterpret_cast<TSAcceptor>(ret);
9708 }
9709 
9710 int
TSAcceptorIDGet(TSAcceptor acceptor)9711 TSAcceptorIDGet(TSAcceptor acceptor)
9712 {
9713   NetAccept *na = reinterpret_cast<NetAccept *>(acceptor);
9714   return na ? na->id : -1;
9715 }
9716 
9717 int
TSAcceptorCount()9718 TSAcceptorCount()
9719 {
9720   SCOPED_MUTEX_LOCK(lock, naVecMutex, this_ethread());
9721   return naVec.size();
9722 }
9723 
9724 tsapi int
TSVConnIsSsl(TSVConn sslp)9725 TSVConnIsSsl(TSVConn sslp)
9726 {
9727   NetVConnection *vc        = reinterpret_cast<NetVConnection *>(sslp);
9728   SSLNetVConnection *ssl_vc = dynamic_cast<SSLNetVConnection *>(vc);
9729   return ssl_vc != nullptr;
9730 }
9731 
9732 tsapi int
TSVConnProvidedSslCert(TSVConn sslp)9733 TSVConnProvidedSslCert(TSVConn sslp)
9734 {
9735   NetVConnection *vc = reinterpret_cast<NetVConnection *>(sslp);
9736   return vc->provided_cert();
9737 }
9738 
9739 void
TSVConnReenable(TSVConn vconn)9740 TSVConnReenable(TSVConn vconn)
9741 {
9742   TSVConnReenableEx(vconn, TS_EVENT_CONTINUE);
9743 }
9744 
9745 void
TSVConnReenableEx(TSVConn vconn,TSEvent event)9746 TSVConnReenableEx(TSVConn vconn, TSEvent event)
9747 {
9748   NetVConnection *vc        = reinterpret_cast<NetVConnection *>(vconn);
9749   SSLNetVConnection *ssl_vc = dynamic_cast<SSLNetVConnection *>(vc);
9750   // We really only deal with a SSLNetVConnection at the moment
9751   if (ssl_vc != nullptr) {
9752     EThread *eth = this_ethread();
9753 
9754     // We use the mutex of VC's NetHandler so we can put the VC into ready_list by reenable()
9755     MUTEX_TRY_LOCK(trylock, ssl_vc->nh->mutex, eth);
9756     if (trylock.is_locked()) {
9757       ssl_vc->reenable(ssl_vc->nh, event);
9758     } else {
9759       // We schedule the reenable to the home thread of ssl_vc.
9760       ssl_vc->thread->schedule_imm(new TSSslCallback(ssl_vc, event));
9761     }
9762   }
9763 }
9764 
9765 extern SSLSessionCache *session_cache; // declared extern in P_SSLConfig.h
9766 
9767 TSSslSession
TSSslSessionGet(const TSSslSessionID * session_id)9768 TSSslSessionGet(const TSSslSessionID *session_id)
9769 {
9770   SSL_SESSION *session = nullptr;
9771   if (session_id && session_cache) {
9772     session_cache->getSession(reinterpret_cast<const SSLSessionID &>(*session_id), &session, nullptr);
9773   }
9774   return reinterpret_cast<TSSslSession>(session);
9775 }
9776 
9777 int
TSSslSessionGetBuffer(const TSSslSessionID * session_id,char * buffer,int * len_ptr)9778 TSSslSessionGetBuffer(const TSSslSessionID *session_id, char *buffer, int *len_ptr)
9779 {
9780   int true_len = 0;
9781   // Don't get if there is no session id or the cache is not yet set up
9782   if (session_id && session_cache && len_ptr) {
9783     true_len = session_cache->getSessionBuffer(reinterpret_cast<const SSLSessionID &>(*session_id), buffer, *len_ptr);
9784   }
9785   return true_len;
9786 }
9787 
9788 TSReturnCode
TSSslSessionInsert(const TSSslSessionID * session_id,TSSslSession add_session,TSSslConnection ssl_conn)9789 TSSslSessionInsert(const TSSslSessionID *session_id, TSSslSession add_session, TSSslConnection ssl_conn)
9790 {
9791   // Don't insert if there is no session id or the cache is not yet set up
9792   if (session_id && session_cache) {
9793     if (is_debug_tag_set("ssl.session_cache")) {
9794       const SSLSessionID *sid = reinterpret_cast<const SSLSessionID *>(session_id);
9795       char buf[sid->len * 2 + 1];
9796       sid->toString(buf, sizeof(buf));
9797       Debug("ssl.session_cache.insert", "TSSslSessionInsert: Inserting session '%s' ", buf);
9798     }
9799     SSL_SESSION *session = reinterpret_cast<SSL_SESSION *>(add_session);
9800     SSL *ssl             = reinterpret_cast<SSL *>(ssl_conn);
9801     session_cache->insertSession(reinterpret_cast<const SSLSessionID &>(*session_id), session, ssl);
9802     // insertSession returns void, assume all went well
9803     return TS_SUCCESS;
9804   } else {
9805     return TS_ERROR;
9806   }
9807 }
9808 
9809 TSReturnCode
TSSslSessionRemove(const TSSslSessionID * session_id)9810 TSSslSessionRemove(const TSSslSessionID *session_id)
9811 {
9812   // Don't remove if there is no session id or the cache is not yet set up
9813   if (session_id && session_cache) {
9814     session_cache->removeSession(reinterpret_cast<const SSLSessionID &>(*session_id));
9815     // removeSession returns void, assume all went well
9816     return TS_SUCCESS;
9817   } else {
9818     return TS_ERROR;
9819   }
9820 }
9821 
9822 // APIs for managing and using UUIDs.
9823 TSUuid
TSUuidCreate()9824 TSUuidCreate()
9825 {
9826   ATSUuid *uuid = new ATSUuid();
9827   return (TSUuid)uuid;
9828 }
9829 
9830 void
TSUuidDestroy(TSUuid uuid)9831 TSUuidDestroy(TSUuid uuid)
9832 {
9833   sdk_assert(sdk_sanity_check_null_ptr((void *)uuid) == TS_SUCCESS);
9834   delete (ATSUuid *)uuid;
9835 }
9836 
9837 TSReturnCode
TSUuidCopy(TSUuid dest,const TSUuid src)9838 TSUuidCopy(TSUuid dest, const TSUuid src)
9839 {
9840   sdk_assert(sdk_sanity_check_null_ptr((void *)dest) == TS_SUCCESS);
9841   sdk_assert(sdk_sanity_check_null_ptr((void *)src) == TS_SUCCESS);
9842   ATSUuid *d = (ATSUuid *)dest;
9843   ATSUuid *s = (ATSUuid *)src;
9844 
9845   if (s->valid()) {
9846     *d = *s;
9847     return TS_SUCCESS;
9848   }
9849 
9850   return TS_ERROR;
9851 }
9852 
9853 TSReturnCode
TSUuidInitialize(TSUuid uuid,TSUuidVersion v)9854 TSUuidInitialize(TSUuid uuid, TSUuidVersion v)
9855 {
9856   sdk_assert(sdk_sanity_check_null_ptr((void *)uuid) == TS_SUCCESS);
9857   ATSUuid *u = (ATSUuid *)uuid;
9858 
9859   u->initialize(v);
9860   return u->valid() ? TS_SUCCESS : TS_ERROR;
9861 }
9862 
9863 TSUuid
TSProcessUuidGet()9864 TSProcessUuidGet()
9865 {
9866   Machine *machine = Machine::instance();
9867   return (TSUuid)(&machine->uuid);
9868 }
9869 
9870 const char *
TSUuidStringGet(const TSUuid uuid)9871 TSUuidStringGet(const TSUuid uuid)
9872 {
9873   sdk_assert(sdk_sanity_check_null_ptr((void *)uuid) == TS_SUCCESS);
9874   ATSUuid *u = (ATSUuid *)(uuid);
9875 
9876   if (u->valid()) {
9877     return u->getString();
9878   }
9879 
9880   return nullptr;
9881 }
9882 
9883 TSReturnCode
TSClientRequestUuidGet(TSHttpTxn txnp,char * uuid_str)9884 TSClientRequestUuidGet(TSHttpTxn txnp, char *uuid_str)
9885 {
9886   sdk_assert(sdk_sanity_check_null_ptr((void *)uuid_str) == TS_SUCCESS);
9887 
9888   HttpSM *sm          = (HttpSM *)txnp;
9889   const char *machine = (char *)Machine::instance()->uuid.getString();
9890   int len;
9891 
9892   len = snprintf(uuid_str, TS_CRUUID_STRING_LEN + 1, "%s-%" PRId64 "", machine, sm->sm_id);
9893   if (len > TS_CRUUID_STRING_LEN) {
9894     return TS_ERROR;
9895   }
9896 
9897   return TS_SUCCESS;
9898 }
9899 
9900 TSReturnCode
TSUuidStringParse(TSUuid uuid,const char * str)9901 TSUuidStringParse(TSUuid uuid, const char *str)
9902 {
9903   sdk_assert(sdk_sanity_check_null_ptr((void *)uuid) == TS_SUCCESS);
9904   sdk_assert(sdk_sanity_check_null_ptr((void *)str) == TS_SUCCESS);
9905   ATSUuid *u = (ATSUuid *)uuid;
9906 
9907   if (u->parseString(str)) {
9908     return TS_SUCCESS;
9909   }
9910 
9911   return TS_ERROR;
9912 }
9913 
9914 TSUuidVersion
TSUuidVersionGet(TSUuid uuid)9915 TSUuidVersionGet(TSUuid uuid)
9916 {
9917   sdk_assert(sdk_sanity_check_null_ptr((void *)uuid) == TS_SUCCESS);
9918   ATSUuid *u = (ATSUuid *)uuid;
9919 
9920   return u->version();
9921 }
9922 
9923 // Expose the HttpSM's sequence number (ID)
9924 uint64_t
TSHttpTxnIdGet(TSHttpTxn txnp)9925 TSHttpTxnIdGet(TSHttpTxn txnp)
9926 {
9927   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
9928   HttpSM *sm = (HttpSM *)txnp;
9929 
9930   return (uint64_t)sm->sm_id;
9931 }
9932 
9933 // Returns unique client session identifier
9934 int64_t
TSHttpSsnIdGet(TSHttpSsn ssnp)9935 TSHttpSsnIdGet(TSHttpSsn ssnp)
9936 {
9937   sdk_assert(sdk_sanity_check_http_ssn(ssnp) == TS_SUCCESS);
9938   ProxySession const *cs = reinterpret_cast<ProxySession *>(ssnp);
9939   return cs->connection_id();
9940 }
9941 
9942 // Return information about the protocols used by the client
9943 TSReturnCode
TSHttpTxnClientProtocolStackGet(TSHttpTxn txnp,int count,const char ** result,int * actual)9944 TSHttpTxnClientProtocolStackGet(TSHttpTxn txnp, int count, const char **result, int *actual)
9945 {
9946   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
9947   sdk_assert(count == 0 || result != nullptr);
9948   HttpSM *sm    = reinterpret_cast<HttpSM *>(txnp);
9949   int new_count = 0;
9950   if (sm && count > 0) {
9951     auto mem  = static_cast<std::string_view *>(alloca(sizeof(std::string_view) * count));
9952     new_count = sm->populate_client_protocol(mem, count);
9953     for (int i = 0; i < new_count; ++i) {
9954       result[i] = mem[i].data();
9955     }
9956   }
9957   if (actual) {
9958     *actual = new_count;
9959   }
9960   return TS_SUCCESS;
9961 }
9962 
9963 TSReturnCode
TSHttpSsnClientProtocolStackGet(TSHttpSsn ssnp,int count,const char ** result,int * actual)9964 TSHttpSsnClientProtocolStackGet(TSHttpSsn ssnp, int count, const char **result, int *actual)
9965 {
9966   sdk_assert(sdk_sanity_check_http_ssn(ssnp) == TS_SUCCESS);
9967   sdk_assert(count == 0 || result != nullptr);
9968   auto const *cs = reinterpret_cast<ProxySession *>(ssnp);
9969   int new_count  = 0;
9970   if (cs && count > 0) {
9971     auto mem  = static_cast<std::string_view *>(alloca(sizeof(std::string_view) * count));
9972     new_count = cs->populate_protocol(mem, count);
9973     for (int i = 0; i < new_count; ++i) {
9974       result[i] = mem[i].data();
9975     }
9976   }
9977   if (actual) {
9978     *actual = new_count;
9979   }
9980   return TS_SUCCESS;
9981 }
9982 
9983 // Return information about the protocols used by the server
9984 TSReturnCode
TSHttpTxnServerProtocolStackGet(TSHttpTxn txnp,int count,const char ** result,int * actual)9985 TSHttpTxnServerProtocolStackGet(TSHttpTxn txnp, int count, const char **result, int *actual)
9986 {
9987   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
9988   sdk_assert(count == 0 || result != nullptr);
9989   HttpSM *sm    = reinterpret_cast<HttpSM *>(txnp);
9990   int new_count = 0;
9991   if (sm && count > 0) {
9992     auto mem  = static_cast<std::string_view *>(alloca(sizeof(std::string_view) * count));
9993     new_count = sm->populate_server_protocol(mem, count);
9994     for (int i = 0; i < new_count; ++i) {
9995       result[i] = mem[i].data();
9996     }
9997   }
9998   if (actual) {
9999     *actual = new_count;
10000   }
10001   return TS_SUCCESS;
10002 }
10003 
10004 const char *
TSNormalizedProtocolTag(const char * tag)10005 TSNormalizedProtocolTag(const char *tag)
10006 {
10007   return RecNormalizeProtoTag(tag);
10008 }
10009 
10010 const char *
TSHttpTxnClientProtocolStackContains(TSHttpTxn txnp,const char * tag)10011 TSHttpTxnClientProtocolStackContains(TSHttpTxn txnp, const char *tag)
10012 {
10013   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
10014   HttpSM *sm = reinterpret_cast<HttpSM *>(txnp);
10015   return sm->client_protocol_contains(std::string_view{tag});
10016 }
10017 
10018 const char *
TSHttpSsnClientProtocolStackContains(TSHttpSsn ssnp,const char * tag)10019 TSHttpSsnClientProtocolStackContains(TSHttpSsn ssnp, const char *tag)
10020 {
10021   sdk_assert(sdk_sanity_check_http_ssn(ssnp) == TS_SUCCESS);
10022   ProxySession *cs = reinterpret_cast<ProxySession *>(ssnp);
10023   return cs->protocol_contains(std::string_view{tag});
10024 }
10025 
10026 const char *
TSHttpTxnServerProtocolStackContains(TSHttpTxn txnp,const char * tag)10027 TSHttpTxnServerProtocolStackContains(TSHttpTxn txnp, const char *tag)
10028 {
10029   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
10030   HttpSM *sm = reinterpret_cast<HttpSM *>(txnp);
10031   return sm->server_protocol_contains(std::string_view{tag});
10032 }
10033 
10034 const char *
TSRegisterProtocolTag(const char * tag)10035 TSRegisterProtocolTag(const char *tag)
10036 {
10037   return nullptr;
10038 }
10039 
10040 TSReturnCode
TSHttpTxnRedoCacheLookup(TSHttpTxn txnp,const char * url,int length)10041 TSHttpTxnRedoCacheLookup(TSHttpTxn txnp, const char *url, int length)
10042 {
10043   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
10044 
10045   HttpSM *sm             = reinterpret_cast<HttpSM *>(txnp);
10046   HttpTransact::State *s = &(sm->t_state);
10047   sdk_assert(s->next_action == HttpTransact::SM_ACTION_CACHE_LOOKUP);
10048 
10049   // Because of where this is in the state machine, the storage for the cache_info URL must
10050   // have already been initialized and @a lookup_url must be valid.
10051   auto result = s->cache_info.lookup_url->parse(url, length < 0 ? strlen(url) : length);
10052   if (PARSE_RESULT_DONE == result) {
10053     s->transact_return_point = nullptr;
10054     sm->rewind_state_machine();
10055     return TS_SUCCESS;
10056   }
10057   return TS_ERROR;
10058 }
10059 
10060 namespace
10061 {
10062 // Function that contains the common logic for TSRemapFrom/ToUrlGet().
10063 //
10064 TSReturnCode
remapUrlGet(TSHttpTxn txnp,TSMLoc * urlLocp,URL * (UrlMappingContainer::* mfp)()const)10065 remapUrlGet(TSHttpTxn txnp, TSMLoc *urlLocp, URL *(UrlMappingContainer::*mfp)() const)
10066 {
10067   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
10068   sdk_assert(sdk_sanity_check_null_ptr(urlLocp) == TS_SUCCESS);
10069   HttpSM *sm = reinterpret_cast<HttpSM *>(txnp);
10070 
10071   URL *url = (sm->t_state.url_map.*mfp)();
10072   if (url == nullptr) {
10073     return TS_ERROR;
10074   }
10075 
10076   auto urlImpl = url->m_url_impl;
10077   if (urlImpl == nullptr) {
10078     return TS_ERROR;
10079   }
10080 
10081   *urlLocp = reinterpret_cast<TSMLoc>(urlImpl);
10082 
10083   return TS_SUCCESS;
10084 }
10085 
10086 } // end anonymous namespace
10087 
10088 tsapi TSReturnCode
TSRemapFromUrlGet(TSHttpTxn txnp,TSMLoc * urlLocp)10089 TSRemapFromUrlGet(TSHttpTxn txnp, TSMLoc *urlLocp)
10090 {
10091   return remapUrlGet(txnp, urlLocp, &UrlMappingContainer::getFromURL);
10092 }
10093 
10094 tsapi TSReturnCode
TSRemapToUrlGet(TSHttpTxn txnp,TSMLoc * urlLocp)10095 TSRemapToUrlGet(TSHttpTxn txnp, TSMLoc *urlLocp)
10096 {
10097   return remapUrlGet(txnp, urlLocp, &UrlMappingContainer::getToURL);
10098 }
10099 
10100 tsapi TSIOBufferReader
TSHttpTxnPostBufferReaderGet(TSHttpTxn txnp)10101 TSHttpTxnPostBufferReaderGet(TSHttpTxn txnp)
10102 {
10103   sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
10104   HttpSM *sm = (HttpSM *)txnp;
10105   return (TSIOBufferReader)sm->get_postbuf_clone_reader();
10106 }
10107