1 /*
2 * Copyright 2014 The Netty Project
3 *
4 * The Netty Project licenses this file to you under the Apache License,
5 * version 2.0 (the "License"); you may not use this file except in compliance
6 * with the License. You may obtain a copy of the License at:
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
14 * under the License.
15 */
16 package io.netty5.handler.ssl;
17
18 import io.netty.internal.tcnative.SSLContext;
19
20 import java.util.concurrent.locks.Lock;
21
22 /**
23 * Stats exposed by an OpenSSL session context.
24 *
25 * @see <a href="https://www.openssl.org/docs/manmaster/man3/SSL_CTX_sess_number.html">SSL_CTX_sess_number</a>
26 */
27 public final class OpenSslSessionStats {
28
29 private final ReferenceCountedOpenSslContext context;
30
31 // IMPORTANT: We take the OpenSslContext and not just the long (which points the native instance) to prevent
32 // the GC to collect OpenSslContext as this would also free the pointer and so could result in a
33 // segfault when the user calls any of the methods here that try to pass the pointer down to the native
34 // level.
35 OpenSslSessionStats(ReferenceCountedOpenSslContext context) {
36 this.context = context;
37 }
38
39 /**
40 * Returns the current number of sessions in the internal session cache.
41 */
42 public long number() {
43 Lock readerLock = context.ctxLock.readLock();
44 readerLock.lock();
45 try {
46 return SSLContext.sessionNumber(context.ctx);
47 } finally {
48 readerLock.unlock();
49 }
50 }
51
52 /**
53 * Returns the number of started SSL/TLS handshakes in client mode.
54 */
55 public long connect() {
56 Lock readerLock = context.ctxLock.readLock();
57 readerLock.lock();
58 try {
59 return SSLContext.sessionConnect(context.ctx);
60 } finally {
61 readerLock.unlock();
62 }
63 }
64
65 /**
66 * Returns the number of successfully established SSL/TLS sessions in client mode.
67 */
68 public long connectGood() {
69 Lock readerLock = context.ctxLock.readLock();
70 readerLock.lock();
71 try {
72 return SSLContext.sessionConnectGood(context.ctx);
73 } finally {
74 readerLock.unlock();
75 }
76 }
77
78 /**
79 * Returns the number of start renegotiations in client mode.
80 */
81 public long connectRenegotiate() {
82 Lock readerLock = context.ctxLock.readLock();
83 readerLock.lock();
84 try {
85 return SSLContext.sessionConnectRenegotiate(context.ctx);
86 } finally {
87 readerLock.unlock();
88 }
89 }
90
91 /**
92 * Returns the number of started SSL/TLS handshakes in server mode.
93 */
94 public long accept() {
95 Lock readerLock = context.ctxLock.readLock();
96 readerLock.lock();
97 try {
98 return SSLContext.sessionAccept(context.ctx);
99 } finally {
100 readerLock.unlock();
101 }
102 }
103
104 /**
105 * Returns the number of successfully established SSL/TLS sessions in server mode.
106 */
107 public long acceptGood() {
108 Lock readerLock = context.ctxLock.readLock();
109 readerLock.lock();
110 try {
111 return SSLContext.sessionAcceptGood(context.ctx);
112 } finally {
113 readerLock.unlock();
114 }
115 }
116
117 /**
118 * Returns the number of start renegotiations in server mode.
119 */
120 public long acceptRenegotiate() {
121 Lock readerLock = context.ctxLock.readLock();
122 readerLock.lock();
123 try {
124 return SSLContext.sessionAcceptRenegotiate(context.ctx);
125 } finally {
126 readerLock.unlock();
127 }
128 }
129
130 /**
131 * Returns the number of successfully reused sessions. In client mode, a session set with {@code SSL_set_session}
132 * successfully reused is counted as a hit. In server mode, a session successfully retrieved from internal or
133 * external cache is counted as a hit.
134 */
135 public long hits() {
136 Lock readerLock = context.ctxLock.readLock();
137 readerLock.lock();
138 try {
139 return SSLContext.sessionHits(context.ctx);
140 } finally {
141 readerLock.unlock();
142 }
143 }
144
145 /**
146 * Returns the number of successfully retrieved sessions from the external session cache in server mode.
147 */
148 public long cbHits() {
149 Lock readerLock = context.ctxLock.readLock();
150 readerLock.lock();
151 try {
152 return SSLContext.sessionCbHits(context.ctx);
153 } finally {
154 readerLock.unlock();
155 }
156 }
157
158 /**
159 * Returns the number of sessions proposed by clients that were not found in the internal session cache
160 * in server mode.
161 */
162 public long misses() {
163 Lock readerLock = context.ctxLock.readLock();
164 readerLock.lock();
165 try {
166 return SSLContext.sessionMisses(context.ctx);
167 } finally {
168 readerLock.unlock();
169 }
170 }
171
172 /**
173 * Returns the number of sessions proposed by clients and either found in the internal or external session cache
174 * in server mode, but that were invalid due to timeout. These sessions are not included in the {@link #hits()}
175 * count.
176 */
177 public long timeouts() {
178 Lock readerLock = context.ctxLock.readLock();
179 readerLock.lock();
180 try {
181 return SSLContext.sessionTimeouts(context.ctx);
182 } finally {
183 readerLock.unlock();
184 }
185 }
186
187 /**
188 * Returns the number of sessions that were removed because the maximum session cache size was exceeded.
189 */
190 public long cacheFull() {
191 Lock readerLock = context.ctxLock.readLock();
192 readerLock.lock();
193 try {
194 return SSLContext.sessionCacheFull(context.ctx);
195 } finally {
196 readerLock.unlock();
197 }
198 }
199
200 /**
201 * Returns the number of times a client presented a ticket that did not match any key in the list.
202 */
203 public long ticketKeyFail() {
204 Lock readerLock = context.ctxLock.readLock();
205 readerLock.lock();
206 try {
207 return SSLContext.sessionTicketKeyFail(context.ctx);
208 } finally {
209 readerLock.unlock();
210 }
211 }
212
213 /**
214 * Returns the number of times a client did not present a ticket and we issued a new one
215 */
216 public long ticketKeyNew() {
217 Lock readerLock = context.ctxLock.readLock();
218 readerLock.lock();
219 try {
220 return SSLContext.sessionTicketKeyNew(context.ctx);
221 } finally {
222 readerLock.unlock();
223 }
224 }
225
226 /**
227 * Returns the number of times a client presented a ticket derived from an older key,
228 * and we upgraded to the primary key.
229 */
230 public long ticketKeyRenew() {
231 Lock readerLock = context.ctxLock.readLock();
232 readerLock.lock();
233 try {
234 return SSLContext.sessionTicketKeyRenew(context.ctx);
235 } finally {
236 readerLock.unlock();
237 }
238 }
239
240 /**
241 * Returns the number of times a client presented a ticket derived from the primary key.
242 */
243 public long ticketKeyResume() {
244 Lock readerLock = context.ctxLock.readLock();
245 readerLock.lock();
246 try {
247 return SSLContext.sessionTicketKeyResume(context.ctx);
248 } finally {
249 readerLock.unlock();
250 }
251 }
252 }