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.proxy;
20
21 import java.net.InetSocketAddress;
22 import java.util.HashMap;
23 import java.util.Map;
24 import java.util.concurrent.ConcurrentHashMap;
25
26 import org.eclipse.jetty.spdy.api.GoAwayResultInfo;
27 import org.eclipse.jetty.spdy.api.PingResultInfo;
28 import org.eclipse.jetty.spdy.api.RstInfo;
29 import org.eclipse.jetty.spdy.api.Session;
30 import org.eclipse.jetty.spdy.api.Stream;
31 import org.eclipse.jetty.spdy.api.StreamFrameListener;
32 import org.eclipse.jetty.spdy.api.StreamStatus;
33 import org.eclipse.jetty.spdy.api.SynInfo;
34 import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
35 import org.eclipse.jetty.spdy.server.http.HTTPSPDYHeader;
36 import org.eclipse.jetty.util.Callback;
37 import org.eclipse.jetty.util.Fields;
38 import org.eclipse.jetty.util.log.Log;
39 import org.eclipse.jetty.util.log.Logger;
40
41
42
43
44
45
46
47
48
49
50
51 public class ProxyEngineSelector extends ServerSessionFrameListener.Adapter
52 {
53 protected final Logger LOG = Log.getLogger(getClass());
54 private final Map<String, ProxyServerInfo> proxyInfos = new ConcurrentHashMap<>();
55 private final Map<String, ProxyEngine> proxyEngines = new ConcurrentHashMap<>();
56
57 @Override
58 public final StreamFrameListener onSyn(final Stream clientStream, SynInfo clientSynInfo)
59 {
60 LOG.debug("C -> P {} on {}", clientSynInfo, clientStream);
61
62 final Session clientSession = clientStream.getSession();
63 short clientVersion = clientSession.getVersion();
64 Fields headers = new Fields(clientSynInfo.getHeaders(), false);
65
66 Fields.Field hostHeader = headers.get(HTTPSPDYHeader.HOST.name(clientVersion));
67 if (hostHeader == null)
68 {
69 LOG.debug("No host header found: " + headers);
70 rst(clientStream);
71 return null;
72 }
73
74 String host = hostHeader.value();
75 int colon = host.indexOf(':');
76 if (colon >= 0)
77 host = host.substring(0, colon);
78
79 ProxyServerInfo proxyServerInfo = getProxyServerInfo(host);
80 if (proxyServerInfo == null)
81 {
82 LOG.debug("No matching ProxyServerInfo found for: " + host);
83 rst(clientStream);
84 return null;
85 }
86
87 String protocol = proxyServerInfo.getProtocol();
88 ProxyEngine proxyEngine = proxyEngines.get(protocol);
89 if (proxyEngine == null)
90 {
91 LOG.debug("No matching ProxyEngine found for: " + protocol);
92 rst(clientStream);
93 return null;
94 }
95 LOG.debug("Forwarding request: {} -> {}", clientSynInfo, proxyServerInfo);
96 return proxyEngine.proxy(clientStream, clientSynInfo, proxyServerInfo);
97 }
98
99 @Override
100 public void onPing(Session clientSession, PingResultInfo pingResultInfo)
101 {
102
103
104 }
105
106 @Override
107 public void onGoAway(Session session, GoAwayResultInfo goAwayResultInfo)
108 {
109
110 }
111
112 public Map<String, ProxyEngine> getProxyEngines()
113 {
114 return new HashMap<>(proxyEngines);
115 }
116
117 public void setProxyEngines(Map<String, ProxyEngine> proxyEngines)
118 {
119 this.proxyEngines.clear();
120 this.proxyEngines.putAll(proxyEngines);
121 }
122
123 public ProxyEngine getProxyEngine(String protocol)
124 {
125 return proxyEngines.get(protocol);
126 }
127
128 public void putProxyEngine(String protocol, ProxyEngine proxyEngine)
129 {
130 proxyEngines.put(protocol, proxyEngine);
131 }
132
133 public Map<String, ProxyServerInfo> getProxyServerInfos()
134 {
135 return new HashMap<>(proxyInfos);
136 }
137
138 protected ProxyServerInfo getProxyServerInfo(String host)
139 {
140 return proxyInfos.get(host);
141 }
142
143 public void setProxyServerInfos(Map<String, ProxyServerInfo> proxyServerInfos)
144 {
145 this.proxyInfos.clear();
146 this.proxyInfos.putAll(proxyServerInfos);
147 }
148
149 public void putProxyServerInfo(String host, ProxyServerInfo proxyServerInfo)
150 {
151 proxyInfos.put(host, proxyServerInfo);
152 }
153
154 private void rst(Stream stream)
155 {
156 RstInfo rstInfo = new RstInfo(stream.getId(), StreamStatus.REFUSED_STREAM);
157 stream.getSession().rst(rstInfo, new Callback.Adapter());
158 }
159
160 public static class ProxyServerInfo
161 {
162 private final String protocol;
163 private final String host;
164 private final InetSocketAddress address;
165
166 public ProxyServerInfo(String protocol, String host, int port)
167 {
168 this.protocol = protocol;
169 this.host = host;
170 this.address = new InetSocketAddress(host, port);
171 }
172
173 public String getProtocol()
174 {
175 return protocol;
176 }
177
178 public String getHost()
179 {
180 return host;
181 }
182
183 public InetSocketAddress getAddress()
184 {
185 return address;
186 }
187
188 @Override
189 public String toString()
190 {
191 return "ProxyServerInfo{" +
192 "protocol='" + protocol + '\'' +
193 ", host='" + host + '\'' +
194 ", address=" + address +
195 '}';
196 }
197 }
198 }