1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.server;
20
21 import java.io.IOException;
22 import java.util.List;
23
24 import javax.net.ssl.SSLEngine;
25 import javax.net.ssl.SSLEngineResult;
26
27 import org.eclipse.jetty.io.AbstractConnection;
28 import org.eclipse.jetty.io.Connection;
29 import org.eclipse.jetty.io.EndPoint;
30 import org.eclipse.jetty.util.BufferUtil;
31 import org.eclipse.jetty.util.log.Log;
32 import org.eclipse.jetty.util.log.Logger;
33
34 public abstract class NegotiatingServerConnection extends AbstractConnection
35 {
36 private static final Logger LOG = Log.getLogger(NegotiatingServerConnection.class);
37
38 public interface CipherDiscriminator
39 {
40 boolean isAcceptable(String protocol, String tlsProtocol, String tlsCipher);
41 }
42
43 private final Connector connector;
44 private final SSLEngine engine;
45 private final List<String> protocols;
46 private final String defaultProtocol;
47 private String protocol;
48
49 protected NegotiatingServerConnection(Connector connector, EndPoint endPoint, SSLEngine engine, List<String> protocols, String defaultProtocol)
50 {
51 super(endPoint, connector.getExecutor());
52 this.connector = connector;
53 this.protocols = protocols;
54 this.defaultProtocol = defaultProtocol;
55 this.engine = engine;
56 }
57
58 protected List<String> getProtocols()
59 {
60 return protocols;
61 }
62
63 protected String getDefaultProtocol()
64 {
65 return defaultProtocol;
66 }
67
68 protected Connector getConnector()
69 {
70 return connector;
71 }
72
73 protected SSLEngine getSSLEngine()
74 {
75 return engine;
76 }
77
78 protected String getProtocol()
79 {
80 return protocol;
81 }
82
83 protected void setProtocol(String protocol)
84 {
85 this.protocol = protocol;
86 }
87
88 @Override
89 public void onOpen()
90 {
91 super.onOpen();
92 fillInterested();
93 }
94
95 @Override
96 public void onFillable()
97 {
98 int filled = fill();
99
100 if (filled == 0)
101 {
102 if (protocol == null)
103 {
104 if (engine.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING)
105 {
106
107 if (LOG.isDebugEnabled())
108 LOG.debug("{} could not negotiate protocol, SSLEngine: {}", this, engine);
109 close();
110 }
111 else
112 {
113
114
115 fillInterested();
116 }
117 }
118 else
119 {
120 ConnectionFactory connectionFactory = connector.getConnectionFactory(protocol);
121 if (connectionFactory == null)
122 {
123 LOG.info("{} application selected protocol '{}', but no correspondent {} has been configured",
124 this, protocol, ConnectionFactory.class.getName());
125 close();
126 }
127 else
128 {
129 EndPoint endPoint = getEndPoint();
130 Connection newConnection = connectionFactory.newConnection(connector, endPoint);
131 endPoint.upgrade(newConnection);
132 }
133 }
134 }
135 else if (filled < 0)
136 {
137
138 if (LOG.isDebugEnabled())
139 LOG.debug("{} detected close on client side", this);
140 close();
141 }
142 else
143 {
144
145 throw new IllegalStateException();
146 }
147 }
148
149 private int fill()
150 {
151 try
152 {
153 return getEndPoint().fill(BufferUtil.EMPTY_BUFFER);
154 }
155 catch (IOException x)
156 {
157 LOG.debug(x);
158 close();
159 return -1;
160 }
161 }
162
163 @Override
164 public void close()
165 {
166
167 getEndPoint().shutdownOutput();
168 super.close();
169 }
170 }