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    HttpSessionManager.h
27 
28    Description:
29 
30 
31  ****************************************************************************/
32 
33 #pragma once
34 
35 #include "P_EventSystem.h"
36 #include "PoolableSession.h"
37 #include "tscore/IntrusiveHashMap.h"
38 
39 class ProxyTransaction;
40 class HttpSM;
41 
42 void initialize_thread_for_http_sessions(EThread *thread, int thread_index);
43 
44 enum HSMresult_t {
45   HSM_DONE,
46   HSM_RETRY,
47   HSM_NOT_FOUND,
48 };
49 
50 /** A pool of server sessions.
51 
52     This is a continuation so that it can get callbacks from the server sessions.
53     This is used to track remote closes on the sessions so they can be cleaned up.
54 
55     @internal Cleanup is the real reason we will always need an IP address mapping for the
56     sessions. The I/O callback will have only the NetVC and thence the remote IP address for the
57     closed session and we need to be able find it based on that.
58 */
59 class ServerSessionPool : public Continuation
60 {
61 public:
62   /// Default constructor.
63   /// Constructs an empty pool.
64   ServerSessionPool();
65   /// Handle events from server sessions.
66   int eventHandler(int event, void *data);
67   static bool validate_host_sni(HttpSM *sm, NetVConnection *netvc);
68   static bool validate_sni(HttpSM *sm, NetVConnection *netvc);
69   static bool validate_cert(HttpSM *sm, NetVConnection *netvc);
70   int
count()71   count() const
72   {
73     return m_ip_pool.count();
74   }
75 
76 protected:
77   using IPTable   = IntrusiveHashMap<PoolableSession::IPLinkage>;
78   using FQDNTable = IntrusiveHashMap<PoolableSession::FQDNLinkage>;
79 
80 public:
81   /** Check if a session matches address and host name.
82    */
83   static bool match(PoolableSession *ss, sockaddr const *addr, CryptoHash const &host_hash,
84                     TSServerSessionSharingMatchMask match_style);
85 
86   /** Get a session from the pool.
87 
88       The session is selected based on @a match_style equivalently to @a match. If found the session
89       is removed from the pool.
90 
91       @return A pointer to the session or @c NULL if not matching session was found.
92   */
93   HSMresult_t acquireSession(sockaddr const *addr, CryptoHash const &host_hash, TSServerSessionSharingMatchMask match_style,
94                              HttpSM *sm, PoolableSession *&server_session);
95   /** Release a session to to pool.
96    */
97   void releaseSession(PoolableSession *ss);
98 
99   /// Close all sessions and then clear the table.
100   void purge();
101 
102   // Pools of server sessions.
103   // Note that each server session is stored in both pools.
104   IPTable m_ip_pool;
105   FQDNTable m_fqdn_pool;
106 };
107 
108 class HttpSessionManager
109 {
110 public:
HttpSessionManager()111   HttpSessionManager() {}
~HttpSessionManager()112   ~HttpSessionManager() {}
113   HSMresult_t acquire_session(Continuation *cont, sockaddr const *addr, const char *hostname, ProxyTransaction *ua_txn, HttpSM *sm);
114   HSMresult_t release_session(PoolableSession *to_release);
115   void purge_keepalives();
116   void init();
117   int main_handler(int event, void *data);
118   void
set_pool_type(int pool_type)119   set_pool_type(int pool_type)
120   {
121     m_pool_type = static_cast<TSServerSessionSharingPoolType>(pool_type);
122   }
123   TSServerSessionSharingPoolType
get_pool_type()124   get_pool_type() const
125   {
126     return m_pool_type;
127   }
128 
129 private:
130   /// Global pool, used if not per thread pools.
131   /// @internal We delay creating this because the session manager is created during global statics init.
132   ServerSessionPool *m_g_pool = nullptr;
133   HSMresult_t _acquire_session(sockaddr const *ip, CryptoHash const &hostname_hash, HttpSM *sm,
134                                TSServerSessionSharingMatchMask match_style, TSServerSessionSharingPoolType pool_type);
135   TSServerSessionSharingPoolType m_pool_type = TS_SERVER_SESSION_SHARING_POOL_THREAD;
136 };
137 
138 extern HttpSessionManager httpSessionManager;
139