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