WebSocket
@@ -0,0 +1,70 @@ | ||
1 | +package startup_action; | |
2 | + | |
3 | +import java.io.IOException; | |
4 | +import java.io.InputStream; | |
5 | +import java.io.OutputStream; | |
6 | +import java.net.ServerSocket; | |
7 | +import java.net.Socket; | |
8 | + | |
9 | +import servercore.job.JobWorker; | |
10 | +import servercore.tcp.TcpInstance; | |
11 | +import socket_action.WebTest; | |
12 | + | |
13 | +public class StartTest extends Thread{ | |
14 | + OutputStream ops = null; | |
15 | + InputStream ips = null; | |
16 | + | |
17 | + public void run() { | |
18 | + // 接続があるまで待機する | |
19 | + ServerSocket serverSocket; | |
20 | + boolean continuos = true; | |
21 | + try { | |
22 | + serverSocket = new ServerSocket(8081, 100); | |
23 | + System.out.println("8081 sock opened"); | |
24 | + while(continuos) { | |
25 | + | |
26 | + Socket socket = null; | |
27 | + System.out.println("waiting..."); | |
28 | + socket = serverSocket.accept(); | |
29 | + | |
30 | + try{ | |
31 | + System.out.println("conected"); | |
32 | + //入出力ストリームを取得 | |
33 | + ops = socket.getOutputStream(); | |
34 | + ips = socket.getInputStream(); | |
35 | + byte[] readData = new byte[10000]; | |
36 | + | |
37 | + while(true) { | |
38 | + int length = ips.read(readData); | |
39 | + String str = new String(readData, 0, length); | |
40 | + WebTest.send(str); | |
41 | + System.out.println(str); | |
42 | + } | |
43 | + | |
44 | + } catch(Exception e){ | |
45 | + e.printStackTrace(); | |
46 | + } finally { | |
47 | + try{ | |
48 | + if(ips != null){ | |
49 | + ips.close(); | |
50 | + ips = null; | |
51 | + } | |
52 | + if(socket != null && !socket.isClosed()){ | |
53 | + socket.close(); | |
54 | + socket = null; | |
55 | + } | |
56 | + if(ops != null) { | |
57 | + ops.close(); | |
58 | + ops = null; | |
59 | + } | |
60 | + } | |
61 | + catch(IOException e){ | |
62 | + e.printStackTrace(); | |
63 | + } | |
64 | + } | |
65 | + } | |
66 | + } catch (IOException e1) { | |
67 | + e1.printStackTrace(); | |
68 | + } | |
69 | + } | |
70 | +} |
@@ -0,0 +1,39 @@ | ||
1 | +package socket_action; | |
2 | + | |
3 | +import java.io.IOException; | |
4 | +import java.io.InputStream; | |
5 | +import java.io.OutputStream; | |
6 | + | |
7 | +import servercore.http.HttpRequest; | |
8 | + | |
9 | +public class WebTest { | |
10 | + private static OutputStream ops = null; | |
11 | + public boolean cont = true; | |
12 | + public void execute(HttpRequest req, OutputStream ops, InputStream ips) { | |
13 | + this.ops = ops; | |
14 | + System.out.println("\r\nWebTest start"); | |
15 | + while(cont) { | |
16 | + try { | |
17 | + Thread.sleep(10); | |
18 | + } catch (InterruptedException e) { | |
19 | + // TODO 自動生成された catch ブロック | |
20 | + e.printStackTrace(); | |
21 | + } | |
22 | + } | |
23 | + System.out.println("\r\nWebTest end"); | |
24 | + } | |
25 | + | |
26 | + public static void send(String str) { | |
27 | + if(ops == null) { | |
28 | + return; | |
29 | + } | |
30 | + try { | |
31 | + ops.write(0x00); | |
32 | + ops.write(str.getBytes()); | |
33 | + ops.write(0xff); | |
34 | + ops.flush(); | |
35 | + } catch (IOException e) { | |
36 | + e.printStackTrace(); | |
37 | + } | |
38 | + } | |
39 | +} |
@@ -4,6 +4,7 @@ | ||
4 | 4 | import servercore.statics.StaticsMeothds; |
5 | 5 | import servercore.tcp.TcpServer; |
6 | 6 | import extension.file.LogWriter; |
7 | +import startup_action.StartTest; | |
7 | 8 | |
8 | 9 | public class HttpServer extends Thread implements StaticValues{ |
9 | 10 |
@@ -85,6 +86,9 @@ | ||
85 | 86 | LogWriter log = new LogWriter(httpServerLogPath); |
86 | 87 | TcpServer server = new TcpServer(); |
87 | 88 | try { |
89 | + StartTest starttest = new StartTest(); | |
90 | + starttest.start(); | |
91 | + | |
88 | 92 | TcpServer.setPortNum(recvPort); |
89 | 93 | server.start(); |
90 | 94 | System.out.println("server started"); |
@@ -41,7 +41,7 @@ | ||
41 | 41 | res = GeneratePage.execute(req, ops, ips); |
42 | 42 | } |
43 | 43 | } else { |
44 | - res = GeneratePage.execute(req); | |
44 | + res = GeneratePage.execute(req, ops, ips); | |
45 | 45 | } |
46 | 46 | |
47 | 47 | String resStr = ""; |
@@ -31,7 +31,7 @@ | ||
31 | 31 | res = executeCgi(req, pkg); |
32 | 32 | return res; |
33 | 33 | } else if("ws".equals(ext)) { |
34 | - int index = cgiPath.indexOf("ws"); | |
34 | + int index = cgiPath.indexOf(".ws"); | |
35 | 35 | String pkg = "socket_action" + cgiPath.substring(0, index); |
36 | 36 | executeWebSokcet(req, pkg, ops, ips); |
37 | 37 | } |
@@ -70,12 +70,113 @@ | ||
70 | 70 | // 実行する |
71 | 71 | return (HttpResponse)method.invoke(cls.newInstance(),req); |
72 | 72 | } |
73 | - private static void executeWebSokcet(HttpRequest req, String PackageName, OutputStream ops, InputStream ips) throws Exception { | |
73 | + private static void executeWebSokcet(HttpRequest req, String PackageName, OutputStream ops, InputStream ips) throws Exception { | |
74 | + String host = req.getHeader().get("Host"); | |
75 | + StringBuffer sb = new StringBuffer(); | |
76 | + | |
77 | + String path = req.getRowPath(); | |
78 | + String key1 = req.getHeader().get("Sec-WebSocket-Key1"); | |
79 | + String key2 = req.getHeader().get("Sec-WebSocket-Key2"); | |
80 | + String origin = req.getHeader().get("Origin"); | |
81 | + String res_ws = "ws://" + host + path; | |
82 | + byte[] body_code = getChalengeKey(req.headerBytes); | |
83 | + long key1_num = chooseNum(key1); | |
84 | + long key2_num = chooseNum(key2); | |
85 | + int key1_s = chooseSpace(key1); | |
86 | + int key2_s = chooseSpace(key2); | |
87 | + long key1_w = key1_num / key1_s; | |
88 | + long key2_w = key2_num / key2_s; | |
89 | + byte[] key_head = bigendiean(key1_w, key2_w); | |
90 | + byte[] byte_keys = new byte[16]; | |
91 | + System.arraycopy(key_head, 0, byte_keys, 0, 8); | |
92 | + System.arraycopy(body_code, 0, byte_keys, 8, 8); | |
93 | + | |
94 | + MessageDigest md = MessageDigest.getInstance("MD5"); | |
95 | + md.update(byte_keys); | |
96 | + byte[] hash = md.digest(); | |
97 | + | |
98 | + sb.append("HTTP/1.1 101 WebSocket Protocol Handshake\r\n"); | |
99 | + sb.append("Upgrade: WebSocket\r\n"); | |
100 | + sb.append("Connection: Upgrade\r\n"); | |
101 | + sb.append("Sec-WebSocket-Location: " + res_ws + "\r\n"); | |
102 | + sb.append("Sec-WebSocket-Origin: http://" + host + "\r\n"); | |
103 | + sb.append("\r\n"); | |
104 | + ops.write(sb.toString().getBytes()); | |
105 | + ops.write(hash); | |
106 | + | |
107 | + | |
74 | 108 | Class<Action> cls = null; |
75 | 109 | |
76 | 110 | cls = (Class<Action>)Class.forName(PackageName); |
77 | - Method method = cls.getMethod("execute", HttpRequest.class); | |
111 | + Method method = cls.getMethod("execute", HttpRequest.class, OutputStream.class, InputStream.class); | |
78 | 112 | // 実行する |
79 | - method.invoke(cls.newInstance(),req); | |
113 | + method.invoke(cls.newInstance(), req, ops, ips); | |
80 | 114 | } |
115 | + public static byte[] getChalengeKey(byte[] header) { | |
116 | + byte[] ret = null; | |
117 | + try { | |
118 | + for(int i = 0;i < header.length;i++) { | |
119 | + if(header[i] == '\r' && header[i + 1] == '\n') { | |
120 | + if(header[i + 2] == '\r' && header[i + 3] == '\n') { | |
121 | + int lastAt = header.length - (i + 4); | |
122 | + ret = new byte[lastAt]; | |
123 | + System.arraycopy(header, i + 4, ret, 0, lastAt); | |
124 | + break; | |
125 | + } | |
126 | + } | |
127 | + } | |
128 | + } catch(Exception e) { | |
129 | + e.printStackTrace(); | |
130 | + } | |
131 | + return ret; | |
132 | + } | |
133 | + public static long chooseNum(String str) { | |
134 | + String code = ""; | |
135 | + for(int i = 0;i < str.length();i++) { | |
136 | + try { | |
137 | + int num = Integer.parseInt("" + str.charAt(i)); | |
138 | + code += num; | |
139 | + } catch(Exception e) {} | |
140 | + } | |
141 | + long ret = 0; | |
142 | + try { | |
143 | + ret = Long.parseLong(code); | |
144 | + } catch(Exception e) {} | |
145 | + return ret; | |
146 | + } | |
147 | + public static int chooseSpace(String str) { | |
148 | + int ret = 0; | |
149 | + for(int i =0;i < str.length();i++) { | |
150 | + if(str.charAt(i) == ' ') { | |
151 | + ret++; | |
152 | + } | |
153 | + } | |
154 | + return ret; | |
155 | + } | |
156 | + public static byte[] bigendiean(long key1_w, long key2_w) { | |
157 | + long lon1 = key1_w; | |
158 | + long lon2 = key2_w; | |
159 | + byte[] bytes = new byte[8]; | |
160 | + int[] ints = new int[8]; | |
161 | + ints[3] = (int)(lon1 % 256); | |
162 | + lon1 /= 256; | |
163 | + ints[2] = (int)(lon1 % 256); | |
164 | + lon1 /= 256; | |
165 | + ints[1] = (int)(lon1 % 256); | |
166 | + lon1 /= 256; | |
167 | + ints[0] = (int)lon1; | |
168 | + | |
169 | + ints[7] = (int)(lon2 % 256); | |
170 | + lon2 /= 256; | |
171 | + ints[6] = (int)(lon2 % 256); | |
172 | + lon2 /= 256; | |
173 | + ints[5] = (int)(lon2 % 256); | |
174 | + lon2 /= 256; | |
175 | + ints[4] = (int)lon2; | |
176 | + | |
177 | + for(int i = 0;i < 8;i++) { | |
178 | + bytes[i] = (byte)ints[i]; | |
179 | + } | |
180 | + return bytes; | |
181 | + } | |
81 | 182 | } |