com.googlecode.lineblog.websocket.v2.TokenThread.java Source code

Java tutorial

Introduction

Here is the source code for com.googlecode.lineblog.websocket.v2.TokenThread.java

Source

/**
 * License
 * 
 * Licensed under the GNU GPL v3
 * http://www.gnu.org/licenses/gpl.html
 * 
 */
package com.googlecode.lineblog.websocket.v2;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.URL;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.googlecode.lineblog.websocket.v2.HelpUtil;
import com.googlecode.lineblog.websocket.v2.TokenManage;
import com.googlecode.lineblog.websocket.v2.TokenThread;
import com.googlecode.lineblog.websocket.v2.WebSocketServer;

/**
 * 
 * @author lichangshu E-mail:lchshu001@gmail.com
 * @version 2011-9-30 ?03:30:17
 */
public class TokenThread extends Thread {

    public static final String GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
    public static final String HEADER_CODE = "iso-8859-1";
    public static final String PROTOCOL = "chat";
    public static final int SPLITVERSION = 6;

    private int webSocketVersion = 0;
    private String token;
    private String user = null;//??
    private OutputStream out;
    private InputStream in;
    private Socket socket;
    private int status = 0; //??
    private static Log log = LogFactory.getLog(TokenThread.class);

    public TokenThread(Socket socket) throws IOException {
        if (socket == null)
            throw new RuntimeException("socket is not null!");
        this.socket = socket;
        this.in = new BufferedInputStream(this.socket.getInputStream());
        this.out = new BufferedOutputStream(this.socket.getOutputStream());
        this.status = this.accept();//?
    }

    public synchronized void sendMessage(MessageJSON json) throws IOException {
        String message = json.toJSON();
        if (webSocketVersion < 6)
            HelpUtil.writeFrame(out, message);
        else
            WebSocketV6Fram.writeWebSocketV6Fram(out, message);
        out.flush();
    }

    public boolean socketIsClosed() {
        return this.socket.isClosed();
    }

    public void logOut() {
        try {
            if (webSocketVersion < 6)
                out.write(WebSocketV6Fram.getCloseV5Fram());
            else
                out.write(WebSocketV6Fram.getCloseV6Fram());
            out.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            TokenManage.getTokenManage().removeTokenThread(this.token);
            try {
                this.socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (this.user != null)//
                    TokenManage.getTokenManage().executCommond(this.token, this.user,
                            TokenManage.COMMEND_OPTION_LOGOUT);
            } catch (IOException e) {
                e.printStackTrace();
            }
            log.info("[" + this.token + "] has logout!");
        }
    }

    public int login(String name) {
        return TokenManage.getTokenManage().putToken2Name(this.token, name);
    }

