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