1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.spdy.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.npn.NextProtoNego;
30 import org.eclipse.jetty.server.ConnectionFactory;
31 import org.eclipse.jetty.server.Connector;
32 import org.eclipse.jetty.util.BufferUtil;
33 import org.eclipse.jetty.util.log.Log;
34 import org.eclipse.jetty.util.log.Logger;
35
36 public class NextProtoNegoServerConnection extends AbstractConnection implements NextProtoNego.ServerProvider
37 {
38 private final Logger LOG = Log.getLogger(getClass());
39 private final Connector connector;
40 private final SSLEngine engine;
41 private final List<String> protocols;
42 private final String defaultProtocol;
43 private String nextProtocol;
44
45 public NextProtoNegoServerConnection(EndPoint endPoint, SSLEngine engine, Connector connector, List<String>protocols, String defaultProtocol)
46 {
47 super(endPoint, connector.getExecutor());
48 this.connector = connector;
49 this.protocols = protocols;
50 this.defaultProtocol = defaultProtocol;
51 this.engine = engine;
52 NextProtoNego.put(engine, this);
53 }
54
55 @Override
56 public void onOpen()
57 {
58 super.onOpen();
59 fillInterested();
60 }
61
62 @Override
63 public void onFillable()
64 {
65 int filled = fill();
66
67 if (filled == 0)
68 {
69 if (nextProtocol == null)
70 {
71 if (engine.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING)
72 {
73
74
75
76 LOG.debug("{} missing next protocol. SSLEngine: {}", this, engine);
77 close();
78 }
79 else
80 {
81
82
83 fillInterested();
84 }
85 }
86 else
87 {
88 ConnectionFactory connectionFactory = connector.getConnectionFactory(nextProtocol);
89 if (connectionFactory == null)
90 {
91 LOG.debug("{} application selected protocol '{}', but no correspondent {} has been configured",
92 this, nextProtocol, ConnectionFactory.class.getName());
93 close();
94 }
95 else
96 {
97 EndPoint endPoint = getEndPoint();
98 Connection oldConnection = endPoint.getConnection();
99 Connection newConnection = connectionFactory.newConnection(connector, endPoint);
100 LOG.debug("{} switching from {} to {}", this, oldConnection, newConnection);
101 oldConnection.onClose();
102 endPoint.setConnection(newConnection);
103 getEndPoint().getConnection().onOpen();
104 }
105 }
106 }
107 else if (filled < 0)
108 {
109
110 LOG.debug("{} closing on client close", this);
111 close();
112 }
113 else
114 {
115
116 throw new IllegalStateException();
117 }
118 }
119
120 private int fill()
121 {
122 try
123 {
124 return getEndPoint().fill(BufferUtil.EMPTY_BUFFER);
125 }
126 catch (IOException x)
127 {
128 LOG.debug(x);
129 close();
130 return -1;
131 }
132 }
133
134 @Override
135 public void unsupported()
136 {
137 protocolSelected(defaultProtocol);
138 }
139
140 @Override
141 public List<String> protocols()
142 {
143 return protocols;
144 }
145
146 @Override
147 public void protocolSelected(String protocol)
148 {
149 LOG.debug("{} protocol selected {}", this, protocol);
150 nextProtocol = protocol != null ? protocol : defaultProtocol;
151 NextProtoNego.remove(engine);
152 }
153
154 @Override
155 public void close()
156 {
157 NextProtoNego.remove(engine);
158 EndPoint endPoint = getEndPoint();
159 endPoint.shutdownOutput();
160 endPoint.close();
161 }
162 }