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    Http1ServerSession.h
27 
28    Description:
29 
30 
31  ****************************************************************************/
32 
33 #pragma once
34 
35 #include "P_Net.h"
36 
37 #include "HttpConnectionCount.h"
38 #include "HttpProxyAPIEnums.h"
39 
40 class HttpSM;
41 class MIOBuffer;
42 class IOBufferReader;
43 
44 enum HSS_State {
45   HSS_INIT,
46   HSS_ACTIVE,
47   HSS_KA_CLIENT_SLAVE,
48   HSS_KA_SHARED,
49 };
50 
51 enum {
52   HTTP_SS_MAGIC_ALIVE = 0x0123FEED,
53   HTTP_SS_MAGIC_DEAD  = 0xDEADFEED,
54 };
55 
56 class Http1ServerSession : public VConnection
57 {
58   using self_type  = Http1ServerSession;
59   using super_type = VConnection;
60 
61 public:
Http1ServerSession()62   Http1ServerSession() : super_type(nullptr) {}
63   Http1ServerSession(self_type const &) = delete;
64   self_type &operator=(self_type const &) = delete;
65 
66   ////////////////////
67   // Methods
68   void new_connection(NetVConnection *new_vc);
69   void release();
70   void destroy();
71 
72   // VConnection Methods
73   VIO *do_io_read(Continuation *c, int64_t nbytes = INT64_MAX, MIOBuffer *buf = nullptr) override;
74   VIO *do_io_write(Continuation *c = nullptr, int64_t nbytes = INT64_MAX, IOBufferReader *buf = nullptr,
75                    bool owner = false) override;
76   void do_io_close(int lerrno = -1) override;
77   void do_io_shutdown(ShutdownHowTo_t howto) override;
78 
79   void reenable(VIO *vio) override;
80 
81   void enable_outbound_connection_tracking(OutboundConnTrack::Group *group);
82   IOBufferReader *get_reader();
83   void attach_hostname(const char *hostname);
84   NetVConnection *get_netvc() const;
85   void set_netvc(NetVConnection *new_vc);
86   IpEndpoint const &get_server_ip() const;
87   int populate_protocol(std::string_view *result, int size) const;
88   const char *protocol_contains(std::string_view tag_prefix) const;
89 
90   ////////////////////
91   // Variables
92   CryptoHash hostname_hash;
93 
94   int64_t con_id     = 0;
95   int transact_count = 0;
96   HSS_State state    = HSS_INIT;
97 
98   // Used to determine whether the session is for parent proxy
99   // it is session to origin server
100   // We need to determine whether a closed connection was to
101   // close parent proxy to update the
102   // proxy.process.http.current_parent_proxy_connections
103   bool to_parent_proxy = false;
104 
105   // Used to verify we are recording the server
106   //   transaction stat properly
107   int server_trans_stat = 0;
108 
109   // Sessions become if authentication headers
110   //  are sent over them
111   bool private_session = false;
112 
113   // Copy of the owning SM's server session sharing settings
114   TSServerSessionSharingMatchMask sharing_match = TS_SERVER_SESSION_SHARING_MATCH_MASK_NONE;
115   TSServerSessionSharingPoolType sharing_pool   = TS_SERVER_SESSION_SHARING_POOL_GLOBAL;
116 
117   /// Hash map descriptor class for IP map.
118   struct IPLinkage {
119     self_type *_next = nullptr;
120     self_type *_prev = nullptr;
121 
122     static self_type *&next_ptr(self_type *);
123     static self_type *&prev_ptr(self_type *);
124     static uint32_t hash_of(sockaddr const *key);
125     static sockaddr const *key_of(self_type const *ssn);
126     static bool equal(sockaddr const *lhs, sockaddr const *rhs);
127     // Add a couple overloads for internal convenience.
128     static bool equal(sockaddr const *lhs, Http1ServerSession const *rhs);
129     static bool equal(Http1ServerSession const *lhs, sockaddr const *rhs);
130   } _ip_link;
131 
132   /// Hash map descriptor class for FQDN map.
133   struct FQDNLinkage {
134     self_type *_next = nullptr;
135     self_type *_prev = nullptr;
136 
137     static self_type *&next_ptr(self_type *);
138     static self_type *&prev_ptr(self_type *);
139     static uint64_t hash_of(CryptoHash const &key);
140     static CryptoHash const &key_of(self_type *ssn);
141     static bool equal(CryptoHash const &lhs, CryptoHash const &rhs);
142   } _fqdn_link;
143 
144   // Keep track of connection limiting and a pointer to the
145   // singleton that keeps track of the connection counts.
146   OutboundConnTrack::Group *conn_track_group = nullptr;
147 
148   // The ServerSession owns the following buffer which use
149   //   for parsing the headers.  The server session needs to
150   //   own the buffer so we can go from a keep-alive state
151   //   to being acquired and parsing the header without
152   //   changing the buffer we are doing I/O on.  We can
153   //   not change the buffer for I/O without issuing a
154   //   an asynchronous cancel on NT
155   MIOBuffer *read_buffer = nullptr;
156 
157 private:
158   NetVConnection *server_vc = nullptr;
159   int magic                 = HTTP_SS_MAGIC_DEAD;
160 
161   IOBufferReader *buf_reader = nullptr;
162 };
163 
164 extern ClassAllocator<Http1ServerSession> httpServerSessionAllocator;
165 
166 ////////////////////////////////////////////
167 // INLINE
168 
169 inline void
attach_hostname(const char * hostname)170 Http1ServerSession::attach_hostname(const char *hostname)
171 {
172   if (CRYPTO_HASH_ZERO == hostname_hash) {
173     CryptoContext().hash_immediate(hostname_hash, (unsigned char *)hostname, strlen(hostname));
174   }
175 }
176 
177 inline IOBufferReader *
get_reader()178 Http1ServerSession::get_reader()
179 {
180   return buf_reader;
181 };
182 
183 //
184 // LINKAGE
185 
186 inline Http1ServerSession *&
next_ptr(self_type * ssn)187 Http1ServerSession::IPLinkage::next_ptr(self_type *ssn)
188 {
189   return ssn->_ip_link._next;
190 }
191 
192 inline Http1ServerSession *&
prev_ptr(self_type * ssn)193 Http1ServerSession::IPLinkage::prev_ptr(self_type *ssn)
194 {
195   return ssn->_ip_link._prev;
196 }
197 
198 inline uint32_t
hash_of(sockaddr const * key)199 Http1ServerSession::IPLinkage::hash_of(sockaddr const *key)
200 {
201   return ats_ip_hash(key);
202 }
203 
204 inline sockaddr const *
key_of(self_type const * ssn)205 Http1ServerSession::IPLinkage::key_of(self_type const *ssn)
206 {
207   return &ssn->get_server_ip().sa;
208 }
209 
210 inline bool
equal(sockaddr const * lhs,sockaddr const * rhs)211 Http1ServerSession::IPLinkage::equal(sockaddr const *lhs, sockaddr const *rhs)
212 {
213   return ats_ip_addr_port_eq(lhs, rhs);
214 }
215 
216 inline bool
equal(sockaddr const * lhs,Http1ServerSession const * rhs)217 Http1ServerSession::IPLinkage::equal(sockaddr const *lhs, Http1ServerSession const *rhs)
218 {
219   return ats_ip_addr_port_eq(lhs, key_of(rhs));
220 }
221 
222 inline bool
equal(Http1ServerSession const * lhs,sockaddr const * rhs)223 Http1ServerSession::IPLinkage::equal(Http1ServerSession const *lhs, sockaddr const *rhs)
224 {
225   return ats_ip_addr_port_eq(key_of(lhs), rhs);
226 }
227 
228 inline Http1ServerSession *&
next_ptr(self_type * ssn)229 Http1ServerSession::FQDNLinkage::next_ptr(self_type *ssn)
230 {
231   return ssn->_fqdn_link._next;
232 }
233 
234 inline Http1ServerSession *&
prev_ptr(self_type * ssn)235 Http1ServerSession::FQDNLinkage::prev_ptr(self_type *ssn)
236 {
237   return ssn->_fqdn_link._prev;
238 }
239 
240 inline uint64_t
hash_of(CryptoHash const & key)241 Http1ServerSession::FQDNLinkage::hash_of(CryptoHash const &key)
242 {
243   return key.fold();
244 }
245 
246 inline CryptoHash const &
key_of(self_type * ssn)247 Http1ServerSession::FQDNLinkage::key_of(self_type *ssn)
248 {
249   return ssn->hostname_hash;
250 }
251 
252 inline bool
equal(CryptoHash const & lhs,CryptoHash const & rhs)253 Http1ServerSession::FQDNLinkage::equal(CryptoHash const &lhs, CryptoHash const &rhs)
254 {
255   return lhs == rhs;
256 }
257