# HG changeset patch # User kazz # Date 1295363786 -32400 # Node ID 5a50d4b48bf964c83fad14402c1c43728ff1a4bb init diff -r 000000000000 -r 5a50d4b48bf9 .classpath --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.classpath Wed Jan 19 00:16:26 2011 +0900 @@ -0,0 +1,6 @@ + + + + + + diff -r 000000000000 -r 5a50d4b48bf9 .project --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.project Wed Jan 19 00:16:26 2011 +0900 @@ -0,0 +1,17 @@ + + + WebSocket + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff -r 000000000000 -r 5a50d4b48bf9 src/AcceptHandler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/AcceptHandler.java Wed Jan 19 00:16:26 2011 +0900 @@ -0,0 +1,24 @@ +import java.io.IOException; +import java.nio.channels.SelectionKey; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; + + +public class AcceptHandler implements Handler { + + @Override + public void handle(SelectionKey key) { + ServerSocketChannel ssChannel = (ServerSocketChannel)key.channel(); + try { + SocketChannel sChannel = ssChannel.accept(); + if (sChannel == null) + return; + sChannel.configureBlocking(false); + sChannel.register(key.selector(), SelectionKey.OP_READ, new IOHandler()); + + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff -r 000000000000 -r 5a50d4b48bf9 src/Handler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/Handler.java Wed Jan 19 00:16:26 2011 +0900 @@ -0,0 +1,6 @@ +import java.nio.channels.SelectionKey; + + +public interface Handler { + public void handle(SelectionKey key); +} diff -r 000000000000 -r 5a50d4b48bf9 src/IOHandler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/IOHandler.java Wed Jan 19 00:16:26 2011 +0900 @@ -0,0 +1,113 @@ +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 map = new HashMap(); + + @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; + } +} diff -r 000000000000 -r 5a50d4b48bf9 src/MatcherTest.java Binary file src/MatcherTest.java has changed diff -r 000000000000 -r 5a50d4b48bf9 src/WebSocketServer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/WebSocketServer.java Wed Jan 19 00:16:26 2011 +0900 @@ -0,0 +1,53 @@ +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.ServerSocketChannel; + +public class WebSocketServer { + public static int port; + private ServerSocketChannel ssChannel; + private Selector selector; + private boolean running = true; + + public WebSocketServer(int port) { + this.port = port; + try { + ssChannel = ServerSocketChannel.open(); + ssChannel.socket().bind(new InetSocketAddress(port)); + ssChannel.configureBlocking(false); + selector = Selector.open(); + ssChannel.register(selector, SelectionKey.OP_ACCEPT, new AcceptHandler()); + } catch (IOException e) { + System.out.println("Can't open ServerSocketChannel."); + e.printStackTrace(); + } + } + + public void mainLoop() { + + while (running) { + try { + int keyCount = selector.select(0); + for (SelectionKey key : selector.selectedKeys()) { + Handler handler = (Handler) key.attachment(); + handler.handle(key); + selector.selectedKeys().remove(key); + } + + } catch (IOException e) { + e.printStackTrace(); + } + } + + } + + /** + * @param args + */ + public static void main(String[] args) { + WebSocketServer wsServer = new WebSocketServer(11000); + wsServer.mainLoop(); + } + +}