Package net.sourceforge.kitteh.impl

Source Code of net.sourceforge.kitteh.impl.ConnectionImpl

package net.sourceforge.kitteh.impl;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.net.URLDecoder;
import java.security.SecureRandom;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.StringTokenizer;

import net.sourceforge.kitteh.DocumentProducer;
import net.sourceforge.kitteh.Method;
import net.sourceforge.kitteh.Redirection;
import net.sourceforge.kitteh.WebSocketListener;
import net.sourceforge.kitteh.impl.ws.WebSocketImpl;

public class ConnectionImpl implements Runnable
{
    private static final String COOKIE_NAME = "session-cookie";
 
    private Socket socket;
    private Random rand = new SecureRandom();

    private DocumentProducer pageProducer;
   
    RequestImpl req = new RequestImpl();
    ResponseImpl resp = new ResponseImpl();

  private WebSocketListener wsHandler;
   
   
    public ConnectionImpl(Socket socket, DocumentProducer pageProducer, WebSocketListener wsHandler)
    {
        this.socket = socket;
        this.pageProducer = pageProducer;
        this.wsHandler = wsHandler;
      
    }

    private static Map<String, String> stringToParams(String p)
    {
        HashMap<String, String> res = new HashMap<String, String>();
        StringTokenizer t = new StringTokenizer(p, "&");
        while (t.hasMoreTokens())
        {
            String couple = t.nextToken();
            int pos = couple.indexOf("=");
            if (pos == -1)
            {
                res.put(couple, "");
            }
            else
            {
                String key = couple.substring(0, pos);
                String val = couple.substring(pos + 1, couple.length());

                try
                {
                    val = URLDecoder.decode(val, "UTF-8");
                }
                catch (UnsupportedEncodingException e)
                {
                    throw new RuntimeException("error", e);
                }

                res.put(key, val);
            }

        }
        return res;
    }

    private static void sendHeader(OutputStream out, int code,
            String contentType, long contentLength, boolean cacheable,
            String location, Map<String, String> headers) throws IOException
    {
        StringBuffer h = new StringBuffer();

        h.append("HTTP/1.0 ");
        h.append(code);
        h.append(" OK\r\n");
        h.append("Date: ");
        h.append(new Date().toString());
        h.append("\r\n");
        h.append("Server: WebServer/1.0\r\n");
        h.append("Connection: close\r\n");
        h.append("Content-Type: ");
        h.append(contentType);
        h.append("\r\n");
       
        if (cacheable)
        {
          headers.put("Expires", "Thu, 01 Jan 2100 00:00:00 GMT");
        }
        else
        {
          headers.put("Cache-Control","no-cache");
          headers.put("Pragma","no-cache");
          headers.put("Expires", "Thu, 01 Jan 1970 00:00:00 GMT");
          /*h.append("Last-modified: ");
            h.append(new Date().toString());
            h.append("\r\n");*/
    }
       
       
        if (contentLength != -1)
        {
            h.append("Content-Length: ");
            h.append(contentLength);
            h.append("\r\n");
        }
        if (location != null)
        {
            h.append("Location: " + location + "\r\n");
        }
       

        for (String header : headers.keySet())
        {
            h.append(header+": "+headers.get(header));
            h.append("\r\n");
        }

       
        h.append("\r\n");
        out.write(h.toString().getBytes());
    }

    private static void error(OutputStream out, Exception e) throws IOException
    {
      StringWriter s = new StringWriter();
      PrintWriter pw = new PrintWriter(s);
      
        pw.println("Kitteh Server error");
        pw.println("-------------------");
        e.printStackTrace(pw);
        pw.flush();
       
        byte[] buf = s.getBuffer().toString().getBytes();
        sendHeader(out, 500, "text/plain", buf.length, false, null, new HashMap<String, String>(0));
        out.write(buf);
    }

    private Map<String, String> loadReqData(BufferedReader in) throws IOException
    {
        HashMap<String, String> x = new HashMap<String, String>();
        String s = in.readLine();
        while (!"".equals(s))
        {
            String[] couple = s.split(":", 2);
            if (couple.length == 2)
            {
                x.put(couple[0].trim().toLowerCase(), couple[1].trim());
            }
            s = in.readLine();

        }
        return x;

    }

