1 /** @file
2
3 A brief file description
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 #pragma once
25
26 #include "tscore/ink_assert.h"
27 #include "tscore/ink_platform.h"
28 #include "P_HostDB.h"
29 #include "P_Net.h"
30 #include "HttpConfig.h"
31 #include "HTTP.h"
32 #include "HttpTransactCache.h"
33 #include "ControlMatcher.h"
34 #include "CacheControl.h"
35 #include "ParentSelection.h"
36 #include "ProxyConfig.h"
37 #include "Transform.h"
38 #include "Milestones.h"
39 #include "ts/remap.h"
40 #include "RemapPluginInfo.h"
41 #include "UrlMapping.h"
42 #include "records/I_RecHttp.h"
43 #include "ProxySession.h"
44 #include "MgmtDefs.h"
45
46 #define HTTP_RELEASE_ASSERT(X) ink_release_assert(X)
47
48 #define DUMP_HEADER(T, H, I, S) \
49 { \
50 if (diags->on(T)) { \
51 fprintf(stderr, "+++++++++ %s +++++++++\n", S); \
52 fprintf(stderr, "-- State Machine Id: %" PRId64 "\n", I); \
53 char b[4096]; \
54 int used, tmp, offset; \
55 int done; \
56 offset = 0; \
57 if ((H)->valid()) { \
58 do { \
59 used = 0; \
60 tmp = offset; \
61 done = (H)->print(b, 4095, &used, &tmp); \
62 offset += used; \
63 b[used] = '\0'; \
64 fprintf(stderr, "%s", b); \
65 } while (!done); \
66 } \
67 } \
68 }
69
70 typedef time_t ink_time_t;
71
72 struct HttpConfigParams;
73 class HttpSM;
74
75 #include "tscore/InkErrno.h"
76 #include "HttpConnectionCount.h"
77
78 #define UNKNOWN_INTERNAL_ERROR (INK_START_ERRNO - 1)
79
80 enum ViaStringIndex_t {
81 //
82 // General information
83 VIA_CLIENT = 0,
84 VIA_CLIENT_REQUEST,
85 VIA_CACHE,
86 VIA_CACHE_RESULT,
87 VIA_SERVER,
88 VIA_SERVER_RESULT,
89 VIA_CACHE_FILL,
90 VIA_CACHE_FILL_ACTION,
91 VIA_PROXY,
92 VIA_PROXY_RESULT,
93 VIA_ERROR,
94 VIA_ERROR_TYPE,
95 //
96 // State Machine specific details
97 VIA_DETAIL_SEPARATOR,
98 VIA_DETAIL_TUNNEL_DESCRIPTOR,
99 VIA_DETAIL_TUNNEL,
100 VIA_DETAIL_CACHE_DESCRIPTOR,
101 VIA_DETAIL_CACHE_TYPE,
102 VIA_DETAIL_CACHE_LOOKUP,
103 VIA_DETAIL_PP_DESCRIPTOR,
104 VIA_DETAIL_PP_CONNECT,
105 VIA_DETAIL_SERVER_DESCRIPTOR,
106 VIA_DETAIL_SERVER_CONNECT,
107 //
108 // Total
109 MAX_VIA_INDICES
110 };
111
112 enum ViaString_t {
113 // client stuff
114 VIA_CLIENT_STRING = 'u',
115 VIA_CLIENT_ERROR = 'E',
116 VIA_CLIENT_IMS = 'I',
117 VIA_CLIENT_NO_CACHE = 'N',
118 VIA_CLIENT_COOKIE = 'C',
119 VIA_CLIENT_SIMPLE = 'S',
120 // cache lookup stuff
121 VIA_CACHE_STRING = 'c',
122 VIA_CACHE_MISS = 'M',
123 VIA_IN_CACHE_NOT_ACCEPTABLE = 'A',
124 VIA_IN_CACHE_STALE = 'S',
125 VIA_IN_CACHE_FRESH = 'H',
126 VIA_IN_RAM_CACHE_FRESH = 'R',
127 // server stuff
128 VIA_SERVER_STRING = 's',
129 VIA_SERVER_ERROR = 'E',
130 VIA_SERVER_NOT_MODIFIED = 'N',
131 VIA_SERVER_SERVED = 'S',
132 // cache fill stuff
133 VIA_CACHE_FILL_STRING = 'f',
134 VIA_CACHE_DELETED = 'D',
135 VIA_CACHE_WRITTEN = 'W',
136 VIA_CACHE_UPDATED = 'U',
137 // proxy stuff
138 VIA_PROXY_STRING = 'p',
139 VIA_PROXY_NOT_MODIFIED = 'N',
140 VIA_PROXY_SERVED = 'S',
141 VIA_PROXY_SERVER_REVALIDATED = 'R',
142 // errors
143 VIA_ERROR_STRING = 'e',
144 VIA_ERROR_NO_ERROR = 'N',
145 VIA_ERROR_AUTHORIZATION = 'A',
146 VIA_ERROR_CONNECTION = 'C',
147 VIA_ERROR_DNS_FAILURE = 'D',
148 VIA_ERROR_FORBIDDEN = 'F',
149 VIA_ERROR_HEADER_SYNTAX = 'H',
150 VIA_ERROR_SERVER = 'S',
151 VIA_ERROR_TIMEOUT = 'T',
152 VIA_ERROR_CACHE_READ = 'R',
153 VIA_ERROR_MOVED_TEMPORARILY = 'M',
154 VIA_ERROR_LOOP_DETECTED = 'L',
155 //
156 // Now the detailed stuff
157 //
158 VIA_DETAIL_SEPARATOR_STRING = ':',
159 // tunnelling
160 VIA_DETAIL_TUNNEL_DESCRIPTOR_STRING = 't',
161 VIA_DETAIL_TUNNEL_HEADER_FIELD = 'F',
162 VIA_DETAIL_TUNNEL_METHOD = 'M',
163 VIA_DETAIL_TUNNEL_CACHE_OFF = 'O',
164 VIA_DETAIL_TUNNEL_URL = 'U',
165 VIA_DETAIL_TUNNEL_NO_FORWARD = 'N',
166 VIA_DETAIL_TUNNEL_AUTHORIZATION = 'A',
167 // cache type
168 VIA_DETAIL_CACHE_DESCRIPTOR_STRING = 'c',
169 VIA_DETAIL_CACHE = 'C',
170 VIA_DETAIL_PARENT = 'P',
171 VIA_DETAIL_SERVER = 'S',
172 // result of cache lookup
173 VIA_DETAIL_HIT_CONDITIONAL = 'N',
174 VIA_DETAIL_HIT_SERVED = 'H',
175 VIA_DETAIL_MISS_CONDITIONAL = 'I',
176 VIA_DETAIL_MISS_NOT_CACHED = 'M',
177 VIA_DETAIL_MISS_EXPIRED = 'S',
178 VIA_DETAIL_MISS_CONFIG = 'C',
179 VIA_DETAIL_MISS_CLIENT = 'U',
180 VIA_DETAIL_MISS_METHOD = 'D',
181 VIA_DETAIL_MISS_COOKIE = 'K',
182 // result of pp suggested host lookup
183 VIA_DETAIL_PP_DESCRIPTOR_STRING = 'p',
184 VIA_DETAIL_PP_SUCCESS = 'S',
185 VIA_DETAIL_PP_FAILURE = 'F',
186 // result of server suggested host lookup
187 VIA_DETAIL_SERVER_DESCRIPTOR_STRING = 's',
188 VIA_DETAIL_SERVER_SUCCESS = 'S',
189 VIA_DETAIL_SERVER_FAILURE = 'F'
190 };
191
192 struct HttpApiInfo {
193 char *parent_proxy_name = nullptr;
194 int parent_proxy_port = -1;
195 bool cache_untransformed = false;
196 bool cache_transformed = true;
197 bool logging_enabled = true;
198 bool retry_intercept_failures = false;
199
HttpApiInfoHttpApiInfo200 HttpApiInfo() {}
201 };
202
203 const int32_t HTTP_UNDEFINED_CL = -1;
204
205 //////////////////////////////////////////////////////////////////////////////
206 //
207 // HttpTransact
208 //
209 // The HttpTransact class is purely used for scoping and should
210 // not be instantiated.
211 //
212 //////////////////////////////////////////////////////////////////////////////
213 #define SET_VIA_STRING(I, S) s->via_string[I] = S;
214 #define GET_VIA_STRING(I) (s->via_string[I])
215
216 class HttpTransact
217 {
218 public:
219 enum AbortState_t {
220 ABORT_UNDEFINED = 0,
221 DIDNOT_ABORT,
222 ABORTED,
223 };
224
225 enum Authentication_t {
226 AUTHENTICATION_SUCCESS = 0,
227 AUTHENTICATION_MUST_REVALIDATE,
228 AUTHENTICATION_MUST_PROXY,
229 AUTHENTICATION_CACHE_AUTH
230 };
231
232 enum CacheAction_t {
233 CACHE_DO_UNDEFINED = 0,
234 CACHE_DO_NO_ACTION,
235 CACHE_DO_DELETE,
236 CACHE_DO_LOOKUP,
237 CACHE_DO_REPLACE,
238 CACHE_DO_SERVE,
239 CACHE_DO_SERVE_AND_DELETE,
240 CACHE_DO_SERVE_AND_UPDATE,
241 CACHE_DO_UPDATE,
242 CACHE_DO_WRITE,
243 CACHE_PREPARE_TO_DELETE,
244 CACHE_PREPARE_TO_UPDATE,
245 CACHE_PREPARE_TO_WRITE,
246 TOTAL_CACHE_ACTION_TYPES
247 };
248
249 enum CacheWriteLock_t {
250 CACHE_WL_INIT,
251 CACHE_WL_SUCCESS,
252 CACHE_WL_FAIL,
253 CACHE_WL_READ_RETRY,
254 };
255
256 enum ClientTransactionResult_t {
257 CLIENT_TRANSACTION_RESULT_UNDEFINED,
258 CLIENT_TRANSACTION_RESULT_HIT_FRESH,
259 CLIENT_TRANSACTION_RESULT_HIT_REVALIDATED,
260 CLIENT_TRANSACTION_RESULT_MISS_COLD,
261 CLIENT_TRANSACTION_RESULT_MISS_CHANGED,
262 CLIENT_TRANSACTION_RESULT_MISS_CLIENT_NO_CACHE,
263 CLIENT_TRANSACTION_RESULT_MISS_UNCACHABLE,
264 CLIENT_TRANSACTION_RESULT_ERROR_ABORT,
265 CLIENT_TRANSACTION_RESULT_ERROR_POSSIBLE_ABORT,
266 CLIENT_TRANSACTION_RESULT_ERROR_CONNECT_FAIL,
267 CLIENT_TRANSACTION_RESULT_ERROR_OTHER
268 };
269
270 enum Freshness_t {
271 FRESHNESS_FRESH = 0, // Fresh enough, serve it
272 FRESHNESS_WARNING, // Stale, but client says OK
273 FRESHNESS_STALE // Stale, don't use
274 };
275
276 enum HttpTransactMagic_t {
277 HTTP_TRANSACT_MAGIC_ALIVE = 0x00001234,
278 HTTP_TRANSACT_MAGIC_DEAD = 0xDEAD1234,
279 HTTP_TRANSACT_MAGIC_SEPARATOR = 0x12345678
280 };
281
282 enum LookingUp_t {
283 ORIGIN_SERVER,
284 UNDEFINED_LOOKUP,
285 PARENT_PROXY,
286 INCOMING_ROUTER,
287 HOST_NONE,
288 };
289
290 enum ProxyMode_t {
291 UNDEFINED_MODE,
292 GENERIC_PROXY,
293 TUNNELLING_PROXY,
294 };
295
296 enum RequestError_t {
297 NO_REQUEST_HEADER_ERROR,
298 BAD_HTTP_HEADER_SYNTAX,
299 BAD_CONNECT_PORT,
300 FAILED_PROXY_AUTHORIZATION,
301 METHOD_NOT_SUPPORTED,
302 MISSING_HOST_FIELD,
303 NO_POST_CONTENT_LENGTH,
304 NO_REQUEST_SCHEME,
305 NON_EXISTANT_REQUEST_HEADER,
306 SCHEME_NOT_SUPPORTED,
307 UNACCEPTABLE_TE_REQUIRED,
308 INVALID_POST_CONTENT_LENGTH,
309 TOTAL_REQUEST_ERROR_TYPES
310 };
311
312 enum ResponseError_t {
313 NO_RESPONSE_HEADER_ERROR,
314 BOGUS_OR_NO_DATE_IN_RESPONSE,
315 CONNECTION_OPEN_FAILED,
316 MISSING_REASON_PHRASE,
317 MISSING_STATUS_CODE,
318 NON_EXISTANT_RESPONSE_HEADER,
319 NOT_A_RESPONSE_HEADER,
320 STATUS_CODE_SERVER_ERROR,
321 TOTAL_RESPONSE_ERROR_TYPES
322 };
323
324 // Please do not forget to fix TSServerState (ts/apidefs.h.in)
325 // in case of any modifications in ServerState_t
326 enum ServerState_t {
327 STATE_UNDEFINED = 0,
328 ACTIVE_TIMEOUT,
329 BAD_INCOMING_RESPONSE,
330 CONNECTION_ALIVE,
331 CONNECTION_CLOSED,
332 CONNECTION_ERROR,
333 INACTIVE_TIMEOUT,
334 OPEN_RAW_ERROR,
335 PARSE_ERROR,
336 TRANSACTION_COMPLETE,
337 PARENT_RETRY,
338 OUTBOUND_CONGESTION
339 };
340
341 enum CacheWriteStatus_t {
342 NO_CACHE_WRITE = 0,
343 CACHE_WRITE_LOCK_MISS,
344 CACHE_WRITE_IN_PROGRESS,
345 CACHE_WRITE_ERROR,
346 CACHE_WRITE_COMPLETE
347 };
348
349 enum HttpRequestFlavor_t {
350 REQ_FLAVOR_INTERCEPTED = 0,
351 REQ_FLAVOR_REVPROXY = 1,
352 REQ_FLAVOR_FWDPROXY = 2,
353 REQ_FLAVOR_SCHEDULED_UPDATE = 3
354 };
355
356 ////////////
357 // source //
358 ////////////
359 enum Source_t {
360 SOURCE_NONE = 0,
361 SOURCE_HTTP_ORIGIN_SERVER,
362 SOURCE_RAW_ORIGIN_SERVER,
363 SOURCE_CACHE,
364 SOURCE_TRANSFORM,
365 SOURCE_INTERNAL // generated from text buffer
366 };
367
368 ////////////////////////////////////////////////
369 // HttpTransact fills a StateMachineAction_t //
370 // to tell the state machine what to do next. //
371 ////////////////////////////////////////////////
372 enum StateMachineAction_t {
373 SM_ACTION_UNDEFINED = 0,
374
375 // SM_ACTION_AUTH_LOOKUP,
376 SM_ACTION_DNS_LOOKUP,
377 SM_ACTION_DNS_REVERSE_LOOKUP,
378
379 SM_ACTION_CACHE_LOOKUP,
380 SM_ACTION_CACHE_ISSUE_WRITE,
381 SM_ACTION_CACHE_ISSUE_WRITE_TRANSFORM,
382 SM_ACTION_CACHE_PREPARE_UPDATE,
383 SM_ACTION_CACHE_ISSUE_UPDATE,
384
385 SM_ACTION_ORIGIN_SERVER_OPEN,
386 SM_ACTION_ORIGIN_SERVER_RAW_OPEN,
387 SM_ACTION_ORIGIN_SERVER_RR_MARK_DOWN,
388
389 SM_ACTION_READ_PUSH_HDR,
390 SM_ACTION_STORE_PUSH_BODY,
391
392 SM_ACTION_INTERNAL_CACHE_DELETE,
393 SM_ACTION_INTERNAL_CACHE_NOOP,
394 SM_ACTION_INTERNAL_CACHE_UPDATE_HEADERS,
395 SM_ACTION_INTERNAL_CACHE_WRITE,
396 SM_ACTION_INTERNAL_100_RESPONSE,
397 SM_ACTION_INTERNAL_REQUEST,
398 SM_ACTION_SEND_ERROR_CACHE_NOOP,
399
400 SM_ACTION_WAIT_FOR_FULL_BODY,
401 SM_ACTION_REQUEST_BUFFER_READ_COMPLETE,
402 SM_ACTION_SERVE_FROM_CACHE,
403 SM_ACTION_SERVER_READ,
404 SM_ACTION_SERVER_PARSE_NEXT_HDR,
405 SM_ACTION_TRANSFORM_READ,
406 SM_ACTION_SSL_TUNNEL,
407 SM_ACTION_CONTINUE,
408
409 SM_ACTION_API_SM_START,
410 SM_ACTION_API_READ_REQUEST_HDR,
411 SM_ACTION_API_PRE_REMAP,
412 SM_ACTION_API_POST_REMAP,
413 SM_ACTION_API_OS_DNS,
414 SM_ACTION_API_SEND_REQUEST_HDR,
415 SM_ACTION_API_READ_CACHE_HDR,
416 SM_ACTION_API_CACHE_LOOKUP_COMPLETE,
417 SM_ACTION_API_READ_RESPONSE_HDR,
418 SM_ACTION_API_SEND_RESPONSE_HDR,
419 SM_ACTION_API_SM_SHUTDOWN,
420
421 SM_ACTION_REMAP_REQUEST,
422 SM_ACTION_POST_REMAP_SKIP,
423 SM_ACTION_REDIRECT_READ
424 };
425
426 enum TransferEncoding_t {
427 NO_TRANSFER_ENCODING = 0,
428 CHUNKED_ENCODING,
429 DEFLATE_ENCODING,
430 };
431
432 enum Variability_t {
433 VARIABILITY_NONE = 0,
434 VARIABILITY_SOME,
435 VARIABILITY_ALL,
436 };
437
438 enum CacheLookupResult_t {
439 CACHE_LOOKUP_NONE,
440 CACHE_LOOKUP_MISS,
441 CACHE_LOOKUP_DOC_BUSY,
442 CACHE_LOOKUP_HIT_STALE,
443 CACHE_LOOKUP_HIT_WARNING,
444 CACHE_LOOKUP_HIT_FRESH,
445 CACHE_LOOKUP_SKIPPED
446 };
447
448 enum UpdateCachedObject_t {
449 UPDATE_CACHED_OBJECT_NONE,
450 UPDATE_CACHED_OBJECT_PREPARE,
451 UPDATE_CACHED_OBJECT_CONTINUE,
452 UPDATE_CACHED_OBJECT_ERROR,
453 UPDATE_CACHED_OBJECT_SUCCEED,
454 UPDATE_CACHED_OBJECT_FAIL
455 };
456
457 enum RangeSetup_t {
458 RANGE_NONE = 0,
459 RANGE_REQUESTED,
460 RANGE_NOT_SATISFIABLE,
461 RANGE_NOT_HANDLED,
462 RANGE_NOT_TRANSFORM_REQUESTED,
463 };
464
465 enum CacheAuth_t {
466 CACHE_AUTH_NONE = 0,
467 // CACHE_AUTH_TRUE,
468 CACHE_AUTH_FRESH,
469 CACHE_AUTH_STALE,
470 CACHE_AUTH_SERVE
471 };
472
473 struct State;
474 typedef void (*TransactFunc_t)(HttpTransact::State *);
475
476 typedef struct _CacheDirectives {
477 bool does_client_permit_lookup = true;
478 bool does_client_permit_storing = true;
479 bool does_client_permit_dns_storing = true;
480 bool does_config_permit_lookup = true;
481 bool does_config_permit_storing = true;
482 bool does_server_permit_lookup = true;
483 bool does_server_permit_storing = true;
484
_CacheDirectives_CacheDirectives485 _CacheDirectives() {}
486 } CacheDirectives;
487
488 typedef struct _CacheLookupInfo {
489 HttpTransact::CacheAction_t action = CACHE_DO_UNDEFINED;
490 HttpTransact::CacheAction_t transform_action = CACHE_DO_UNDEFINED;
491
492 HttpTransact::CacheWriteStatus_t write_status = NO_CACHE_WRITE;
493 HttpTransact::CacheWriteStatus_t transform_write_status = NO_CACHE_WRITE;
494
495 URL *lookup_url = nullptr;
496 URL lookup_url_storage;
497 URL original_url;
498 HTTPInfo object_store;
499 HTTPInfo transform_store;
500 CacheDirectives directives;
501 HTTPInfo *object_read = nullptr;
502 int open_read_retries = 0;
503 int open_write_retries = 0;
504 CacheWriteLock_t write_lock_state = CACHE_WL_INIT;
505 int lookup_count = 0;
506 SquidHitMissCode hit_miss_code = SQUID_MISS_NONE;
507 URL *parent_selection_url = nullptr;
508 URL parent_selection_url_storage;
509
_CacheLookupInfo_CacheLookupInfo510 _CacheLookupInfo() {}
511 } CacheLookupInfo;
512
513 typedef struct _RedirectInfo {
514 bool redirect_in_process = false;
515 URL original_url;
516
_RedirectInfo_RedirectInfo517 _RedirectInfo() {}
518 } RedirectInfo;
519
520 struct ConnectionAttributes {
521 HTTPVersion http_version;
522 HTTPKeepAlive keep_alive = HTTP_KEEPALIVE_UNDEFINED;
523
524 // The following variable is true if the client expects to
525 // received a chunked response.
526 bool receive_chunked_response = false;
527 bool proxy_connect_hdr = false;
528 /// @c errno from the most recent attempt to connect.
529 /// zero means no failure (not attempted, succeeded).
530 int connect_result = 0;
531 char *name = nullptr;
532 TransferEncoding_t transfer_encoding = NO_TRANSFER_ENCODING;
533
534 /** This is the source address of the connection from the point of view of the transaction.
535 It is the address of the source of the request.
536 */
537 IpEndpoint src_addr;
538 /** This is the destination address of the connection from the point of view of the transaction.
539 It is the address of the target of the request.
540 */
541 IpEndpoint dst_addr;
542
543 ServerState_t state = STATE_UNDEFINED;
544 AbortState_t abort = ABORT_UNDEFINED;
545 HttpProxyPort::TransportType port_attribute = HttpProxyPort::TRANSPORT_DEFAULT;
546
547 /// @c true if the connection is transparent.
548 bool is_transparent = false;
549 ProxyError rx_error_code;
550 ProxyError tx_error_code;
551
552 bool
had_connect_failConnectionAttributes553 had_connect_fail() const
554 {
555 return 0 != connect_result;
556 }
557 void
clear_connect_failConnectionAttributes558 clear_connect_fail()
559 {
560 connect_result = 0;
561 }
ConnectionAttributesConnectionAttributes562 ConnectionAttributes() { clear(); }
563
564 void
clearConnectionAttributes565 clear()
566 {
567 ink_zero(src_addr);
568 ink_zero(dst_addr);
569 connect_result = 0;
570 }
571 };
572
573 typedef struct _CurrentInfo {
574 ProxyMode_t mode = UNDEFINED_MODE;
575 LookingUp_t request_to = UNDEFINED_LOOKUP;
576 ConnectionAttributes *server = nullptr;
577 ink_time_t now = 0;
578 ServerState_t state = STATE_UNDEFINED;
579 unsigned attempts = 0;
580 unsigned simple_retry_attempts = 0;
581 unsigned unavailable_server_retry_attempts = 0;
582 ParentRetry_t retry_type = PARENT_RETRY_NONE;
583
_CurrentInfo_CurrentInfo584 _CurrentInfo() {}
585 } CurrentInfo;
586
587 typedef struct _DNSLookupInfo {
588 /** Origin server address source selection.
589
590 If config says to use CTA (client target addr) state is
591 OS_ADDR_TRY_CLIENT, otherwise it remains the default. If the
592 connect fails then we switch to a USE. We go to USE_HOSTDB if
593 (1) the HostDB lookup is successful and (2) some address other
594 than the CTA is available to try. Otherwise we keep retrying
595 on the CTA (USE_CLIENT) up to the max retry value. In essence
596 we try to treat the CTA as if it were another RR value in the
597 HostDB record.
598 */
599 enum class OS_Addr {
600 OS_ADDR_TRY_DEFAULT, ///< Initial state, use what config says.
601 OS_ADDR_TRY_HOSTDB, ///< Try HostDB data.
602 OS_ADDR_TRY_CLIENT, ///< Try client target addr.
603 OS_ADDR_USE_HOSTDB, ///< Force use of HostDB target address.
604 OS_ADDR_USE_CLIENT ///< Use client target addr, no fallback.
605 };
606
607 OS_Addr os_addr_style = OS_Addr::OS_ADDR_TRY_DEFAULT;
608
609 bool lookup_success = false;
610 char *lookup_name = nullptr;
611 char srv_hostname[MAXDNAME] = {0};
612 LookingUp_t looking_up = UNDEFINED_LOOKUP;
613 bool srv_lookup_success = false;
614 short srv_port = 0;
615 HostDBApplicationInfo srv_app;
616
617 /*** Set to true by default. If use_client_target_address is set
618 * to 1, this value will be set to false if the client address is
619 * not in the DNS pool */
620 bool lookup_validated = true;
621
_DNSLookupInfo_DNSLookupInfo622 _DNSLookupInfo() {}
623 } DNSLookupInfo;
624
625 // Conversion handling for DNS host resolution type.
626 static const MgmtConverter HOST_RES_CONV;
627
628 typedef struct _HeaderInfo {
629 HTTPHdr client_request;
630 HTTPHdr client_response;
631 HTTPHdr server_request;
632 HTTPHdr server_response;
633 HTTPHdr transform_response;
634 HTTPHdr cache_response;
635 int64_t request_content_length = HTTP_UNDEFINED_CL;
636 int64_t response_content_length = HTTP_UNDEFINED_CL;
637 int64_t transform_request_cl = HTTP_UNDEFINED_CL;
638 int64_t transform_response_cl = HTTP_UNDEFINED_CL;
639 bool client_req_is_server_style = false;
640 bool trust_response_cl = false;
641 ResponseError_t response_error = NO_RESPONSE_HEADER_ERROR;
642 bool extension_method = false;
643
_HeaderInfo_HeaderInfo644 _HeaderInfo() {}
645 } HeaderInfo;
646
647 typedef struct _SquidLogInfo {
648 SquidLogCode log_code = SQUID_LOG_ERR_UNKNOWN;
649 SquidSubcode subcode = SQUID_SUBCODE_EMPTY;
650 SquidHierarchyCode hier_code = SQUID_HIER_EMPTY;
651 SquidHitMissCode hit_miss_code = SQUID_MISS_NONE;
652
_SquidLogInfo_SquidLogInfo653 _SquidLogInfo() {}
654 } SquidLogInfo;
655
656 struct State {
657 HttpTransactMagic_t m_magic = HTTP_TRANSACT_MAGIC_ALIVE;
658
659 HttpSM *state_machine = nullptr;
660
661 Arena arena;
662
663 HttpConfigParams *http_config_param = nullptr;
664 CacheLookupInfo cache_info;
665 DNSLookupInfo dns_info;
666 RedirectInfo redirect_info;
667 OutboundConnTrack::TxnState outbound_conn_track_state;
668 HTTPVersion updated_server_version = HTTP_INVALID;
669 bool force_dns = false;
670 MgmtByte cache_open_write_fail_action = 0;
671 ConnectionAttributes client_info;
672 ConnectionAttributes parent_info;
673 ConnectionAttributes server_info;
674
675 Source_t source = SOURCE_NONE;
676 Source_t pre_transform_source = SOURCE_NONE;
677 HttpRequestFlavor_t req_flavor = REQ_FLAVOR_FWDPROXY;
678
679 CurrentInfo current;
680 HeaderInfo hdr_info;
681 SquidLogInfo squid_codes;
682 HttpApiInfo api_info;
683 // To handle parent proxy case, we need to be
684 // able to defer some work in building the request
685 TransactFunc_t pending_work = nullptr;
686
687 HttpRequestData request_data;
688 ParentConfigParams *parent_params = nullptr;
689 std::shared_ptr<NextHopSelectionStrategy> next_hop_strategy = nullptr;
690 ParentResult parent_result;
691 CacheControlResult cache_control;
692 CacheLookupResult_t cache_lookup_result = CACHE_LOOKUP_NONE;
693
694 StateMachineAction_t next_action = SM_ACTION_UNDEFINED; // out
695 StateMachineAction_t api_next_action = SM_ACTION_UNDEFINED; // out
696 void (*transact_return_point)(HttpTransact::State *s) = nullptr; // out
697
698 // We keep this so we can jump back to the upgrade handler after remap is complete
699 void (*post_remap_upgrade_return_point)(HttpTransact::State *s) = nullptr; // out
700 const char *upgrade_token_wks = nullptr;
701 bool is_upgrade_request = false;
702
703 // Some WebSocket state
704 bool is_websocket = false;
705 bool did_upgrade_succeed = false;
706
707 char *internal_msg_buffer = nullptr; // out
708 char *internal_msg_buffer_type = nullptr; // out
709 int64_t internal_msg_buffer_size = 0; // out
710 int64_t internal_msg_buffer_fast_allocator_size = -1;
711
712 int scheme = -1; // out
713 int next_hop_scheme = scheme; // out
714 int orig_scheme = scheme; // pre-mapped scheme
715 int method = 0;
716 int cause_of_death_errno = -UNKNOWN_INTERNAL_ERROR; // in
717 Ptr<HostDBInfo> hostdb_entry; // Pointer to the entry we are referencing in hostdb-- to keep our ref
718 HostDBInfo host_db_info; // in
719
720 ink_time_t client_request_time = UNDEFINED_TIME; // internal
721 ink_time_t request_sent_time = UNDEFINED_TIME; // internal
722 ink_time_t response_received_time = UNDEFINED_TIME; // internal
723 ink_time_t plugin_set_expire_time = UNDEFINED_TIME;
724
725 char via_string[MAX_VIA_INDICES + 1];
726
727 int64_t state_machine_id = 0;
728
729 // new ACL filtering result (calculated immediately after remap)
730 bool client_connection_enabled = true;
731 bool acl_filtering_performed = false;
732
733 /// True if the response is cacheable because of negative caching configuration.
734 ///
735 /// This being true implies the following:
736 ///
737 /// * The response code was negative.
738 /// * Negative caching is enabled.
739 /// * The response is considered cacheable because of negative caching
740 /// configuration.
741 bool is_cacheable_due_to_negative_caching_configuration = false;
742 // for authenticated content caching
743 CacheAuth_t www_auth_content = CACHE_AUTH_NONE;
744
745 RemapPluginInst *os_response_plugin_inst = nullptr;
746 HTTPStatus http_return_code = HTTP_STATUS_NONE;
747
748 int api_txn_active_timeout_value = -1;
749 int api_txn_connect_timeout_value = -1;
750 int api_txn_dns_timeout_value = -1;
751 int api_txn_no_activity_timeout_value = -1;
752
753 // Used by INKHttpTxnCachedReqGet and INKHttpTxnCachedRespGet SDK functions
754 // to copy part of HdrHeap (only the writable portion) for cached response headers
755 // and request headers
756 // These ptrs are deallocate when transaction is over.
757 HdrHeapSDKHandle *cache_req_hdr_heap_handle = nullptr;
758 HdrHeapSDKHandle *cache_resp_hdr_heap_handle = nullptr;
759 bool api_cleanup_cache_read = false;
760 bool api_server_response_no_store = false;
761 bool api_server_response_ignore = false;
762 bool api_http_sm_shutdown = false;
763 bool api_modifiable_cached_resp = false;
764 bool api_server_request_body_set = false;
765 bool api_req_cacheable = false;
766 bool api_resp_cacheable = false;
767 bool api_server_addr_set = false;
768 UpdateCachedObject_t api_update_cached_object = UPDATE_CACHED_OBJECT_NONE;
769 StateMachineAction_t saved_update_next_action = SM_ACTION_UNDEFINED;
770 CacheAction_t saved_update_cache_action = CACHE_DO_UNDEFINED;
771
772 // Remap plugin processor support
773 UrlMappingContainer url_map;
774 host_hdr_info hh_info = {nullptr, 0, 0};
775
776 int congestion_control_crat = 0; // Client retry after
777
778 unsigned int filter_mask = 0;
779 char *remap_redirect = nullptr;
780 bool reverse_proxy = false;
781 bool url_remap_success = false;
782
783 bool api_skip_all_remapping = false;
784
785 bool already_downgraded = false;
786 URL unmapped_url; // unmapped url is the effective url before remap
787
788 // Http Range: related variables
789 RangeSetup_t range_setup = RANGE_NONE;
790 int64_t num_range_fields = 0;
791 int64_t range_output_cl = 0;
792 RangeRecord *ranges = nullptr;
793
794 OverridableHttpConfigParams const *txn_conf = nullptr;
795 OverridableHttpConfigParams &
my_txn_confState796 my_txn_conf() // Storage for plugins, to avoid malloc
797 {
798 auto p = reinterpret_cast<OverridableHttpConfigParams *>(_my_txn_conf);
799
800 ink_assert(p == txn_conf);
801
802 return *p;
803 }
804
805 bool transparent_passthrough = false;
806 bool range_in_cache = false;
807
808 // Methods
809 void
initState810 init()
811 {
812 parent_params = ParentConfig::acquire();
813 }
814
815 // Constructor
StateState816 State()
817 {
818 int i;
819 char *via_ptr = via_string;
820
821 for (i = 0; i < MAX_VIA_INDICES; i++) {
822 *via_ptr++ = ' ';
823 }
824
825 via_string[VIA_CLIENT] = VIA_CLIENT_STRING;
826 via_string[VIA_CACHE] = VIA_CACHE_STRING;
827 via_string[VIA_SERVER] = VIA_SERVER_STRING;
828 via_string[VIA_CACHE_FILL] = VIA_CACHE_FILL_STRING;
829 via_string[VIA_PROXY] = VIA_PROXY_STRING;
830 via_string[VIA_ERROR] = VIA_ERROR_STRING;
831 via_string[VIA_ERROR_TYPE] = VIA_ERROR_NO_ERROR;
832 via_string[VIA_DETAIL_SEPARATOR] = VIA_DETAIL_SEPARATOR_STRING;
833 via_string[VIA_DETAIL_TUNNEL_DESCRIPTOR] = VIA_DETAIL_TUNNEL_DESCRIPTOR_STRING;
834 via_string[VIA_DETAIL_CACHE_DESCRIPTOR] = VIA_DETAIL_CACHE_DESCRIPTOR_STRING;
835 via_string[VIA_DETAIL_PP_DESCRIPTOR] = VIA_DETAIL_PP_DESCRIPTOR_STRING;
836 via_string[VIA_DETAIL_SERVER_DESCRIPTOR] = VIA_DETAIL_SERVER_DESCRIPTOR_STRING;
837 via_string[MAX_VIA_INDICES] = '\0';
838
839 memset((void *)&host_db_info, 0, sizeof(host_db_info));
840 }
841
842 void
destroyState843 destroy()
844 {
845 m_magic = HTTP_TRANSACT_MAGIC_DEAD;
846
847 free_internal_msg_buffer();
848 ats_free(internal_msg_buffer_type);
849
850 ParentConfig::release(parent_params);
851 parent_params = nullptr;
852
853 hdr_info.client_request.destroy();
854 hdr_info.client_response.destroy();
855 hdr_info.server_request.destroy();
856 hdr_info.server_response.destroy();
857 hdr_info.transform_response.destroy();
858 hdr_info.cache_response.destroy();
859 cache_info.lookup_url_storage.destroy();
860 cache_info.parent_selection_url_storage.destroy();
861 cache_info.original_url.destroy();
862 cache_info.object_store.destroy();
863 cache_info.transform_store.destroy();
864 redirect_info.original_url.destroy();
865
866 url_map.clear();
867 arena.reset();
868 unmapped_url.clear();
869 hostdb_entry.clear();
870 outbound_conn_track_state.clear();
871
872 delete[] ranges;
873 ranges = nullptr;
874 range_setup = RANGE_NONE;
875 return;
876 }
877
878 // Little helper function to setup the per-transaction configuration copy
879 void
setup_per_txn_configsState880 setup_per_txn_configs()
881 {
882 if (txn_conf != reinterpret_cast<OverridableHttpConfigParams *>(_my_txn_conf)) {
883 txn_conf = reinterpret_cast<OverridableHttpConfigParams *>(_my_txn_conf);
884 memcpy(_my_txn_conf, &http_config_param->oride, sizeof(_my_txn_conf));
885 }
886 }
887
888 void
free_internal_msg_bufferState889 free_internal_msg_buffer()
890 {
891 if (internal_msg_buffer) {
892 if (internal_msg_buffer_fast_allocator_size >= 0) {
893 ioBufAllocator[internal_msg_buffer_fast_allocator_size].free_void(internal_msg_buffer);
894 } else {
895 ats_free(internal_msg_buffer);
896 }
897 internal_msg_buffer = nullptr;
898 }
899 internal_msg_buffer_size = 0;
900 }
901
902 ProxyProtocol pp_info;
903
904 void
set_connect_failState905 set_connect_fail(int e)
906 {
907 if (e == EIO || this->current.server->connect_result == EIO) {
908 this->current.server->connect_result = e;
909 }
910 if (e != EIO) {
911 this->cause_of_death_errno = e;
912 }
913 }
914
915 private:
916 // Make this a raw byte array, so it will be accessed through the my_txn_conf() member function.
917 alignas(OverridableHttpConfigParams) char _my_txn_conf[sizeof(OverridableHttpConfigParams)];
918
919 }; // End of State struct.
920
921 static void HandleBlindTunnel(State *s);
922 static void StartRemapRequest(State *s);
923 static void EndRemapRequest(State *s);
924 static void PerformRemap(State *s);
925 static void ModifyRequest(State *s);
926 static void HandleRequest(State *s);
927 static void HandleRequestBufferDone(State *s);
928 static bool handleIfRedirect(State *s);
929
930 static void StartAccessControl(State *s);
931 static void HandleRequestAuthorized(State *s);
932 static void BadRequest(State *s);
933 static void Forbidden(State *s);
934 static void SelfLoop(State *s);
935 static void TooEarly(State *s);
936 static void OriginDead(State *s);
937 static void PostActiveTimeoutResponse(State *s);
938 static void PostInactiveTimeoutResponse(State *s);
939 static void DecideCacheLookup(State *s);
940 static void LookupSkipOpenServer(State *s);
941
942 static void CallOSDNSLookup(State *s);
943 static void OSDNSLookup(State *s);
944 static void ReDNSRoundRobin(State *s);
945 static void PPDNSLookup(State *s);
946 static void OriginServerRawOpen(State *s);
947 static void HandleCacheOpenRead(State *s);
948 static void HandleCacheOpenReadHitFreshness(State *s);
949 static void HandleCacheOpenReadHit(State *s);
950 static void HandleCacheOpenReadMiss(State *s);
951 static void build_response_from_cache(State *s, HTTPWarningCode warning_code);
952 static void handle_cache_write_lock(State *s);
953 static void HandleResponse(State *s);
954 static void HandleUpdateCachedObject(State *s);
955 static void HandleUpdateCachedObjectContinue(State *s);
956 static void HandleStatPage(State *s);
957 static void handle_100_continue_response(State *s);
958 static void handle_transform_ready(State *s);
959 static void handle_transform_cache_write(State *s);
960 static void handle_response_from_parent(State *s);
961 static void handle_response_from_server(State *s);
962 static void delete_server_rr_entry(State *s, int max_retries);
963 static void retry_server_connection_not_open(State *s, ServerState_t conn_state, unsigned max_retries);
964 static void error_log_connection_failure(State *s, ServerState_t conn_state);
965 static void handle_server_connection_not_open(State *s);
966 static void handle_forward_server_connection_open(State *s);
967 static void handle_cache_operation_on_forward_server_response(State *s);
968 static void handle_no_cache_operation_on_forward_server_response(State *s);
969 static void merge_and_update_headers_for_cache_update(State *s);
970 static void set_headers_for_cache_write(State *s, HTTPInfo *cache_info, HTTPHdr *request, HTTPHdr *response);
971 static void set_header_for_transform(State *s, HTTPHdr *base_header);
972 static void merge_response_header_with_cached_header(HTTPHdr *cached_header, HTTPHdr *response_header);
973 static void merge_warning_header(HTTPHdr *cached_header, HTTPHdr *response_header);
974 static void SetCacheFreshnessLimit(State *s);
975 static void HandleApiErrorJump(State *);
976 static void handle_websocket_upgrade_pre_remap(State *s);
977 static void handle_websocket_upgrade_post_remap(State *s);
978 static bool handle_upgrade_request(State *s);
979 static void handle_websocket_connection(State *s);
980
981 static void HandleCacheOpenReadPush(State *s, bool read_successful);
982 static void HandlePushResponseHdr(State *s);
983 static void HandlePushCacheWrite(State *s);
984 static void HandlePushTunnelSuccess(State *s);
985 static void HandlePushTunnelFailure(State *s);
986 static void HandlePushError(State *s, const char *reason);
987 static void HandleBadPushRespHdr(State *s);
988
989 // Utility Methods
990 static void issue_revalidate(State *s);
991 static bool get_ka_info_from_config(State *s, ConnectionAttributes *server_info);
992 static void get_ka_info_from_host_db(State *s, ConnectionAttributes *server_info, ConnectionAttributes *client_info,
993 HostDBInfo *host_db_info);
994 static void setup_plugin_request_intercept(State *s);
995 static void add_client_ip_to_outgoing_request(State *s, HTTPHdr *request);
996 static RequestError_t check_request_validity(State *s, HTTPHdr *incoming_hdr);
997 static ResponseError_t check_response_validity(State *s, HTTPHdr *incoming_hdr);
998 static void set_client_request_state(State *s, HTTPHdr *incoming_hdr);
999 static bool delete_all_document_alternates_and_return(State *s, bool cache_hit);
1000 static bool does_client_request_permit_cached_response(const OverridableHttpConfigParams *p, CacheControlResult *c, HTTPHdr *h,
1001 char *via_string);
1002 static bool does_client_request_permit_dns_caching(CacheControlResult *c, HTTPHdr *h);
1003 static bool does_client_request_permit_storing(CacheControlResult *c, HTTPHdr *h);
1004 static bool handle_internal_request(State *s, HTTPHdr *incoming_hdr);
1005 static bool handle_trace_and_options_requests(State *s, HTTPHdr *incoming_hdr);
1006 static void bootstrap_state_variables_from_request(State *s, HTTPHdr *incoming_request);
1007 static void initialize_state_variables_from_request(State *s, HTTPHdr *obsolete_incoming_request);
1008 static void initialize_state_variables_from_response(State *s, HTTPHdr *incoming_response);
1009 static bool is_server_negative_cached(State *s);
1010 static bool is_cache_response_returnable(State *s);
1011 static bool is_stale_cache_response_returnable(State *s);
1012 static bool need_to_revalidate(State *s);
1013 static bool url_looks_dynamic(URL *url);
1014 static bool is_request_cache_lookupable(State *s);
1015 static bool is_request_valid(State *s, HTTPHdr *incoming_request);
1016 static bool is_request_retryable(State *s);
1017
1018 static bool is_response_cacheable(State *s, HTTPHdr *request, HTTPHdr *response);
1019 static bool is_response_valid(State *s, HTTPHdr *incoming_response);
1020
1021 static void process_quick_http_filter(State *s, int method);
1022 static bool will_this_request_self_loop(State *s);
1023 static bool is_request_likely_cacheable(State *s, HTTPHdr *request);
1024 static bool is_cache_hit(CacheLookupResult_t r);
1025 static bool is_fresh_cache_hit(CacheLookupResult_t r);
1026
1027 static void build_request(State *s, HTTPHdr *base_request, HTTPHdr *outgoing_request, HTTPVersion outgoing_version);
1028 static void build_response(State *s, HTTPHdr *base_response, HTTPHdr *outgoing_response, HTTPVersion outgoing_version,
1029 HTTPStatus status_code, const char *reason_phrase = nullptr);
1030 static void build_response(State *s, HTTPHdr *base_response, HTTPHdr *outgoing_response, HTTPVersion outgoing_version);
1031 static void build_response(State *s, HTTPHdr *outgoing_response, HTTPVersion outgoing_version, HTTPStatus status_code,
1032 const char *reason_phrase = nullptr);
1033
1034 static void build_response_copy(State *s, HTTPHdr *base_response, HTTPHdr *outgoing_response, HTTPVersion outgoing_version);
1035 static void handle_content_length_header(State *s, HTTPHdr *header, HTTPHdr *base);
1036 static void change_response_header_because_of_range_request(State *s, HTTPHdr *header);
1037
1038 static void handle_request_keep_alive_headers(State *s, HTTPVersion ver, HTTPHdr *heads);
1039 static void handle_response_keep_alive_headers(State *s, HTTPVersion ver, HTTPHdr *heads);
1040 static int get_max_age(HTTPHdr *response);
1041 static int calculate_document_freshness_limit(State *s, HTTPHdr *response, time_t response_date, bool *heuristic);
1042 static Freshness_t what_is_document_freshness(State *s, HTTPHdr *client_request, HTTPHdr *cached_obj_response);
1043 static Authentication_t AuthenticationNeeded(const OverridableHttpConfigParams *p, HTTPHdr *client_request,
1044 HTTPHdr *obj_response);
1045 static void handle_parent_died(State *s);
1046 static void handle_server_died(State *s);
1047 static void build_error_response(State *s, HTTPStatus status_code, const char *reason_phrase_or_null,
1048 const char *error_body_type);
1049 static void build_redirect_response(State *s);
1050 static const char *get_error_string(int erno);
1051
1052 // the stat functions
1053 static void update_size_and_time_stats(State *s, ink_hrtime total_time, ink_hrtime user_agent_write_time,
1054 ink_hrtime origin_server_read_time, int user_agent_request_header_size,
1055 int64_t user_agent_request_body_size, int user_agent_response_header_size,
1056 int64_t user_agent_response_body_size, int origin_server_request_header_size,
1057 int64_t origin_server_request_body_size, int origin_server_response_header_size,
1058 int64_t origin_server_response_body_size, int pushed_response_header_size,
1059 int64_t pushed_response_body_size, const TransactionMilestones &milestones);
1060 static void histogram_request_document_size(State *s, int64_t size);
1061 static void histogram_response_document_size(State *s, int64_t size);
1062 static void user_agent_connection_speed(State *s, ink_hrtime transfer_time, int64_t nbytes);
1063 static void origin_server_connection_speed(State *s, ink_hrtime transfer_time, int64_t nbytes);
1064 static void client_result_stat(State *s, ink_hrtime total_time, ink_hrtime request_process_time);
1065 static void delete_warning_value(HTTPHdr *to_warn, HTTPWarningCode warning_code);
1066 static bool is_connection_collapse_checks_success(State *s); // YTS Team, yamsat
1067 };
1068
1069 typedef void (*TransactEntryFunc_t)(HttpTransact::State *s);
1070
1071 /* The spec says about message body the following:
1072 *
1073 * All responses to the HEAD and CONNECT request method
1074 * MUST NOT include a message-body, even though the presence
1075 * of entity-header fields might lead one to believe they do.
1076 *
1077 * All 1xx (informational), 204 (no content), and 304 (not modified)
1078 * responses MUST NOT include a message-body.
1079 *
1080 * Refer : [https://tools.ietf.org/html/rfc7231#section-4.3.6]
1081 */
1082 inline bool
is_response_body_precluded(HTTPStatus status_code)1083 is_response_body_precluded(HTTPStatus status_code)
1084 {
1085 if (((status_code != HTTP_STATUS_OK) &&
1086 ((status_code == HTTP_STATUS_NOT_MODIFIED) || ((status_code < HTTP_STATUS_OK) && (status_code >= HTTP_STATUS_CONTINUE)) ||
1087 (status_code == HTTP_STATUS_NO_CONTENT)))) {
1088 return true;
1089 } else {
1090 return false;
1091 }
1092 }
1093
1094 inline bool
is_response_body_precluded(HTTPStatus status_code,int method)1095 is_response_body_precluded(HTTPStatus status_code, int method)
1096 {
1097 if ((method == HTTP_WKSIDX_HEAD) || (method == HTTP_WKSIDX_CONNECT) || is_response_body_precluded(status_code)) {
1098 return true;
1099 } else {
1100 return false;
1101 }
1102 }
1103
1104 inkcoreapi extern ink_time_t ink_local_time();
1105