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