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.util.List;
23 import java.util.Map;
24
25 import javax.net.ssl.SSLEngine;
26
27 import org.eclipse.jetty.io.AbstractConnection;
28 import org.eclipse.jetty.io.ClientConnectionFactory;
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.npn.NextProtoNego;
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 NPNClientConnection extends AbstractConnection implements NextProtoNego.ClientProvider
38 {
39 private final Logger LOG = Log.getLogger(getClass());
40 private final SPDYClient client;
41 private final ClientConnectionFactory connectionFactory;
42 private final SSLEngine engine;
43 private final Map<String, Object> context;
44 private volatile boolean completed;
45
46 public NPNClientConnection(EndPoint endPoint, SPDYClient client, ClientConnectionFactory connectionFactory, SSLEngine sslEngine, Map<String, Object> context)
47 {
48 super(endPoint, client.getFactory().getExecutor());
49 this.client = client;
50 this.connectionFactory = connectionFactory;
51 this.engine = sslEngine;
52 this.context = context;
53 NextProtoNego.put(engine, this);
54 }
55
56 @Override
57 public void onOpen()
58 {
59 super.onOpen();
60 try
61 {
62 getEndPoint().flush(BufferUtil.EMPTY_BUFFER);
63 if (completed)
64 replaceConnection();
65 else
66 fillInterested();
67 }
68 catch(IOException e)
69 {
70 throw new RuntimeIOException(e);
71 }
72 }
73
74 @Override
75 public void onFillable()
76 {
77 while (true)
78 {
79 int filled = fill();
80 if (filled == 0 && !completed)
81 fillInterested();
82 if (filled <= 0 || completed)
83 break;
84 }
85 if (completed)
86 replaceConnection();
87 }
88
89 private int fill()
90 {
91 try
92 {
93 return getEndPoint().fill(BufferUtil.EMPTY_BUFFER);
94 }
95 catch (IOException x)
96 {
97 LOG.debug(x);
98 NextProtoNego.remove(engine);
99 close();
100 return -1;
101 }
102 }
103
104 @Override
105 public boolean supports()
106 {
107 return true;
108 }
109
110 @Override
111 public void unsupported()
112 {
113 NextProtoNego.remove(engine);
114 completed = true;
115 }
116
117 @Override
118 public String selectProtocol(List<String> protocols)
119 {
120 NextProtoNego.remove(engine);
121 completed = true;
122 return client.selectProtocol(protocols);
123 }
124
125 private void replaceConnection()
126 {
127 EndPoint endPoint = getEndPoint();
128 try
129 {
130 Connection oldConnection = endPoint.getConnection();
131 Connection newConnection = connectionFactory.newConnection(endPoint, context);
132 ClientConnectionFactory.Helper.replaceConnection(oldConnection, newConnection);
133 }
134 catch (Throwable x)
135 {
136 LOG.debug(x);
137 close();
138 }
139 }
140 }