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