1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.proxy.filter;
21
22 import org.apache.mina.core.buffer.IoBuffer;
23 import org.apache.mina.core.filterchain.IoFilter;
24 import org.apache.mina.core.filterchain.IoFilterAdapter;
25 import org.apache.mina.core.filterchain.IoFilterChain;
26 import org.apache.mina.core.session.IdleStatus;
27 import org.apache.mina.core.session.IoSession;
28 import org.apache.mina.core.write.WriteRequest;
29 import org.apache.mina.proxy.ProxyAuthException;
30 import org.apache.mina.proxy.ProxyConnector;
31 import org.apache.mina.proxy.ProxyLogicHandler;
32 import org.apache.mina.proxy.event.IoSessionEvent;
33 import org.apache.mina.proxy.event.IoSessionEventQueue;
34 import org.apache.mina.proxy.event.IoSessionEventType;
35 import org.apache.mina.proxy.handlers.ProxyRequest;
36 import org.apache.mina.proxy.handlers.http.HttpSmartProxyHandler;
37 import org.apache.mina.proxy.handlers.socks.Socks4LogicHandler;
38 import org.apache.mina.proxy.handlers.socks.Socks5LogicHandler;
39 import org.apache.mina.proxy.handlers.socks.SocksProxyConstants;
40 import org.apache.mina.proxy.handlers.socks.SocksProxyRequest;
41 import org.apache.mina.proxy.session.ProxyIoSession;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45
46
47
48
49
50
51
52
53
54
55
56
57 public class ProxyFilter extends IoFilterAdapter {
58 private final static Logger logger = LoggerFactory
59 .getLogger(ProxyFilter.class);
60
61
62
63
64 public ProxyFilter() {
65 }
66
67
68
69
70
71
72
73
74
75
76
77 @Override
78 public void onPreAdd(final IoFilterChain chain, final String name,
79 final NextFilter nextFilter) {
80 if (chain.contains(ProxyFilter.class)) {
81 throw new IllegalStateException(
82 "A filter chain cannot contain more than one ProxyFilter.");
83 }
84 }
85
86
87
88
89
90
91
92
93
94 @Override
95 public void onPreRemove(final IoFilterChain chain, final String name,
96 final NextFilter nextFilter) {
97 IoSession session = chain.getSession();
98 session.removeAttribute(ProxyIoSession.PROXY_SESSION);
99 }
100
101
102
103
104
105
106
107
108
109
110 @Override
111 public void exceptionCaught(NextFilter nextFilter, IoSession session,
112 Throwable cause) throws Exception {
113 ProxyIoSession proxyIoSession = (ProxyIoSession) session
114 .getAttribute(ProxyIoSession.PROXY_SESSION);
115 proxyIoSession.setAuthenticationFailed(true);
116 super.exceptionCaught(nextFilter, session, cause);
117 }
118
119
120
121
122
123
124
125 private ProxyLogicHandler getProxyHandler(final IoSession session) {
126 ProxyLogicHandler handler = ((ProxyIoSession) session
127 .getAttribute(ProxyIoSession.PROXY_SESSION)).getHandler();
128
129 if (handler == null) {
130 throw new IllegalStateException();
131 }
132
133
134 if (handler.getProxyIoSession().getProxyFilter() != this) {
135 throw new IllegalArgumentException("Not managed by this filter.");
136 }
137
138 return handler;
139 }
140
141
142
143
144
145
146
147
148
149 @Override
150 public void messageReceived(final NextFilter nextFilter,
151 final IoSession session, final Object message)
152 throws ProxyAuthException {
153 ProxyLogicHandler handler = getProxyHandler(session);
154
155 synchronized (handler) {
156 IoBuffer buf = (IoBuffer) message;
157
158 if (handler.isHandshakeComplete()) {
159
160 nextFilter.messageReceived(session, buf);
161
162 } else {
163 logger.debug(" Data Read: {} ({})", handler, buf);
164
165
166
167 while (buf.hasRemaining() && !handler.isHandshakeComplete()) {
168 logger.debug(" Pre-handshake - passing to handler");
169
170 int pos = buf.position();
171 handler.messageReceived(nextFilter, buf);
172
173
174 if (buf.position() == pos || session.isClosing()) {
175 return;
176 }
177 }
178
179
180 if (buf.hasRemaining()) {
181 logger.debug(" Passing remaining data to next filter");
182
183 nextFilter.messageReceived(session, buf);
184 }
185 }
186 }
187 }
188
189
190
191
192
193
194
195
196
197 @Override
198 public void filterWrite(final NextFilter nextFilter,
199 final IoSession session, final WriteRequest writeRequest) {
200 writeData(nextFilter, session, writeRequest, false);
201 }
202
203
204
205
206
207
208
209
210
211
212 public void writeData(final NextFilter nextFilter, final IoSession session,
213 final WriteRequest writeRequest, final boolean isHandshakeData) {
214 ProxyLogicHandler handler = getProxyHandler(session);
215
216 synchronized (handler) {
217 if (handler.isHandshakeComplete()) {
218
219 nextFilter.filterWrite(session, writeRequest);
220 } else if (isHandshakeData) {
221 logger.debug(" handshake data: {}", writeRequest.getMessage());
222
223
224 nextFilter.filterWrite(session, writeRequest);
225 } else {
226
227 if (!session.isConnected()) {
228
229 logger.debug(" Write request on closed session. Request ignored.");
230 } else {
231
232 logger.debug(" Handshaking is not complete yet. Buffering write request.");
233 handler.enqueueWriteRequest(nextFilter, writeRequest);
234 }
235 }
236 }
237 }
238
239
240
241
242
243
244
245
246
247 @Override
248 public void messageSent(final NextFilter nextFilter,
249 final IoSession session, final WriteRequest writeRequest)
250 throws Exception {
251 if (writeRequest.getMessage() != null
252 && writeRequest.getMessage() instanceof ProxyHandshakeIoBuffer) {
253
254 return;
255 }
256
257 nextFilter.messageSent(session, writeRequest);
258 }
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274 @Override
275 public void sessionCreated(NextFilter nextFilter, IoSession session)
276 throws Exception {
277 logger.debug("Session created: " + session);
278 ProxyIoSession proxyIoSession = (ProxyIoSession) session
279 .getAttribute(ProxyIoSession.PROXY_SESSION);
280 logger.debug(" get proxyIoSession: " + proxyIoSession);
281 proxyIoSession.setProxyFilter(this);
282
283
284 ProxyLogicHandler handler = proxyIoSession.getHandler();
285
286
287
288 if (handler == null) {
289 ProxyRequest request = proxyIoSession.getRequest();
290
291 if (request instanceof SocksProxyRequest) {
292 SocksProxyRequest req = (SocksProxyRequest) request;
293 if (req.getProtocolVersion() == SocksProxyConstants.SOCKS_VERSION_4) {
294 handler = new Socks4LogicHandler(proxyIoSession);
295 } else {
296 handler = new Socks5LogicHandler(proxyIoSession);
297 }
298 } else {
299 handler = new HttpSmartProxyHandler(proxyIoSession);
300 }
301
302 proxyIoSession.setHandler(handler);
303 handler.doHandshake(nextFilter);
304 }
305
306 proxyIoSession.getEventQueue().enqueueEventIfNecessary(
307 new IoSessionEvent(nextFilter, session,
308 IoSessionEventType.CREATED));
309 }
310
311
312
313
314
315
316
317
318
319 @Override
320 public void sessionOpened(NextFilter nextFilter, IoSession session)
321 throws Exception {
322 ProxyIoSession proxyIoSession = (ProxyIoSession) session
323 .getAttribute(ProxyIoSession.PROXY_SESSION);
324 proxyIoSession.getEventQueue().enqueueEventIfNecessary(
325 new IoSessionEvent(nextFilter, session,
326 IoSessionEventType.OPENED));
327 }
328
329
330
331
332
333
334
335
336
337 @Override
338 public void sessionIdle(NextFilter nextFilter, IoSession session,
339 IdleStatus status) throws Exception {
340 ProxyIoSession proxyIoSession = (ProxyIoSession) session
341 .getAttribute(ProxyIoSession.PROXY_SESSION);
342 proxyIoSession.getEventQueue().enqueueEventIfNecessary(
343 new IoSessionEvent(nextFilter, session, status));
344 }
345
346
347
348
349
350
351
352
353
354 @Override
355 public void sessionClosed(NextFilter nextFilter, IoSession session)
356 throws Exception {
357 ProxyIoSession proxyIoSession = (ProxyIoSession) session
358 .getAttribute(ProxyIoSession.PROXY_SESSION);
359 proxyIoSession.getEventQueue().enqueueEventIfNecessary(
360 new IoSessionEvent(nextFilter, session,
361 IoSessionEventType.CLOSED));
362 }
363 }