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