view src/IOHandler.java @ 0:5a50d4b48bf9

init
author kazz <kazz@cr.ie.u-ryukyu.ac.jp>
date Wed, 19 Jan 2011 00:16:26 +0900
parents
children 4c2ddaa9b998
line wrap: on
line source

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class IOHandler implements Handler {
	public static int BUFFERSIZE = 8192;
	public HashMap<String, String> map = new HashMap<String, String>();
	
	@Override
	public void handle(SelectionKey key) {
		if (!key.isReadable())
			return;
		SocketChannel sChannel = (SocketChannel)key.channel();
		ByteBuffer buffer = ByteBuffer.allocate(BUFFERSIZE);
		try {
			int num;
			if ((num = sChannel.read(buffer)) > 0) {
				String str = new String(buffer.array());
				Pattern pat = Pattern.compile("((([^\n\r]+): ([^\n\r]+))|(^GET ([/A-Za-z]+) HTTP/1.1))");
				Matcher mat = pat.matcher(str);
				while (mat.find()) {
					if (mat.group(6) != null) {
						map.put("path", mat.group(6));
					}
					if (mat.group(3) != null && mat.group(4) != null) {
						map.put(mat.group(3), mat.group(4));
					}
				}
				buffer.position(num - 8);
				byte[] key3 = new byte[8];
				buffer.get(key3);
				byte[] resCode = generateResponseCode(key3);
				ByteBuffer response = generateResponse(resCode);
				sChannel.write(response);
				System.out.println("sent response");
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private ByteBuffer generateResponse(byte[] resCode) {
		ByteBuffer response = ByteBuffer.allocate(BUFFERSIZE);
		response.put("HTTP/1.1 101 WebSocket Protocol Handshake\r\n".getBytes());
		response.put("Upgrade: WebSocket\r\n".getBytes());
		response.put("Connection: ".getBytes());
		response.put(map.get("Connection").getBytes());
		response.put("\r\n".getBytes());
		response.put("Sec-WebSocket-Origin: ".getBytes());
		response.put(map.get("Origin").getBytes());
		response.put("\r\n".getBytes());
		response.put("Sec-WebSocket-Location: ".getBytes());
		response.put(generateWebSocketAddress(map.get("Origin"), map.get("path")).getBytes());
		response.put("\r\n".getBytes());
		String s;
		if ((s = map.get("Sec-WebSocket-Protocol")) != null) {
			response.put("Sec-WebSocket-Protocol: ".getBytes());
			response.put(s.getBytes());
			response.put("\r\n".getBytes());
		}		
		response.put("\r\n".getBytes());
		response.put(resCode);
		//response.put("\r\n".getBytes());
		response.limit(response.position());
		response.rewind();
		return response;
	}
	
	private String generateWebSocketAddress(String origin, String path) {
		return origin.replaceAll("https*", "ws") + ":" + WebSocketServer.port + path;
	}

	private byte[] generateResponseCode(byte[] key3) {
		int val1 = generateResponseCodeValue(map.get("Sec-WebSocket-Key1"));
		int val2 = generateResponseCodeValue(map.get("Sec-WebSocket-Key2"));
		ByteBuffer buf = ByteBuffer.allocate(16);
		buf.order(ByteOrder.BIG_ENDIAN);
		buf.putInt(val1);
		buf.putInt(val2);
		buf.put(key3);
		byte[] code = null;
		try {
			MessageDigest digest = MessageDigest.getInstance("MD5");
			code = digest.digest(buf.array());
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return code;
	} 
	
	private int generateResponseCodeValue(String str) {
		char[] ch = str.toCharArray();
		int val = 0;
		int spNum = 0;
		for (char c : ch) {
			if (c == ' ') {
				spNum++;
			} else if ('0' <= c && c <= '9') {
				val *= 10;
				val += c - '0';
			}
		}
		return val / spNum;
	}
}