1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.spdy.client;
20
21 import java.io.IOException;
22 import java.nio.channels.SocketChannel;
23 import java.util.List;
24 import java.util.concurrent.Executor;
25
26 import javax.net.ssl.SSLEngine;
27
28 import org.eclipse.jetty.io.AbstractConnection;
29 import org.eclipse.jetty.io.Connection;
30 import org.eclipse.jetty.io.EndPoint;
31 import org.eclipse.jetty.io.RuntimeIOException;
32 import org.eclipse.jetty.io.ssl.SslConnection.DecryptedEndPoint;
33 import org.eclipse.jetty.npn.NextProtoNego;
34 import org.eclipse.jetty.util.BufferUtil;
35 import org.eclipse.jetty.util.log.Log;
36 import org.eclipse.jetty.util.log.Logger;
37
38 public class NextProtoNegoClientConnection extends AbstractConnection implements NextProtoNego.ClientProvider
39 {
40 private final Logger LOG = Log.getLogger(getClass());
41 private final SocketChannel channel;
42 private final Object attachment;
43 private final SPDYClient client;
44 private final SSLEngine engine;
45 private volatile boolean completed;
46
47 public NextProtoNegoClientConnection(SocketChannel channel, DecryptedEndPoint endPoint, Object attachment, Executor executor, SPDYClient client)
48 {
49 super(endPoint, executor);
50 this.channel = channel;
51 this.attachment = attachment;
52 this.client = client;
53 this.engine = endPoint.getSslConnection().getSSLEngine();
54 NextProtoNego.put(engine, this);
55 }
56
57 @Override
58 public void onOpen()
59 {
60 super.onOpen();
61 try
62 {
63 getEndPoint().flush(BufferUtil.EMPTY_BUFFER);
64 if (completed)
65 replaceConnection();
66 else
67 fillInterested();
68 }
69 catch(IOException e)
70 {
71 throw new RuntimeIOException(e);
72 }
73 }
74
75 @Override
76 public void onFillable()
77 {
78 while (true)
79 {
80 int filled = fill();
81 if (filled == 0 && !completed)
82 fillInterested();
83 if (filled <= 0 || completed)
84 break;
85 }
86 if (completed)
87 replaceConnection();
88 }
89
90 private int fill()
91 {
92 try
93 {
94 return getEndPoint().fill(BufferUtil.EMPTY_BUFFER);
95 }
96 catch (IOException x)
97 {
98 LOG.debug(x);
99 NextProtoNego.remove(engine);
100 getEndPoint().close();
101 return -1;
102 }
103 }
104
105 @Override
106 public boolean supports()
107 {
108 return true;
109 }
110
111 @Override
112 public void unsupported()
113 {
114 NextProtoNego.remove(engine);
115 completed = true;
116 }
117
118 @Override
119 public String selectProtocol(List<String> protocols)
120 {
121 NextProtoNego.remove(engine);
122 completed = true;
123 String protocol = client.selectProtocol(protocols);
124 return protocol == null ? null : protocol;
125 }
126
127 private void replaceConnection()
128 {
129 EndPoint endPoint = getEndPoint();
130 Connection connection = client.getConnectionFactory().newConnection(channel, endPoint, attachment);
131 endPoint.getConnection().onClose();
132 endPoint.setConnection(connection);
133 connection.onOpen();
134 }
135 }