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(¶ms->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(¶ms->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