0
|
1 import java.io.IOException;
|
|
2 import java.nio.ByteBuffer;
|
|
3 import java.nio.ByteOrder;
|
|
4 import java.nio.channels.SelectionKey;
|
|
5 import java.nio.channels.SocketChannel;
|
|
6 import java.security.MessageDigest;
|
|
7 import java.security.NoSuchAlgorithmException;
|
|
8 import java.util.HashMap;
|
|
9 import java.util.regex.Matcher;
|
|
10 import java.util.regex.Pattern;
|
|
11
|
|
12 public class IOHandler implements Handler {
|
|
13 public static int BUFFERSIZE = 8192;
|
|
14 public HashMap<String, String> map = new HashMap<String, String>();
|
|
15
|
|
16 @Override
|
|
17 public void handle(SelectionKey key) {
|
2
|
18 if (!key.isReadable()) {
|
3
|
19 key.cancel();
|
0
|
20 return;
|
2
|
21 }
|
0
|
22 SocketChannel sChannel = (SocketChannel)key.channel();
|
|
23 ByteBuffer buffer = ByteBuffer.allocate(BUFFERSIZE);
|
|
24 try {
|
|
25 int num;
|
|
26 if ((num = sChannel.read(buffer)) > 0) {
|
1
|
27 String str = new String(buffer.array(), 0, num - 8);
|
|
28 Pattern pat = Pattern.compile("((([^\n\r:]+): ([^\n\r]+))|(^GET ([^ \n\r]+) HTTP/1.1))");
|
0
|
29 Matcher mat = pat.matcher(str);
|
|
30 while (mat.find()) {
|
|
31 if (mat.group(6) != null) {
|
|
32 map.put("path", mat.group(6));
|
|
33 }
|
|
34 if (mat.group(3) != null && mat.group(4) != null) {
|
|
35 map.put(mat.group(3), mat.group(4));
|
|
36 }
|
|
37 }
|
|
38 buffer.position(num - 8);
|
|
39 byte[] key3 = new byte[8];
|
|
40 buffer.get(key3);
|
|
41 byte[] resCode = generateResponseCode(key3);
|
|
42 ByteBuffer response = generateResponse(resCode);
|
|
43 sChannel.write(response);
|
|
44 System.out.println("sent response");
|
3
|
45 } else {
|
|
46 key.cancel();
|
0
|
47 }
|
|
48 } catch (IOException e) {
|
|
49 e.printStackTrace();
|
|
50 }
|
|
51 }
|
|
52
|
|
53 private ByteBuffer generateResponse(byte[] resCode) {
|
|
54 ByteBuffer response = ByteBuffer.allocate(BUFFERSIZE);
|
|
55 response.put("HTTP/1.1 101 WebSocket Protocol Handshake\r\n".getBytes());
|
|
56 response.put("Upgrade: WebSocket\r\n".getBytes());
|
|
57 response.put("Connection: ".getBytes());
|
|
58 response.put(map.get("Connection").getBytes());
|
|
59 response.put("\r\n".getBytes());
|
|
60 response.put("Sec-WebSocket-Origin: ".getBytes());
|
|
61 response.put(map.get("Origin").getBytes());
|
|
62 response.put("\r\n".getBytes());
|
|
63 response.put("Sec-WebSocket-Location: ".getBytes());
|
|
64 response.put(generateWebSocketAddress(map.get("Origin"), map.get("path")).getBytes());
|
|
65 response.put("\r\n".getBytes());
|
|
66 String s;
|
|
67 if ((s = map.get("Sec-WebSocket-Protocol")) != null) {
|
|
68 response.put("Sec-WebSocket-Protocol: ".getBytes());
|
|
69 response.put(s.getBytes());
|
|
70 response.put("\r\n".getBytes());
|
|
71 }
|
|
72 response.put("\r\n".getBytes());
|
|
73 response.put(resCode);
|
|
74 //response.put("\r\n".getBytes());
|
|
75 response.limit(response.position());
|
|
76 response.rewind();
|
|
77 return response;
|
|
78 }
|
|
79
|
|
80 private String generateWebSocketAddress(String origin, String path) {
|
|
81 return origin.replaceAll("https*", "ws") + ":" + WebSocketServer.port + path;
|
|
82 }
|
|
83
|
|
84 private byte[] generateResponseCode(byte[] key3) {
|
|
85 int val1 = generateResponseCodeValue(map.get("Sec-WebSocket-Key1"));
|
|
86 int val2 = generateResponseCodeValue(map.get("Sec-WebSocket-Key2"));
|
|
87 ByteBuffer buf = ByteBuffer.allocate(16);
|
|
88 buf.order(ByteOrder.BIG_ENDIAN);
|
|
89 buf.putInt(val1);
|
|
90 buf.putInt(val2);
|
|
91 buf.put(key3);
|
|
92 byte[] code = null;
|
|
93 try {
|
|
94 MessageDigest digest = MessageDigest.getInstance("MD5");
|
|
95 code = digest.digest(buf.array());
|
|
96 } catch (NoSuchAlgorithmException e) {
|
|
97 e.printStackTrace();
|
|
98 }
|
|
99 return code;
|
|
100 }
|
|
101
|
|
102 private int generateResponseCodeValue(String str) {
|
|
103 char[] ch = str.toCharArray();
|
1
|
104 long val = 0;
|
0
|
105 int spNum = 0;
|
|
106 for (char c : ch) {
|
|
107 if (c == ' ') {
|
|
108 spNum++;
|
|
109 } else if ('0' <= c && c <= '9') {
|
|
110 val *= 10;
|
|
111 val += c - '0';
|
|
112 }
|
|
113 }
|
1
|
114 return (int) (val / spNum);
|
0
|
115 }
|
|
116 }
|