1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  package org.apache.mina.example.proxy;
21  
22  import java.io.File;
23  import java.io.FileOutputStream;
24  import java.io.IOException;
25  import java.nio.channels.FileChannel;
26  
27  import org.apache.mina.core.buffer.IoBuffer;
28  import org.apache.mina.core.session.IdleStatus;
29  import org.apache.mina.core.session.IoSession;
30  import org.apache.mina.proxy.AbstractProxyIoHandler;
31  import org.apache.mina.proxy.handlers.ProxyRequest;
32  import org.apache.mina.proxy.handlers.http.HttpProxyConstants;
33  import org.apache.mina.proxy.handlers.http.HttpProxyRequest;
34  import org.apache.mina.proxy.handlers.socks.SocksProxyRequest;
35  import org.apache.mina.proxy.session.ProxyIoSession;
36  import org.slf4j.Logger;
37  import org.slf4j.LoggerFactory;
38  
39  /**
40   * ClientSessionHandler.java - Client session handler for the mina proxy test class.
41   * 
42   * @author The Apache MINA Project (dev@mina.apache.org)
43   * @version $Rev$, $Date$
44   * @since MINA 2.0.0-M3
45   */
46  public class ClientSessionHandler extends AbstractProxyIoHandler {
47      private final static Logger logger = LoggerFactory
48              .getLogger(ClientSessionHandler.class);
49  
50      /**
51       * The temporary file were the request result will be written.
52       */
53      private File file;
54  
55      /**
56       * NIO channel of the temporary file.
57       */
58      private FileChannel wChannel;
59  
60      /**
61       * The command to issue to the proxy.
62       */
63      private String cmd;
64  
65      public ClientSessionHandler(String cmd) {
66          this.cmd = cmd;
67      }
68  
69      /**
70       * {@inheritDoc} 
71       */
72      @Override
73      public void sessionCreated(IoSession session) throws Exception {
74          logger.debug("CLIENT - Session created: " + session);
75      }
76  
77      /**
78       * Sends the request to the proxy server when session is opened with
79       * the proxy. 
80       */
81      @Override
82      public void proxySessionOpened(IoSession session) throws Exception {
83          logger.debug("CLIENT - Session opened: " + session);
84          ProxyIoSession proxyIoSession = (ProxyIoSession) session
85                  .getAttribute(ProxyIoSession.PROXY_SESSION);
86          if (proxyIoSession != null) {
87              ProxyRequest req = proxyIoSession.getRequest();
88  
89              byte[] c = null;
90              if (req instanceof SocksProxyRequest && cmd != null) {
91                  logger.debug("Sending request to a SOCKS SESSION ...");
92                  c = cmd.getBytes(proxyIoSession.getCharsetName());
93              } else if (req instanceof HttpProxyRequest
94                      && ((HttpProxyRequest) req).getHttpVerb() == HttpProxyConstants.CONNECT) {
95                  logger.debug("Sending request to a HTTP CONNECTED SESSION ...");
96                  c = (((HttpProxyRequest) req).toHttpString())
97                          .getBytes(proxyIoSession.getCharsetName());
98              }
99  
100             if (c != null) {
101                 IoBuffer buf = IoBuffer.allocate(c.length);
102                 buf.put(c);
103                 buf.flip();
104                 session.write(buf);
105             }
106         }
107     }
108 
109     /**
110      * Writes the request result to a temporary file.
111      */
112     @Override
113     public void messageReceived(IoSession session, Object message) {
114         logger.debug("CLIENT - Message received: " + session);
115         IoBuffer buf = (IoBuffer) message;
116 
117         try {
118             if (file == null) {
119                 file = File.createTempFile("http", ".html");
120                 logger.info("Writing request result to "
121                         + file.getAbsolutePath());
122                 wChannel = new FileOutputStream(file, false).getChannel();
123             }
124 
125             // Write the ByteBuffer contents; the bytes between the ByteBuffer's
126             // position and the limit is written to the file
127             wChannel.write(buf.buf());
128         } catch (IOException e) {
129             //e.printStackTrace();
130         }
131     }
132 
133     /**
134      * Closes the temporary file if it was opened. 
135      */
136     @Override
137     public void sessionClosed(IoSession session) throws Exception {
138         logger.debug("CLIENT - Session closed - closing result file if open.");
139         // Close the file
140         if (wChannel != null) {
141             wChannel.close();
142         }
143     }
144 
145     /**
146      * {@inheritDoc} 
147      */
148     @Override
149     public void sessionIdle(IoSession session, IdleStatus status)
150             throws Exception {
151         if (session.isClosing()) {
152             return;
153         }
154 
155         logger.debug("CLIENT - Session idle");
156     }
157 
158     /**
159      * {@inheritDoc} 
160      */
161     @Override
162     public void exceptionCaught(IoSession session, Throwable cause) {
163         logger.debug("CLIENT - Exception caught");
164         //cause.printStackTrace();
165         session.close(true);
166     }
167 }