    private String getCookie(Map<String, String> headers)
    {
      String c = (String)headers.get("cookie");
      if (c != null)
    {
        String[] x = c.split("=");
        if (x[0].equals(COOKIE_NAME))
      {
        return x[1];
      }
    }
      return null;
          
    }
    private void handleRequest(RequestImpl request, BufferedReader in) throws IOException
    {
        // read the first line. HelloWorld "GET /index.html HTTP/1.1"
        String firstLine = in.readLine();
        if (firstLine == null)
        {
            throw new IOException("Null request");
        }
        // separate the three token
        String[] req = firstLine.split(" ", 3);
        if (req.length != 3)
        {
            throw new IOException("Non standard request");
        }
        // method and document name.. forget the protocol :P
        String method = req[0].toLowerCase();
        String docName = req[1];
        if (docName.startsWith("/"))
        {
            docName = docName.substring(1, docName.length());
        }

        // load request data
        request.setHeaders( loadReqData(in) );

        if (method.equals("get"))
        {
          request.setMethod(Method.GET);
            // if it is GET, separate the parameters from the doc name
            int pos = docName.indexOf("?");
            if (pos == -1)
            {
                // no parameters passed
                request.setDocumentName( docName );
            }
            else
            {
                // parameters!
              request.setDocumentName( docName.substring(0, pos) );
                String paramStr = docName.substring(pos + 1, docName.length());
                request.setParameters( stringToParams(paramStr) );
            }

        }
        else if (method.equals("post"))
        {
          request.setMethod(Method.POST);
            // if it is post, read the following data..
          request.setDocumentName( docName );
            try
            {
                int size = Integer.parseInt((String) request.getHeaders().get("content-length"));
                char[] b = new char[size];
                if (in.read(b) != size)
                {
                    throw new Exception("can't read all");
                }
                request.setParameters( stringToParams(new String(b)) );
            }
            catch (Exception e)
            {
                e.printStackTrace();
                // ensure we do not pass anything if something goes wrong
                request.setParameters( new HashMap<String, String>() );
            }
        }
        else
        {
            throw new IOException("Unknown method");
        }
    }

    private String bakeNewCookie()
    {
      StringBuffer s = new StringBuffer();
      while (s.length()<30)
    {
      s.append( Long.toString( rand.nextLong() & Long.MAX_VALUE , 36 ).toUpperCase() );
    }
      return s.substring(0, 30);

    }
    private static int copyStream(InputStream in, OutputStream out) throws IOException
    {
      int bufferSize = 1024;
      int streamLength = 0;
      byte[] buffer = new byte[bufferSize];
      for (int len=in.read(buffer); len>0; len=in.read(buffer) )
      {
        out.write(buffer, 0, len);
        out.flush();
        streamLength += len;
      }
      return streamLength;
    }
    private void writeResponse() throws IOException
    {
    OutputStream out = socket.getOutputStream();
    try
    {
            pageProducer.produceDocument(req, resp);
            sendHeader(out, resp.getHtmlReturnCode(), resp.getContentType(), resp.getContentLength(), resp.isCacheable(), null, resp.getHeaders());
            InputStream cont = resp.getContent();
            try
            {
              copyStream(cont, out);
            }
            finally
            {
              cont.close();
            }
    }
    catch (Redirection e)
    {
        // handle user redirections
        String d = "Document moved";
        sendHeader(out, 302, "text/plain", d.length(), false, e.getUrl(), new HashMap<String, String>(0));
        out.write(d.getBytes());
    }
    catch (Exception e)
    {
        // send generic unexpected exception
        error(out, e);
    }
    out.flush();
    }

    public void readRequest()
    {
  try
  {
      socket.setSoTimeout(600000);
     
     
      BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
     
      handleRequest(req, in);
      req.setRemoteAddr( socket.getInetAddress().toString() );
     
      handleSession(req, resp);
  }
  catch (Exception e)
  {
      try
      {
    socket.close();
      }
      catch (IOException e1)
      {
    // nothing
      }
      e.printStackTrace();
  }
    }

    private void handleSession(RequestImpl req, ResponseImpl resp)
    {
    String cookie = getCookie(req.getHeaders());
    if ((cookie == null) || (!SessionContainer.hasSession(cookie)))
    {
      cookie = bakeNewCookie();
      resp.getHeaders().put("Set-Cookie", COOKIE_NAME+"="+cookie);
    }
    req.setSession(SessionContainer.getSession(cookie));
    req.setSessionId(cookie);
    }

    public void run()
    {
    try
    {
      if(isWebSocketRequest())
      {
        WebSocketImpl ws = new WebSocketImpl(socket, req, wsHandler);
        ws.start();
      }
      else
      {
        try
        {
          writeResponse();
        }
        finally
        {
          try
            {
              socket.close();
            }
            catch (IOException e1)
            {
              // nothing
            }
        }
      }
    }
    catch (IOException e)
    {
       
        e.printStackTrace();
    }
   
   
    }




  private boolean isWebSocketRequest() {
    String con = req.getHeaders().get("connection");
    String upg = req.getHeaders().get("upgrade");
   
    return "Upgrade".equals(con) && "websocket".equals(upg);
  }
}
TOP

Related Classes of net.sourceforge.kitteh.impl.ConnectionImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.