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