1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.ssl;
17
18 import io.netty.internal.tcnative.SSL;
19 import io.netty.util.AsciiString;
20
21 import java.util.HashMap;
22 import java.util.Map;
23
24
25
26
27 final class OpenSslClientSessionCache extends OpenSslSessionCache {
28
29
30 private final Map<HostPort, NativeSslSession> sessions = new HashMap<HostPort, NativeSslSession>();
31
32 OpenSslClientSessionCache(OpenSslEngineMap engineMap) {
33 super(engineMap);
34 }
35
36 @Override
37 protected boolean sessionCreated(NativeSslSession session) {
38 assert Thread.holdsLock(this);
39 HostPort hostPort = keyFor(session.getPeerHost(), session.getPeerPort());
40 if (hostPort == null || sessions.containsKey(hostPort)) {
41 return false;
42 }
43 sessions.put(hostPort, session);
44 return true;
45 }
46
47 @Override
48 protected void sessionRemoved(NativeSslSession session) {
49 assert Thread.holdsLock(this);
50 HostPort hostPort = keyFor(session.getPeerHost(), session.getPeerPort());
51 if (hostPort == null) {
52 return;
53 }
54 sessions.remove(hostPort);
55 }
56
57 @Override
58 boolean setSession(long ssl, OpenSslSession session, String host, int port) {
59 HostPort hostPort = keyFor(host, port);
60 if (hostPort == null) {
61 return false;
62 }
63 final NativeSslSession nativeSslSession;
64 final boolean reused;
65 boolean singleUsed = false;
66 synchronized (this) {
67 nativeSslSession = sessions.get(hostPort);
68 if (nativeSslSession == null) {
69 return false;
70 }
71 if (!nativeSslSession.isValid()) {
72 removeSessionWithId(nativeSslSession.sessionId());
73 return false;
74 }
75
76
77 reused = SSL.setSession(ssl, nativeSslSession.session());
78 if (reused) {
79 singleUsed = nativeSslSession.shouldBeSingleUse();
80 }
81 }
82
83 if (reused) {
84 if (singleUsed) {
85
86 nativeSslSession.invalidate();
87 session.invalidate();
88 }
89 nativeSslSession.setLastAccessedTime(System.currentTimeMillis());
90 session.setSessionDetails(nativeSslSession.getCreationTime(), nativeSslSession.getLastAccessedTime(),
91 nativeSslSession.sessionId(), nativeSslSession.keyValueStorage);
92 }
93 return reused;
94 }
95
96 private static HostPort keyFor(String host, int port) {
97 if (host == null && port < 1) {
98 return null;
99 }
100 return new HostPort(host, port);
101 }
102
103 @Override
104 synchronized void clear() {
105 super.clear();
106 sessions.clear();
107 }
108
109
110
111
112 private static final class HostPort {
113 private final int hash;
114 private final String host;
115 private final int port;
116
117 HostPort(String host, int port) {
118 this.host = host;
119 this.port = port;
120
121 this.hash = 31 * AsciiString.hashCode(host) + port;
122 }
123
124 @Override
125 public int hashCode() {
126 return hash;
127 }
128
129 @Override
130 public boolean equals(Object obj) {
131 if (!(obj instanceof HostPort)) {
132 return false;
133 }
134 HostPort other = (HostPort) obj;
135 return port == other.port && host.equalsIgnoreCase(other.host);
136 }
137
138 @Override
139 public String toString() {
140 return "HostPort{" +
141 "host='" + host + '\'' +
142 ", port=" + port +
143 '}';
144 }
145 }
146 }