xref: /trafficserver/proxy/http/HttpSM.h (revision 678b605a)
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 /****************************************************************************
25 
26    HttpSM.h
27 
28    Description:
29 
30 
31  ****************************************************************************/
32 #pragma once
33 
34 #include <string_view>
35 #include <optional>
36 
37 #include "tscore/ink_platform.h"
38 #include "P_EventSystem.h"
39 #include "HttpCacheSM.h"
40 #include "HttpTransact.h"
41 #include "UrlRewrite.h"
42 #include "HttpTunnel.h"
43 #include "InkAPIInternal.h"
44 #include "../ProxyTransaction.h"
45 #include "HdrUtils.h"
46 #include "tscore/History.h"
47 
48 #define HTTP_API_CONTINUE (INK_API_EVENT_EVENTS_START + 0)
49 #define HTTP_API_ERROR (INK_API_EVENT_EVENTS_START + 1)
50 
51 // The default size for http header buffers when we don't
52 //   need to include extra space for the document
53 static size_t const HTTP_HEADER_BUFFER_SIZE_INDEX = CLIENT_CONNECTION_FIRST_READ_BUFFER_SIZE_INDEX;
54 
55 // We want to use a larger buffer size when reading response
56 //   headers from the origin server since we want to get
57 //   as much of the document as possible on the first read
58 //   Marco benchmarked about 3% ops/second improvement using
59 //   the larger buffer size
60 static size_t const HTTP_SERVER_RESP_HDR_BUFFER_INDEX = BUFFER_SIZE_INDEX_8K;
61 
62 class Http1ServerSession;
63 class AuthHttpAdapter;
64 
65 class HttpSM;
66 typedef int (HttpSM::*HttpSMHandler)(int event, void *data);
67 
68 enum HttpVC_t {
69   HTTP_UNKNOWN = 0,
70   HTTP_UA_VC,
71   HTTP_SERVER_VC,
72   HTTP_TRANSFORM_VC,
73   HTTP_CACHE_READ_VC,
74   HTTP_CACHE_WRITE_VC,
75   HTTP_RAW_SERVER_VC
76 };
77 
78 enum BackgroundFill_t {
79   BACKGROUND_FILL_NONE = 0,
80   BACKGROUND_FILL_STARTED,
81   BACKGROUND_FILL_ABORTED,
82   BACKGROUND_FILL_COMPLETED,
83 };
84 
85 extern ink_mutex debug_sm_list_mutex;
86 
87 struct HttpVCTableEntry {
88   VConnection *vc;
89   MIOBuffer *read_buffer;
90   MIOBuffer *write_buffer;
91   VIO *read_vio;
92   VIO *write_vio;
93   HttpSMHandler vc_handler;
94   HttpVC_t vc_type;
95   HttpSM *sm;
96   bool eos;
97   bool in_tunnel;
98 };
99 
100 struct HttpVCTable {
101   static const int vc_table_max_entries = 4;
102   explicit HttpVCTable(HttpSM *);
103 
104   HttpVCTableEntry *new_entry();
105   HttpVCTableEntry *find_entry(VConnection *);
106   HttpVCTableEntry *find_entry(VIO *);
107   void remove_entry(HttpVCTableEntry *);
108   void cleanup_entry(HttpVCTableEntry *);
109   void cleanup_all();
110   bool is_table_clear() const;
111 
112 private:
113   HttpVCTableEntry vc_table[vc_table_max_entries];
114   HttpSM *sm = nullptr;
115 };
116 
117 inline bool
is_table_clear() const118 HttpVCTable::is_table_clear() const
119 {
120   for (const auto &i : vc_table) {
121     if (i.vc != nullptr) {
122       return false;
123     }
124   }
125   return true;
126 }
127 
128 struct HttpTransformInfo {
129   HttpVCTableEntry *entry = nullptr;
130   VConnection *vc         = nullptr;
131 
HttpTransformInfoHttpTransformInfo132   HttpTransformInfo() {}
133 };
134 
135 enum {
136   HTTP_SM_MAGIC_ALIVE = 0x0000FEED,
137   HTTP_SM_MAGIC_DEAD  = 0xDEADFEED,
138 };
139 
140 enum {
141   HTTP_SM_POST_UNKNOWN     = 0,
142   HTTP_SM_POST_UA_FAIL     = 1,
143   HTTP_SM_POST_SERVER_FAIL = 2,
144   HTTP_SM_POST_SUCCESS     = 3,
145 };
146 
147 enum {
148   HTTP_SM_TRANSFORM_OPEN   = 0,
149   HTTP_SM_TRANSFORM_CLOSED = 1,
150   HTTP_SM_TRANSFORM_FAIL   = 2,
151 };
152 
153 enum HttpApiState_t {
154   HTTP_API_NO_CALLOUT,
155   HTTP_API_IN_CALLOUT,
156   HTTP_API_DEFERED_CLOSE,
157   HTTP_API_DEFERED_SERVER_ERROR,
158   HTTP_API_REWIND_STATE_MACHINE,
159 };
160 
161 enum HttpPluginTunnel_t {
162   HTTP_NO_PLUGIN_TUNNEL = 0,
163   HTTP_PLUGIN_AS_SERVER,
164   HTTP_PLUGIN_AS_INTERCEPT,
165 };
166 
167 class CoreUtils;
168 class PluginVCCore;
169 
170 class PostDataBuffers
171 {
172 public:
PostDataBuffers()173   PostDataBuffers() { Debug("http_redirect", "[PostDataBuffers::PostDataBuffers]"); }
174   MIOBuffer *postdata_copy_buffer            = nullptr;
175   IOBufferReader *postdata_copy_buffer_start = nullptr;
176   IOBufferReader *ua_buffer_reader           = nullptr;
177   bool post_data_buffer_done                 = false;
178 
179   void clear();
180   void init(IOBufferReader *ua_reader);
181   void copy_partial_post_data();
182   IOBufferReader *get_post_data_buffer_clone_reader();
183   void
set_post_data_buffer_done(bool done)184   set_post_data_buffer_done(bool done)
185   {
186     post_data_buffer_done = done;
187   }
188   bool
get_post_data_buffer_done()189   get_post_data_buffer_done()
190   {
191     return post_data_buffer_done;
192   }
193   bool
is_valid()194   is_valid()
195   {
196     return postdata_copy_buffer_start != nullptr;
197   }
198 
199   ~PostDataBuffers();
200 };
201 
202 class HttpSM : public Continuation, public PluginUserArgs<TS_USER_ARGS_TXN>
203 {
204   friend class HttpPagesHandler;
205   friend class CoreUtils;
206 
207 public:
208   HttpSM();
209   void cleanup();
210   virtual void destroy();
211 
212   static HttpSM *allocate();
213   HttpCacheSM &get_cache_sm(); // Added to get the object of CacheSM YTS Team, yamsat
214 
215   void init(bool from_early_data = false);
216 
217   void attach_client_session(ProxyTransaction *client_vc_arg, IOBufferReader *buffer_reader);
218 
219   // Called by httpSessionManager so that we can reset
220   //  the session timeouts and initiate a read while
221   //  holding the lock for the server session
222   void attach_server_session(Http1ServerSession *s);
223 
224   // Used to read attributes of
225   // the current active server session
226   Http1ServerSession *
get_server_session()227   get_server_session()
228   {
229     return server_session;
230   }
231 
232   ProxyTransaction *
get_ua_txn()233   get_ua_txn()
234   {
235     return ua_txn;
236   }
237 
238   // Called by transact.  Updates are fire and forget
239   //  so there are no callbacks and are safe to do
240   //  directly from transact
241   void do_hostdb_update_if_necessary();
242 
243   // Called by transact. Decide if cached response supports Range and
244   // setup Range transfomration if so.
245   // return true when the Range is unsatisfiable
246   void do_range_setup_if_necessary();
247 
248   void do_range_parse(MIMEField *range_field);
249   void calculate_output_cl(int64_t, int64_t);
250   void parse_range_and_compare(MIMEField *, int64_t);
251 
252   // Called by transact to prevent reset problems
253   //  failed PUSH requests
254   void set_ua_half_close_flag();
255 
256   // Called by either state_hostdb_lookup() or directly
257   //   by the HostDB in the case of inline completion
258   // Handles the setting of all state necessary before
259   //   calling transact to process the hostdb lookup
260   // A NULL 'r' argument indicates the hostdb lookup failed
261   void process_hostdb_info(HostDBInfo *r);
262   void process_srv_info(HostDBInfo *r);
263 
264   // Called by transact.  Synchronous.
265   VConnection *do_transform_open();
266   VConnection *do_post_transform_open();
267 
268   // Called by transact(HttpTransact::is_request_retryable), temporarily.
269   // This function should be remove after #1994 fixed.
270   bool
is_post_transform_request()271   is_post_transform_request()
272   {
273     return t_state.method == HTTP_WKSIDX_POST && post_transform_info.vc;
274   }
275 
276   // Called from InkAPI.cc which acquires the state machine lock
277   //  before calling
278   int state_api_callback(int event, void *data);
279   int state_api_callout(int event, void *data);
280 
281   // Used for Http Stat Pages
282   HttpTunnel *
get_tunnel()283   get_tunnel()
284   {
285     return &tunnel;
286   }
287 
288   // Debugging routines to dump the SM history, hdrs
289   void dump_state_on_assert();
290   void dump_state_hdr(HTTPHdr *h, const char *s);
291 
292   // Functions for manipulating api hooks
293   void txn_hook_add(TSHttpHookID id, INKContInternal *cont);
294   APIHook *txn_hook_get(TSHttpHookID id);
295 
296   bool is_private();
297   bool is_redirect_required();
298 
299   /// Get the protocol stack for the inbound (client, user agent) connection.
300   /// @arg result [out] Array to store the results
301   /// @arg n [in] Size of the array @a result.
302   int populate_client_protocol(std::string_view *result, int n) const;
303   const char *client_protocol_contains(std::string_view tag_prefix) const;
304   std::string_view find_proto_string(HTTPVersion version) const;
305 
306   int64_t sm_id      = -1;
307   unsigned int magic = HTTP_SM_MAGIC_DEAD;
308 
309   // YTS Team, yamsat Plugin
310   bool enable_redirection = false; // To check if redirection is enabled
311   bool post_failed        = false; // Added to identify post failure
312   bool debug_on           = false; // Transaction specific debug flag
313   char *redirect_url    = nullptr; // url for force redirect (provide users a functionality to redirect to another url when needed)
314   int redirect_url_len  = 0;
315   int redirection_tries = 0;    // To monitor number of redirections
316   int64_t transfered_bytes = 0; // Added to calculate POST data
317 
318   // Tunneling request to plugin
319   HttpPluginTunnel_t plugin_tunnel_type = HTTP_NO_PLUGIN_TUNNEL;
320   PluginVCCore *plugin_tunnel           = nullptr;
321 
322   HttpTransact::State t_state;
323 
324   // This unfortunately can't go into the t_state, because of circular dependencies. We could perhaps refactor
325   // this, with a lot of work, but this is easier for now.
326   UrlRewrite *m_remap = nullptr;
327 
328   // _postbuf api
329   int64_t postbuf_reader_avail();
330   int64_t postbuf_buffer_avail();
331   void postbuf_clear();
332   void disable_redirect();
333   void postbuf_copy_partial_data();
334   void postbuf_init(IOBufferReader *ua_reader);
335   void set_postbuf_done(bool done);
336   IOBufferReader *get_postbuf_clone_reader();
337   bool get_postbuf_done();
338   bool is_postbuf_valid();
339 
340   // See if we should allow the transaction
341   // based on sni and host name header values
342   void check_sni_host();
343 
344 protected:
345   int reentrancy_count = 0;
346 
347   HttpTunnel tunnel;
348 
349   HttpVCTable vc_table;
350 
351   HttpVCTableEntry *ua_entry = nullptr;
352 
353 public:
354   ProxyTransaction *ua_txn         = nullptr;
355   BackgroundFill_t background_fill = BACKGROUND_FILL_NONE;
356   void set_http_schedule(Continuation *);
357   int get_http_schedule(int event, void *data);
358 
359   History<HISTORY_DEFAULT_SIZE> history;
360 
361 protected:
362   IOBufferReader *ua_buffer_reader     = nullptr;
363   IOBufferReader *ua_raw_buffer_reader = nullptr;
364 
365   HttpVCTableEntry *server_entry     = nullptr;
366   Http1ServerSession *server_session = nullptr;
367 
368   /* Because we don't want to take a session from a shared pool if we know that it will be private,
369    * but we cannot set it to private until we have an attached server session.
370    * So we use this variable to indicate that
371    * we should create a new connection and then once we attach the session we'll mark it as private.
372    */
373   bool will_be_private_ss              = false;
374   int shared_session_retries           = 0;
375   IOBufferReader *server_buffer_reader = nullptr;
376 
377   HttpTransformInfo transform_info;
378   HttpTransformInfo post_transform_info;
379   /// Set if plugin client / user agents are active.
380   /// Need primarily for cleanup.
381   bool has_active_plugin_agents = false;
382 
383   HttpCacheSM cache_sm;
384   HttpCacheSM transform_cache_sm;
385 
386   HttpSMHandler default_handler = nullptr;
387   Action *pending_action        = nullptr;
388   Continuation *schedule_cont   = nullptr;
389 
390   HTTPParser http_parser;
391   void start_sub_sm();
392 
393   int main_handler(int event, void *data);
394   int tunnel_handler(int event, void *data);
395   int tunnel_handler_push(int event, void *data);
396   int tunnel_handler_post(int event, void *data);
397 
398   // YTS Team, yamsat Plugin
399   int tunnel_handler_for_partial_post(int event, void *data);
400 
401   void tunnel_handler_post_or_put(HttpTunnelProducer *p);
402 
403   int tunnel_handler_100_continue(int event, void *data);
404   int tunnel_handler_cache_fill(int event, void *data);
405   int state_read_client_request_header(int event, void *data);
406   int state_watch_for_client_abort(int event, void *data);
407   int state_read_push_response_header(int event, void *data);
408   int state_hostdb_lookup(int event, void *data);
409   int state_hostdb_reverse_lookup(int event, void *data);
410   int state_mark_os_down(int event, void *data);
411   int state_handle_stat_page(int event, void *data);
412   int state_auth_callback(int event, void *data);
413   int state_add_to_list(int event, void *data);
414   int state_remove_from_list(int event, void *data);
415 
416   // Y! ebalsa: remap handlers
417   int state_remap_request(int event, void *data);
418   void do_remap_request(bool);
419 
420   // Cache Handlers
421   int state_cache_open_read(int event, void *data);
422   int state_cache_open_write(int event, void *data);
423 
424   // Http Server Handlers
425   int state_http_server_open(int event, void *data);
426   int state_raw_http_server_open(int event, void *data);
427   int state_send_server_request_header(int event, void *data);
428   int state_acquire_server_read(int event, void *data);
429   int state_read_server_response_header(int event, void *data);
430 
431   // API
432   int state_request_wait_for_transform_read(int event, void *data);
433   int state_response_wait_for_transform_read(int event, void *data);
434   int state_common_wait_for_transform_read(HttpTransformInfo *t_info, HttpSMHandler tunnel_handler, int event, void *data);
435 
436   // Tunnel event handlers
437   int tunnel_handler_server(int event, HttpTunnelProducer *p);
438   int tunnel_handler_ua(int event, HttpTunnelConsumer *c);
439   int tunnel_handler_ua_push(int event, HttpTunnelProducer *p);
440   int tunnel_handler_100_continue_ua(int event, HttpTunnelConsumer *c);
441   int tunnel_handler_cache_write(int event, HttpTunnelConsumer *c);
442   int tunnel_handler_cache_read(int event, HttpTunnelProducer *p);
443   int tunnel_handler_post_ua(int event, HttpTunnelProducer *c);
444   int tunnel_handler_post_server(int event, HttpTunnelConsumer *c);
445   int tunnel_handler_ssl_producer(int event, HttpTunnelProducer *p);
446   int tunnel_handler_ssl_consumer(int event, HttpTunnelConsumer *p);
447   int tunnel_handler_transform_write(int event, HttpTunnelConsumer *c);
448   int tunnel_handler_transform_read(int event, HttpTunnelProducer *p);
449   int tunnel_handler_plugin_agent(int event, HttpTunnelConsumer *c);
450 
451   void do_hostdb_lookup();
452   void do_hostdb_reverse_lookup();
453   void do_cache_lookup_and_read();
454   void do_http_server_open(bool raw = false);
455   void send_origin_throttled_response();
456   void do_setup_post_tunnel(HttpVC_t to_vc_type);
457   void do_cache_prepare_write();
458   void do_cache_prepare_write_transform();
459   void do_cache_prepare_update();
460   void do_cache_prepare_action(HttpCacheSM *c_sm, CacheHTTPInfo *object_read_info, bool retry, bool allow_multiple = false);
461   void do_cache_delete_all_alts(Continuation *cont);
462   void do_auth_callout();
463   int do_api_callout();
464   int do_api_callout_internal();
465   void do_redirect();
466   void redirect_request(const char *redirect_url, const int redirect_len);
467   void do_drain_request_body(HTTPHdr &response);
468 
469   void wait_for_full_body();
470 
471   virtual void handle_api_return();
472   void handle_server_setup_error(int event, void *data);
473   void handle_http_server_open();
474   void handle_post_failure();
475   void mark_host_failure(HostDBInfo *info, time_t time_down);
476   void mark_server_down_on_client_abort();
477   void release_server_session(bool serve_from_cache = false);
478   void set_ua_abort(HttpTransact::AbortState_t ua_abort, int event);
479   int write_header_into_buffer(HTTPHdr *h, MIOBuffer *b);
480   int write_response_header_into_buffer(HTTPHdr *h, MIOBuffer *b);
481   void setup_blind_tunnel_port();
482   void setup_client_header_nca();
483   void setup_client_read_request_header();
484   void setup_push_read_response_header();
485   void setup_server_read_response_header();
486   void setup_cache_lookup_complete_api();
487   void setup_server_send_request();
488   void setup_server_send_request_api();
489   HttpTunnelProducer *setup_server_transfer();
490   void setup_server_transfer_to_cache_only();
491   HttpTunnelProducer *setup_cache_read_transfer();
492   void setup_internal_transfer(HttpSMHandler handler);
493   void setup_error_transfer();
494   void setup_100_continue_transfer();
495   HttpTunnelProducer *setup_push_transfer_to_cache();
496   void setup_transform_to_server_transfer();
497   void setup_cache_write_transfer(HttpCacheSM *c_sm, VConnection *source_vc, HTTPInfo *store_info, int64_t skip_bytes,
498                                   const char *name);
499   void issue_cache_update();
500   void perform_cache_write_action();
501   void perform_transform_cache_write_action();
502   void perform_nca_cache_action();
503   void setup_blind_tunnel(bool send_response_hdr, IOBufferReader *initial = nullptr);
504   HttpTunnelProducer *setup_server_transfer_to_transform();
505   HttpTunnelProducer *setup_transfer_from_transform();
506   HttpTunnelProducer *setup_cache_transfer_to_transform();
507   HttpTunnelProducer *setup_transfer_from_transform_to_cache_only();
508   void setup_plugin_agents(HttpTunnelProducer *p);
509 
510   HttpTransact::StateMachineAction_t last_action     = HttpTransact::SM_ACTION_UNDEFINED;
511   int (HttpSM::*m_last_state)(int event, void *data) = nullptr;
512   virtual void set_next_state();
513   void call_transact_and_set_next_state(TransactEntryFunc_t f);
514 
515   bool is_http_server_eos_truncation(HttpTunnelProducer *);
516   bool is_bg_fill_necessary(HttpTunnelConsumer *c);
517   int find_server_buffer_size();
518   int find_http_resp_buffer_size(int64_t cl);
519   int64_t server_transfer_init(MIOBuffer *buf, int hdr_size);
520 
521 public:
522   // TODO:  Now that bodies can be empty, should the body counters be set to -1 ? TS-2213
523   // Stats & Logging Info
524   int client_request_hdr_bytes       = 0;
525   int64_t client_request_body_bytes  = 0;
526   int server_request_hdr_bytes       = 0;
527   int64_t server_request_body_bytes  = 0;
528   int server_response_hdr_bytes      = 0;
529   int64_t server_response_body_bytes = 0;
530   int client_response_hdr_bytes      = 0;
531   int64_t client_response_body_bytes = 0;
532   int cache_response_hdr_bytes       = 0;
533   int64_t cache_response_body_bytes  = 0;
534   int pushed_response_hdr_bytes      = 0;
535   int64_t pushed_response_body_bytes = 0;
536   bool client_tcp_reused             = false;
537   bool client_ssl_reused             = false;
538   bool client_connection_is_ssl      = false;
539   bool is_internal                   = false;
540   bool server_connection_is_ssl      = false;
541   bool is_waiting_for_full_body      = false;
542   bool is_using_post_buffer          = false;
543   std::optional<bool> mptcp_state; // Don't initialize, that marks it as "not defined".
544   const char *client_protocol     = "-";
545   const char *client_sec_protocol = "-";
546   const char *client_cipher_suite = "-";
547   const char *client_curve        = "-";
548   int server_transact_count       = 0;
549 
550   TransactionMilestones milestones;
551   ink_hrtime api_timer = 0;
552   // The next two enable plugins to tag the state machine for
553   // the purposes of logging so the instances can be correlated
554   // with the source plugin.
555   const char *plugin_tag = nullptr;
556   int64_t plugin_id      = 0;
557 
558   // hooks_set records whether there are any hooks relevant
559   //  to this transaction.  Used to avoid costly calls
560   //  do_api_callout_internal()
561   bool hooks_set = false;
562 
563 protected:
564   TSHttpHookID cur_hook_id = TS_HTTP_LAST_HOOK;
565   APIHook const *cur_hook  = nullptr;
566   HttpHookState hook_state;
567 
568   //
569   // Continuation time keeper
570   int64_t prev_hook_start_time = 0;
571 
572   int cur_hooks                = 0;
573   HttpApiState_t callout_state = HTTP_API_NO_CALLOUT;
574 
575   // api_hooks must not be changed directly
576   //  Use txn_hook_{ap,pre}pend so hooks_set is
577   //  updated
578   HttpAPIHooks api_hooks;
579 
580   // The terminate flag is set by handlers and checked by the
581   //   main handler who will terminate the state machine
582   //   when the flag is set
583   bool terminate_sm         = false;
584   bool kill_this_async_done = false;
585   bool parse_range_done     = false;
586   virtual int kill_this_async_hook(int event, void *data);
587   void kill_this();
588   void update_stats();
589   void transform_cleanup(TSHttpHookID hook, HttpTransformInfo *info);
590   bool is_transparent_passthrough_allowed();
591   void plugin_agents_cleanup();
592 
593 public:
594   LINK(HttpSM, debug_link);
595 
596 public:
597   bool set_server_session_private(bool private_session);
598   bool
is_dying() const599   is_dying() const
600   {
601     return terminate_sm;
602   }
603 
604   int
client_connection_id() const605   client_connection_id() const
606   {
607     return _client_connection_id;
608   }
609 
610   int
client_transaction_id() const611   client_transaction_id() const
612   {
613     return _client_transaction_id;
614   }
615 
616   int
client_transaction_priority_weight() const617   client_transaction_priority_weight() const
618   {
619     return _client_transaction_priority_weight;
620   }
621 
622   int
client_transaction_priority_dependence() const623   client_transaction_priority_dependence() const
624   {
625     return _client_transaction_priority_dependence;
626   }
627 
628   void set_server_netvc_inactivity_timeout(NetVConnection *netvc);
629   void set_server_netvc_active_timeout(NetVConnection *netvc);
630   void set_server_netvc_connect_timeout(NetVConnection *netvc);
631   void rewind_state_machine();
632 
633 private:
634   PostDataBuffers _postbuf;
635   int _client_connection_id = -1, _client_transaction_id = -1;
636   int _client_transaction_priority_weight = -1, _client_transaction_priority_dependence = -1;
637   bool _from_early_data = false;
638 };
639 
640 // Function to get the cache_sm object - YTS Team, yamsat
641 inline HttpCacheSM &
get_cache_sm()642 HttpSM::get_cache_sm()
643 {
644   return cache_sm;
645 }
646 
647 inline HttpSM *
allocate()648 HttpSM::allocate()
649 {
650   extern ClassAllocator<HttpSM> httpSMAllocator;
651   return httpSMAllocator.alloc();
652 }
653 
654 inline int
write_response_header_into_buffer(HTTPHdr * h,MIOBuffer * b)655 HttpSM::write_response_header_into_buffer(HTTPHdr *h, MIOBuffer *b)
656 {
657   if (t_state.client_info.http_version == HTTPVersion(0, 9)) {
658     return 0;
659   } else {
660     return write_header_into_buffer(h, b);
661   }
662 }
663 
664 inline int
find_server_buffer_size()665 HttpSM::find_server_buffer_size()
666 {
667   return find_http_resp_buffer_size(t_state.hdr_info.response_content_length);
668 }
669 
670 inline void
txn_hook_add(TSHttpHookID id,INKContInternal * cont)671 HttpSM::txn_hook_add(TSHttpHookID id, INKContInternal *cont)
672 {
673   api_hooks.append(id, cont);
674   hooks_set = true;
675 }
676 
677 inline APIHook *
txn_hook_get(TSHttpHookID id)678 HttpSM::txn_hook_get(TSHttpHookID id)
679 {
680   return api_hooks.get(id);
681 }
682 
683 inline bool
is_transparent_passthrough_allowed()684 HttpSM::is_transparent_passthrough_allowed()
685 {
686   return (t_state.client_info.is_transparent && ua_txn->is_transparent_passthrough_allowed() && ua_txn->is_first_transaction());
687 }
688 
689 inline int64_t
postbuf_reader_avail()690 HttpSM::postbuf_reader_avail()
691 {
692   return this->_postbuf.ua_buffer_reader->read_avail();
693 }
694 
695 inline int64_t
postbuf_buffer_avail()696 HttpSM::postbuf_buffer_avail()
697 {
698   return this->_postbuf.postdata_copy_buffer_start->read_avail();
699 }
700 
701 inline void
postbuf_clear()702 HttpSM::postbuf_clear()
703 {
704   this->_postbuf.clear();
705 }
706 
707 inline void
disable_redirect()708 HttpSM::disable_redirect()
709 {
710   this->enable_redirection = false;
711   this->_postbuf.clear();
712 }
713 
714 inline void
postbuf_copy_partial_data()715 HttpSM::postbuf_copy_partial_data()
716 {
717   this->_postbuf.copy_partial_post_data();
718 }
719 
720 inline void
postbuf_init(IOBufferReader * ua_reader)721 HttpSM::postbuf_init(IOBufferReader *ua_reader)
722 {
723   this->_postbuf.init(ua_reader);
724 }
725 
726 inline void
set_postbuf_done(bool done)727 HttpSM::set_postbuf_done(bool done)
728 {
729   this->_postbuf.set_post_data_buffer_done(done);
730 }
731 
732 inline bool
get_postbuf_done()733 HttpSM::get_postbuf_done()
734 {
735   return this->_postbuf.get_post_data_buffer_done();
736 }
737 
738 inline bool
is_postbuf_valid()739 HttpSM::is_postbuf_valid()
740 {
741   return this->_postbuf.is_valid();
742 }
743 
744 inline IOBufferReader *
get_postbuf_clone_reader()745 HttpSM::get_postbuf_clone_reader()
746 {
747   return this->_postbuf.get_post_data_buffer_clone_reader();
748 }
749