1 /*
2  *
3  * Copyright 2018 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 #ifndef GRPC_CORE_TSI_SSL_SESSION_CACHE_SSL_SESSION_CACHE_H
20 #define GRPC_CORE_TSI_SSL_SESSION_CACHE_SSL_SESSION_CACHE_H
21 
22 #include <grpc/support/port_platform.h>
23 
24 #include "src/core/tsi/grpc_shadow_boringssl.h"
25 
26 #include <grpc/slice.h>
27 #include <grpc/support/sync.h>
28 
29 extern "C" {
30 #include <openssl/ssl.h>
31 }
32 
33 #include "src/core/lib/avl/avl.h"
34 #include "src/core/lib/gprpp/memory.h"
35 #include "src/core/lib/gprpp/ref_counted.h"
36 #include "src/core/tsi/ssl/session_cache/ssl_session.h"
37 
38 /// Cache for SSL sessions for sessions resumption.
39 ///
40 /// Older sessions may be evicted from the cache using LRU policy if capacity
41 /// limit is hit. All sessions are associated with some key, usually server
42 /// name. Note that servers are required to share session ticket encryption keys
43 /// in order for cache to be effective.
44 ///
45 /// This class is thread safe.
46 
47 namespace tsi {
48 
49 class SslSessionLRUCache : public grpc_core::RefCounted<SslSessionLRUCache> {
50  public:
51   /// Create new LRU cache with the given capacity.
Create(size_t capacity)52   static grpc_core::RefCountedPtr<SslSessionLRUCache> Create(size_t capacity) {
53     return grpc_core::MakeRefCounted<SslSessionLRUCache>(capacity);
54   }
55 
56   // Not copyable nor movable.
57   SslSessionLRUCache(const SslSessionLRUCache&) = delete;
58   SslSessionLRUCache& operator=(const SslSessionLRUCache&) = delete;
59 
60   /// Returns current number of sessions in the cache.
61   size_t Size();
62   /// Add \a session in the cache using \a key. This operation may discard older
63   /// sessions.
64   void Put(const char* key, SslSessionPtr session);
65   /// Returns the session from the cache associated with \a key or null if not
66   /// found.
67   SslSessionPtr Get(const char* key);
68 
69  private:
70   // So New() can call our private ctor.
71   template <typename T, typename... Args>
72   friend T* grpc_core::New(Args&&... args);
73 
74   // So Delete() can call our private dtor.
75   template <typename T>
76   friend void grpc_core::Delete(T*);
77 
78   class Node;
79 
80   explicit SslSessionLRUCache(size_t capacity);
81   ~SslSessionLRUCache();
82 
83   Node* FindLocked(const grpc_slice& key);
84   void Remove(Node* node);
85   void PushFront(Node* node);
86   void AssertInvariants();
87 
88   gpr_mu lock_;
89   size_t capacity_;
90 
91   Node* use_order_list_head_ = nullptr;
92   Node* use_order_list_tail_ = nullptr;
93   size_t use_order_list_size_ = 0;
94   grpc_avl entry_by_key_;
95 };
96 
97 }  // namespace tsi
98 
99 #endif /* GRPC_CORE_TSI_SSL_SESSION_CACHE_SSL_SESSION_CACHE_H */
100