1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.server;
20
21 import java.io.IOException;
22 import java.net.InetSocketAddress;
23 import java.nio.ByteBuffer;
24 import java.nio.channels.ReadPendingException;
25 import java.nio.channels.WritePendingException;
26 import java.util.Iterator;
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.util.BufferUtil;
32 import org.eclipse.jetty.util.Callback;
33 import org.eclipse.jetty.util.log.Log;
34 import org.eclipse.jetty.util.log.Logger;
35
36
37
38
39
40
41
42
43
44
45 public class ProxyConnectionFactory extends AbstractConnectionFactory
46 {
47 private static final Logger LOG = Log.getLogger(ProxyConnectionFactory.class);
48 private final String _next;
49
50
51
52
53
54 public ProxyConnectionFactory()
55 {
56 super("proxy");
57 _next=null;
58 }
59
60 public ProxyConnectionFactory(String nextProtocol)
61 {
62 super("proxy");
63 _next=nextProtocol;
64 }
65
66 @Override
67 public Connection newConnection(Connector connector, EndPoint endp)
68 {
69 String next=_next;
70 if (next==null)
71 {
72 for (Iterator<String> i = connector.getProtocols().iterator();i.hasNext();)
73 {
74 String p=i.next();
75 if (getProtocol().equalsIgnoreCase(p))
76 {
77 next=i.next();
78 break;
79 }
80 }
81 }
82
83 return new ProxyConnection(endp,connector,next);
84 }
85
86 public static class ProxyConnection extends AbstractConnection
87 {
88
89
90
91
92 private final int[] __size = {29,23,21,13,5,3,1};
93 private final Connector _connector;
94 private final String _next;
95 private final StringBuilder _builder=new StringBuilder();
96 private final String[] _field=new String[6];
97 private int _fields;
98 private int _length;
99
100 protected ProxyConnection(EndPoint endp, Connector connector, String next)
101 {
102 super(endp,connector.getExecutor());
103 _connector=connector;
104 _next=next;
105 }
106
107 @Override
108 public void onOpen()
109 {
110 super.onOpen();
111 fillInterested();
112 }
113
114 @Override
115 public void onFillable()
116 {
117 try
118 {
119 ByteBuffer buffer=null;
120 loop: while(true)
121 {
122
123 int size=Math.max(1,__size[_fields]-_builder.length());
124 if (buffer==null || buffer.capacity()!=size)
125 buffer=BufferUtil.allocate(size);
126 else
127 BufferUtil.clear(buffer);
128
129
130 int fill=getEndPoint().fill(buffer);
131 if (fill<0)
132 {
133 getEndPoint().shutdownOutput();
134 return;
135 }
136 if (fill==0)
137 {
138 fillInterested();
139 return;
140 }
141
142 _length+=fill;
143 if (_length>=108)
144 {
145 LOG.warn("PROXY line too long {} for {}",_length,getEndPoint());
146 close();
147 return;
148 }
149
150
151 while (buffer.hasRemaining())
152 {
153 byte b = buffer.get();
154 if (_fields<6)
155 {
156 if (b==' ' || b=='\r' && _fields==5)
157 {
158 _field[_fields++]=_builder.toString();
159 _builder.setLength(0);
160 }
161 else if (b<' ')
162 {
163 LOG.warn("Bad character {} for {}",b&0xFF,getEndPoint());
164 close();
165 return;
166 }
167 else
168 {
169 _builder.append((char)b);
170 }
171 }
172 else
173 {
174 if (b=='\n')
175 break loop;
176
177 LOG.warn("Bad CRLF for {}",getEndPoint());
178 close();
179 return;
180 }
181 }
182 }
183
184
185 if (!"PROXY".equals(_field[0]))
186 {
187 LOG.warn("Not PROXY protocol for {}",getEndPoint());
188 close();
189 return;
190 }
191
192
193 InetSocketAddress remote=new InetSocketAddress(_field[2],Integer.parseInt(_field[4]));
194 InetSocketAddress local =new InetSocketAddress(_field[3],Integer.parseInt(_field[5]));
195
196
197 ConnectionFactory connectionFactory = _connector.getConnectionFactory(_next);
198 if (connectionFactory == null)
199 {
200 LOG.info("Next protocol '{}' for {}",_next,getEndPoint());
201 close();
202 return;
203 }
204
205 EndPoint endPoint = new ProxyEndPoint(getEndPoint(),remote,local);
206 Connection newConnection = connectionFactory.newConnection(_connector, endPoint);
207 endPoint.upgrade(newConnection);
208 }
209 catch (Throwable x)
210 {
211 LOG.warn("PROXY error for "+getEndPoint(),x);
212 close();
213 }
214 }
215 }
216
217 public static class ProxyEndPoint implements EndPoint
218 {
219 private final EndPoint _endp;
220 private final InetSocketAddress _remote;
221 private final InetSocketAddress _local;
222
223 public ProxyEndPoint(EndPoint endp, InetSocketAddress remote, InetSocketAddress local)
224 {
225 _endp=endp;
226 _remote=remote;
227 _local=local;
228 }
229
230 @Override
231 public boolean isOptimizedForDirectBuffers()
232 {
233 return _endp.isOptimizedForDirectBuffers();
234 }
235
236 public InetSocketAddress getLocalAddress()
237 {
238 return _local;
239 }
240
241 public InetSocketAddress getRemoteAddress()
242 {
243 return _remote;
244 }
245
246 public boolean isOpen()
247 {
248 return _endp.isOpen();
249 }
250
251 public long getCreatedTimeStamp()
252 {
253 return _endp.getCreatedTimeStamp();
254 }
255
256 public void shutdownOutput()
257 {
258 _endp.shutdownOutput();
259 }
260
261 public boolean isOutputShutdown()
262 {
263 return _endp.isOutputShutdown();
264 }
265
266 public boolean isInputShutdown()
267 {
268 return _endp.isInputShutdown();
269 }
270
271 public void close()
272 {
273 _endp.close();
274 }
275
276 public int fill(ByteBuffer buffer) throws IOException
277 {
278 return _endp.fill(buffer);
279 }
280
281 public boolean flush(ByteBuffer... buffer) throws IOException
282 {
283 return _endp.flush(buffer);
284 }
285
286 public Object getTransport()
287 {
288 return _endp.getTransport();
289 }
290
291 public long getIdleTimeout()
292 {
293 return _endp.getIdleTimeout();
294 }
295
296 public void setIdleTimeout(long idleTimeout)
297 {
298 _endp.setIdleTimeout(idleTimeout);
299 }
300
301 public void fillInterested(Callback callback) throws ReadPendingException
302 {
303 _endp.fillInterested(callback);
304 }
305
306 @Override
307 public boolean isFillInterested()
308 {
309 return _endp.isFillInterested();
310 }
311
312 public void write(Callback callback, ByteBuffer... buffers) throws WritePendingException
313 {
314 _endp.write(callback,buffers);
315 }
316
317 public Connection getConnection()
318 {
319 return _endp.getConnection();
320 }
321
322 public void setConnection(Connection connection)
323 {
324 _endp.setConnection(connection);
325 }
326
327 public void onOpen()
328 {
329 _endp.onOpen();
330 }
331
332 public void onClose()
333 {
334 _endp.onClose();
335 }
336
337 @Override
338 public void upgrade(Connection newConnection)
339 {
340 _endp.upgrade(newConnection);
341 }
342 }
343 }