xref: /trafficserver/proxy/ProxySession.h (revision dd123e1e)
1 /** @file
2 
3   ProxySession - Base class for protocol client sessions.
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_platform.h"
27 #include "tscore/ink_resolver.h"
28 #include "tscore/TSSystemState.h"
29 #include <string_view>
30 #include <memory>
31 #include "P_Net.h"
32 #include "InkAPIInternal.h"
33 #include "http/Http1ServerSession.h"
34 #include "http/HttpSessionAccept.h"
35 #include "IPAllow.h"
36 #include "private/SSLProxySession.h"
37 
38 // Emit a debug message conditional on whether this particular client session
39 // has debugging enabled. This should only be called from within a client session
40 // member function.
41 #define SsnDebug(ssn, tag, ...) SpecificDebug((ssn)->debug(), tag, __VA_ARGS__)
42 
43 class ProxyTransaction;
44 
45 enum class ProxyErrorClass {
46   NONE,
47   SSN,
48   TXN,
49 };
50 
51 struct ProxyError {
ProxyErrorProxyError52   ProxyError() {}
ProxyErrorProxyError53   ProxyError(ProxyErrorClass cl, uint32_t co) : cls(cl), code(co) {}
54   size_t
strProxyError55   str(char *buf, size_t buf_len) const
56   {
57     size_t len = 0;
58 
59     if (this->cls == ProxyErrorClass::NONE) {
60       buf[0] = '-';
61       return 1;
62     }
63 
64     buf[0] = (this->cls == ProxyErrorClass::SSN) ? 'S' : 'T';
65     ++len;
66 
67     len += snprintf(buf + len, buf_len - len, "%" PRIx32, this->code);
68 
69     return len;
70   }
71 
72   ProxyErrorClass cls = ProxyErrorClass::NONE;
73   uint32_t code       = 0;
74 };
75 
76 /// Abstract class for HttpSM to interface with any session
77 class ProxySession : public VConnection, public PluginUserArgs<TS_USER_ARGS_SSN>
78 {
79 public:
80   ProxySession();
81   ProxySession(NetVConnection *vc);
82 
83   // noncopyable
84   ProxySession(ProxySession &) = delete;
85   ProxySession &operator=(const ProxySession &) = delete;
86 
87   static int64_t next_connection_id();
88 
89   // Virtual Methods
90   virtual void new_connection(NetVConnection *new_vc, MIOBuffer *iobuf, IOBufferReader *reader) = 0;
91   virtual void start()                                                                          = 0;
92   virtual void attach_server_session(Http1ServerSession *ssession, bool transaction_done = true);
93 
94   virtual void release(ProxyTransaction *trans) = 0;
95 
96   virtual void destroy() = 0;
97   virtual void free();
98 
99   virtual void increment_current_active_client_connections_stat() = 0;
100   virtual void decrement_current_active_client_connections_stat() = 0;
101 
102   // Virtual Accessors
103   NetVConnection *get_netvc() const;
104   virtual int get_transact_count() const          = 0;
105   virtual const char *get_protocol_string() const = 0;
106 
107   virtual void hook_add(TSHttpHookID id, INKContInternal *cont);
108 
109   virtual bool is_chunked_encoding_supported() const;
110 
111   virtual void set_half_close_flag(bool flag);
112   virtual bool get_half_close_flag() const;
113 
114   virtual Http1ServerSession *get_server_session() const;
115 
116   // Replicate NetVConnection API
117   virtual sockaddr const *get_client_addr();
118   virtual sockaddr const *get_local_addr();
119 
120   virtual void set_active_timeout(ink_hrtime timeout_in);
121   virtual void set_inactivity_timeout(ink_hrtime timeout_in);
122   virtual void cancel_inactivity_timeout();
123 
124   virtual int populate_protocol(std::string_view *result, int size) const;
125   virtual const char *protocol_contains(std::string_view tag_prefix) const;
126 
127   // Non-Virtual Methods
128   int do_api_callout(TSHttpHookID id);
129 
130   void set_debug(bool flag);
131   bool debug() const;
132 
133   void set_session_active();
134   void clear_session_active();
135   bool is_active() const;
136   bool is_draining() const;
137   bool is_client_closed() const;
138 
139   int64_t connection_id() const;
140   TSHttpHookID get_hookid() const;
141   bool has_hooks() const;
142 
143   virtual bool support_sni() const;
144 
145   APIHook *hook_get(TSHttpHookID id) const;
146   HttpAPIHooks const *feature_hooks() const;
147 
148   // Returns null pointer if session does not use a TLS connection.
149   SSLProxySession const *ssl() const;
150 
151   // Implement VConnection interface
152   VIO *do_io_read(Continuation *c, int64_t nbytes = INT64_MAX, MIOBuffer *buf = nullptr) override;
153   VIO *do_io_write(Continuation *c = nullptr, int64_t nbytes = INT64_MAX, IOBufferReader *buf = 0, bool owner = false) override;
154   void do_io_shutdown(ShutdownHowTo_t howto) override;
155   void reenable(VIO *vio) override;
156 
157   ////////////////////
158   // Members
159 
160   IpAllow::ACL acl; ///< IpAllow based method ACL.
161 
162   HttpSessionAccept::Options const *accept_options; ///< connection info // L7R TODO: set in constructor
163 
164   ink_hrtime ssn_start_time    = 0;
165   ink_hrtime ssn_last_txn_time = 0;
166 
167 protected:
168   // Hook dispatching state
169   HttpHookState hook_state;
170 
171   // XXX Consider using a bitwise flags variable for the following flags, so
172   // that we can make the best use of internal alignment padding.
173 
174   // Session specific debug flag.
175   bool debug_on   = false;
176   bool in_destroy = false;
177 
178   int64_t con_id        = 0;
179   Event *schedule_event = nullptr;
180 
181   // This function should be called in all overrides of new_connection() where
182   // the new_vc may be an SSLNetVConnection object.
183   void _handle_if_ssl(NetVConnection *new_vc);
184 
185   NetVConnection *_vc = nullptr; // The netvc associated with the concrete session class
186 
187 private:
188   void handle_api_return(int event);
189   int state_api_callout(int event, void *edata);
190 
191   APIHook const *cur_hook = nullptr;
192   HttpAPIHooks api_hooks;
193 
194   // for DI. An active connection is one that a request has
195   // been successfully parsed (PARSE_DONE) and it remains to
196   // be active until the transaction goes through or the client
197   // aborts.
198   bool m_active = false;
199 
200   std::unique_ptr<SSLProxySession> _ssl;
201   static inline int64_t next_cs_id = 0;
202 };
203 
204 ///////////////////
205 // INLINE
206 
207 inline int64_t
next_connection_id()208 ProxySession::next_connection_id()
209 {
210   return ink_atomic_increment(&next_cs_id, 1);
211 }
212 
213 inline void
set_debug(bool flag)214 ProxySession::set_debug(bool flag)
215 {
216   debug_on = flag;
217 }
218 
219 // Return whether debugging is enabled for this session.
220 inline bool
debug() const221 ProxySession::debug() const
222 {
223   return this->debug_on;
224 }
225 
226 inline bool
is_active() const227 ProxySession::is_active() const
228 {
229   return m_active;
230 }
231 
232 inline bool
is_draining() const233 ProxySession::is_draining() const
234 {
235   return TSSystemState::is_draining();
236 }
237 
238 inline bool
is_client_closed() const239 ProxySession::is_client_closed() const
240 {
241   return get_netvc() == nullptr;
242 }
243 
244 inline TSHttpHookID
get_hookid() const245 ProxySession::get_hookid() const
246 {
247   return hook_state.id();
248 }
249 
250 inline void
hook_add(TSHttpHookID id,INKContInternal * cont)251 ProxySession::hook_add(TSHttpHookID id, INKContInternal *cont)
252 {
253   this->api_hooks.append(id, cont);
254 }
255 
256 inline APIHook *
hook_get(TSHttpHookID id) const257 ProxySession::hook_get(TSHttpHookID id) const
258 {
259   return this->api_hooks.get(id);
260 }
261 
262 inline HttpAPIHooks const *
feature_hooks() const263 ProxySession::feature_hooks() const
264 {
265   return &api_hooks;
266 }
267 
268 inline bool
has_hooks() const269 ProxySession::has_hooks() const
270 {
271   return this->api_hooks.has_hooks() || http_global_hooks->has_hooks();
272 }
273 
274 inline SSLProxySession const *
ssl() const275 ProxySession::ssl() const
276 {
277   return _ssl.get();
278 }
279 
280 inline NetVConnection *
get_netvc() const281 ProxySession::get_netvc() const
282 {
283   return _vc;
284 }
285