    @Override
    public void run() {
        if (status == 0)
            return;
        try {
            while (true) {
                byte[] bts;
                if (webSocketVersion < SPLITVERSION)
                    bts = HelpUtil.readFrame(in);
                else {
                    WebSocketV6Fram ws = WebSocketV6Fram.parseWebSocketV6Fram(in);
                    bts = WebSocketV6Fram.readWebSocketV6(in, ws);
                }
                if (bts == null)
                    return;
                String message = new String(bts, HelpUtil.WEB_SOCKET_CHARSET);
                log.debug(token + ":" + new String(bts, HelpUtil.WEB_SOCKET_CHARSET));
                //??
                try {
                    if (this.user == null) {
                        if (message.matches("^[0-9A-Za-z\\u00FF-\\u9FA5]*$")) {
                            int st = login(message);
                            if (st == 0) {
                                this.sendMessage(new MessageJSON(MessageJSON.MessageType_self, message));
                                TokenManage.getTokenManage().executCommond(this.getToken(), message,
                                        TokenManage.COMMEND_OPTION_LOGIN);
                                continue;
                            } else if (st == -2) {
                                message = "??????";
                            }
                        } else {
                            message = "??";
                        }
                        sendMessage(new MessageJSON(MessageJSON.MessageType_error, message,
                                System.currentTimeMillis(), null));
                        continue;
                    } else {
                        TokenManage.getTokenManage().executCommond(this.getToken(), message);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            this.logOut();
        }
    }

    public String getToken() {
        return token;
    }

    /**
     * ?
     */
    private int accept() {
        log.info("Start : " + socket.getRemoteSocketAddress().toString() + "["
                + TokenManage.getTokenManage().tokenThreadCount() + "]");
        try {
            String reqestLine = new String(HelpUtil.readLine(in));
            // headers : HTTP request header!
            Map<String, String> requestHeaders = new HashMap<String, String>();
            while (true) {
                byte[] bts = HelpUtil.readLine(in);
                if (bts[0] == '\r' && bts[1] == '\n') {
                    break;
                }
                String line = new String(bts);
                int mh = line.indexOf(':');
                requestHeaders.put(line.substring(0, mh), line.substring(mh + 1).trim());
            }
            //HTTP request headers!
            if (log.isDebugEnabled()) {
                log.debug("-- request : headers --");
                log.debug(reqestLine);
                for (String key : requestHeaders.keySet()) {
                    log.debug(key + ": " + requestHeaders.get(key));
                }
            }

            //Upgrade:WebSocket is null , so it's a general http request!
            if (requestHeaders.get("Upgrade") == null) {
                String url = "http://127.0.0.1" + reqestLine.split(" ")[1];
                //socket.setSoTimeout(5000);
                url = new URL(url).getPath();
                HelpUtil.writeFile(WebSocketServer.ROOT + url, out);
                socket.close();
                return 0;
            }

            // HTTP response header!
            Map<String, String> resMap = new HashMap<String, String>();
            String responsLine = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n";
            resMap.put("Upgrade", "WebSocket");
            resMap.put("Connection", "Upgrade");
            if (requestHeaders.get("Origin") != null)
                resMap.put("Sec-WebSocket-Origin", requestHeaders.get("Origin"));
            resMap.put("Sec-WebSocket-Location", "ws://" + requestHeaders.get("Host").trim() + "/");

            String token = null;
            byte[] content = null;
            //Sec-WebSocket-Version: 6  ? 
            String version = requestHeaders.get("Sec-WebSocket-Version");
            if (version != null) {
                webSocketVersion = new Integer(version);
            }
            if (webSocketVersion >= 6) {
                String code = requestHeaders.get("Sec-WebSocket-Key") + GUID;
                byte[] bts = MessageDigest.getInstance("SHA1").digest(code.getBytes(HEADER_CODE));
                code = HelpUtil.getBASE64(bts);
                resMap.put("Sec-WebSocket-Accept", code);
                //Sec-WebSocket-Protocol: chat
                resMap.put("Sec-WebSocket-Protocol", PROTOCOL);
                if (requestHeaders.get("Sec-WebSocket-Version") != null)
                    resMap.put("Sec-WebSocket-Version", requestHeaders.get("Sec-WebSocket-Version"));
                if (requestHeaders.get("Sec-WebSocket-Origin") != null)
                    resMap.put("Sec-WebSocket-Origin", requestHeaders.get("Sec-WebSocket-Origin"));
                token = HelpUtil.md5(code);
            } else {
                // the end 8 Byte!
                int len = 8; // in.available();
                byte[] key3 = new byte[len];
                if (in.read(key3) != len)
                    throw new RuntimeException();
                log.debug(HelpUtil.formatBytes(key3));
                String key1 = requestHeaders.get("Sec-WebSocket-Key1");
                String key2 = requestHeaders.get("Sec-WebSocket-Key2");
                int k1 = HelpUtil.parseWebsokcetKey(key1);
                int k2 = HelpUtil.parseWebsokcetKey(key2);

                byte[] sixteenByte = new byte[16];
                System.arraycopy(HelpUtil.intTo4Byte(k1), 0, sixteenByte, 0, 4);
                System.arraycopy(HelpUtil.intTo4Byte(k2), 0, sixteenByte, 4, 4);
                System.arraycopy(key3, 0, sixteenByte, 8, 8);
                byte[] md5 = MessageDigest.getInstance("MD5").digest(sixteenByte);
                content = md5;
                log.debug("response content : " + HelpUtil.formatBytes(md5));
                token = HelpUtil.md5(md5);
            }
            log.info("START , token [" + token + "]");

            //return user message
            out.write(responsLine.getBytes(HEADER_CODE));
            log.debug(responsLine);
            for (String key : resMap.keySet()) {
                out.write((key + ": " + resMap.get(key) + "\r\n").getBytes(HEADER_CODE));
                if (log.isDebugEnabled())
                    log.debug(key + ": " + resMap.get(key));
            }
            out.write("\r\n".getBytes());

            if (content != null)
                out.write(content);

            // return user the token!
            // HelpUtil.writeFrame(out, token);
            //getTokenUsers
            this.sendMessage(new MessageJSON(MessageJSON.MessageType_user,
                    TokenManage.getTokenManage().getTokenUsers(), System.currentTimeMillis(), null));
            this.sendMessage(new MessageJSON(MessageJSON.MessageType_system, "???"));
            out.flush();

            this.token = token;
            TokenManage.getTokenManage().putTokenThread(token, this);
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            if (socket != null)
                try {
                    socket.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            return 0;
        }
    }

    public int getWebSocketVersion() {
        return webSocketVersion;
    }

    public void setUser(String user) {
        this.user = user;
    }

    public String getUser() {
        return user;
    }
}