• R/O
  • SSH
  • HTTPS

webserver: Commit


Commit MetaInfo

Revision61 (tree)
Time2010-11-19 23:27:59
Authorhoritaku

Log Message

HTML5 WebSocket テスト

Change Summary

Incremental Difference

--- branch/Basic 0.2x/src/servercore/job/JobWorker.java (revision 60)
+++ branch/Basic 0.2x/src/servercore/job/JobWorker.java (revision 61)
@@ -4,6 +4,8 @@
44 import java.io.InputStream;
55 import java.io.OutputStream;
66 import java.io.File;
7+import java.security.MessageDigest;
8+import java.security.NoSuchAlgorithmException;
79 import java.sql.Date;
810 import java.text.SimpleDateFormat;
911 import java.util.HashMap;
@@ -25,10 +27,10 @@
2527
2628 System.out.print(req.getMethod() + "\t" + req.getRowPath() + "\t");
2729
28- HttpResponse res = security(req);
29- if(res.getStatusCore() == 200) {
30- res = GeneratePage.execute(req);
30+ if("ws".equals(ext)) {
31+ websocketTest(req, ops, ips);
3132 }
33+ HttpResponse res = GeneratePage.execute(req);
3234 System.out.println(res.getStatusCore());
3335
3436 String resStr = "";
@@ -93,6 +95,9 @@
9395 if(recvByteNum < 0) {
9496 return null;
9597 }
98+ byte[] headerRowBytes = new byte[recvByteNum];
99+ System.arraycopy(recvByte, 0, headerRowBytes, 0, recvByteNum);
100+ req.headerBytes = headerRowBytes;
96101 String firstLine = new String(recvByte, 0, recvByteNum);
97102
98103 firstLine = firstLine.replaceAll("\\r\\n\\r\\n", "\r\n \r\n");
@@ -202,4 +207,120 @@
202207 String editedDate = sdf.format(new Date(milliSecound));
203208 return editedDate;
204209 }
210+ public void websocketTest(HttpRequest req, OutputStream ops, InputStream ips) {
211+ String host = req.getHeader().get("Host");
212+ StringBuffer sb = new StringBuffer();
213+ try {
214+ String path = req.getRowPath();
215+ String key1 = req.getHeader().get("Sec-WebSocket-Key1");
216+ String key2 = req.getHeader().get("Sec-WebSocket-Key2");
217+ String origin = req.getHeader().get("Origin");
218+ String res_ws = "ws://" + host + path;
219+ byte[] c = getChalengeKey(req.headerBytes);
220+ long key1_num = chooseNum(key1);
221+ long key2_num = chooseNum(key2);
222+ int key1_s = chooseSpace(key1);
223+ int key2_s = chooseSpace(key2);
224+ long key1_w = key1_num / key1_s;
225+ long key2_w = key2_num / key2_s;
226+ byte[] key_head = bigendiean(key1_w, key2_w);
227+ byte[] byte_keys = new byte[16];
228+ System.arraycopy(key_head, 0, byte_keys, 0, 8);
229+ System.arraycopy(c, 0, byte_keys, 8, 8);
230+
231+ MessageDigest md = MessageDigest.getInstance("MD5");
232+ md.update(byte_keys);
233+ byte[] hash = md.digest();
234+
235+ sb.append("HTTP/1.1 101 WebSocket Protocol Handshake\r\n");
236+ sb.append("Upgrade: WebSocket\r\n");
237+ sb.append("Connection: Upgrade\r\n");
238+ sb.append("Sec-WebSocket-Location: " + res_ws + "\r\n");
239+ sb.append("Sec-WebSocket-Origin: http://" + host + "\r\n");
240+ sb.append("\r\n");
241+ ops.write(sb.toString().getBytes());
242+ ops.write(hash);
243+
244+ byte[] recv = new byte[128];
245+ int rescByte = ips.read(recv);
246+ String str = new String(recv, 0, rescByte);
247+ ops.write(0x00);
248+ ops.write("abcdefg".getBytes());
249+ ops.write(0xff);
250+
251+ } catch (IOException e) {
252+ e.printStackTrace();
253+ } catch (NoSuchAlgorithmException e) {
254+ e.printStackTrace();
255+ }
256+
257+ }
258+ public byte[] getChalengeKey(byte[] header) {
259+ byte[] ret = null;
260+ try {
261+ for(int i = 0;i < header.length;i++) {
262+ if(header[i] == '\r' && header[i + 1] == '\n') {
263+ if(header[i + 2] == '\r' && header[i + 3] == '\n') {
264+ int lastAt = header.length - (i + 4);
265+ ret = new byte[lastAt];
266+ System.arraycopy(header, i + 4, ret, 0, lastAt);
267+ break;
268+ }
269+ }
270+
271+ }
272+ } catch(Exception e) {
273+ e.printStackTrace();
274+ }
275+ return ret;
276+ }
277+ public long chooseNum(String str) {
278+ String code = "";
279+ for(int i = 0;i < str.length();i++) {
280+ try {
281+ int num = Integer.parseInt("" + str.charAt(i));
282+ code += num;
283+ } catch(Exception e) {}
284+ }
285+ long ret = 0;
286+ try {
287+ ret = Long.parseLong(code);
288+ } catch(Exception e) {}
289+ return ret;
290+ }
291+ public int chooseSpace(String str) {
292+ int ret = 0;
293+ for(int i =0;i < str.length();i++) {
294+ if(str.charAt(i) == ' ') {
295+ ret++;
296+ }
297+ }
298+ return ret;
299+ }
300+ public byte[] bigendiean(long key1_w, long key2_w) {
301+ long lon1 = key1_w;
302+ long lon2 = key2_w;
303+ byte[] bytes = new byte[8];
304+ int[] ints = new int[8];
305+ ints[3] = (int)(lon1 % 256);
306+ lon1 /= 256;
307+ ints[2] = (int)(lon1 % 256);
308+ lon1 /= 256;
309+ ints[1] = (int)(lon1 % 256);
310+ lon1 /= 256;
311+ ints[0] = (int)lon1;
312+
313+ ints[7] = (int)(lon2 % 256);
314+ lon2 /= 256;
315+ ints[6] = (int)(lon2 % 256);
316+ lon2 /= 256;
317+ ints[5] = (int)(lon2 % 256);
318+ lon2 /= 256;
319+ ints[4] = (int)lon2;
320+
321+ for(int i = 0;i < 8;i++) {
322+ bytes[i] = (byte)ints[i];
323+ }
324+ return bytes;
325+ }
205326 }
--- branch/Basic 0.2x/src/servercore/http/HttpRequest.java (revision 60)
+++ branch/Basic 0.2x/src/servercore/http/HttpRequest.java (revision 61)
@@ -22,6 +22,7 @@
2222 private HtmlParam getParams = null;
2323 private HtmlParam postParams = null;
2424 private HashMap<String, String> cookieValues = new HashMap<String, String>();
25+ public byte[] headerBytes = null;
2526 public String getExtesion() {
2627 return extension;
2728 }
--- branch/Basic 0.2x/docRoot2/index.html (revision 0)
+++ branch/Basic 0.2x/docRoot2/index.html (revision 61)
@@ -0,0 +1,31 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
2+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3+
4+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
5+<head>
6+<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8"/>
7+<meta http-equiv="Content-Style-Type" content="text/css" />
8+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
9+<meta http-equiv="Content-Script-Type" content="text/javascript" />
10+
11+<script type="text/javascript" src="js/jquery.js"></script>
12+<script>
13+<!--
14+var ws = new WebSocket("ws://localhost/WebTest.ws");
15+ws.onmessage = function(msg) {
16+ alert(msg.data);
17+}
18+ws.onopen = function(){
19+ ws.send('message');
20+}
21+ -->
22+</script>
23+<title>メイン画面</title>
24+
25+</head>
26+
27+<body>
28+<p>これはメイン画面です。</p>
29+<div id="test"></div>
30+</body>
31+</html>
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
--- branch/Basic 0.2x/docRoot2/real.html (revision 0)
+++ branch/Basic 0.2x/docRoot2/real.html (revision 61)
@@ -0,0 +1,173 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
2+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3+
4+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
5+<head>
6+<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8"/>
7+<meta http-equiv="Content-Style-Type" content="text/css" />
8+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
9+<meta http-equiv="Content-Script-Type" content="text/javascript" />
10+
11+<script type="text/javascript" src="js/jquery.js"></script>
12+<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
13+<script type="text/javascript" src ="http://www.google.com/jsapi"></script>
14+<script>
15+<!--
16+var tmrID;//タイマーID
17+var first = 0;
18+var all_map;
19+window.onload = function myload() {
20+ initialize();
21+ tmrID = setInterval( "interval()", 1000 );
22+}
23+function interval() {
24+ $.ajax({url : "/Log.do?mode=get&first=" + first,
25+ type : "get",
26+ success : success,
27+ error : errorMsg
28+ });
29+}
30+function success(data, status) {
31+ if(status == "success"){
32+ var new_data = eval(data);
33+ var gps_ary = new_data["data"];
34+ if(gps_ary != "") {
35+ var ary = gps_ary.split("|");
36+ for (var i in ary) {
37+ var geo = ary[i];
38+ if(!geo) {
39+ continue;
40+ }
41+ var latlon = geo.split(",");
42+ var ll = [];
43+ ll[1] = latlon[0];
44+ ll[2] = latlon[1];
45+ setMarkers(ll);
46+ }
47+ $('#test').html($('#test').html() + "<br>" + gps_ary);
48+ first = new_data["last"];
49+ }
50+ }
51+}
52+function stop_interval(){
53+ clearInterval(tmrID);
54+}
55+
56+function errorMsg(xmlObj) {
57+ alert("エラー発生 :" + xmlObj.status + "\n" + xmlObj.responseText);
58+
59+}
60+
61+
62+var geocoder;
63+
64+function initialize() {
65+ geocoder = new google.maps.Geocoder();
66+ var latlng;
67+ var zoom = 5;
68+ latlng = new google.maps.LatLng(38.662484, 139.734222);
69+
70+ var myOptions = {
71+ zoom: zoom,
72+ center: latlng,
73+ mapTypeId: google.maps.MapTypeId.ROADMAP
74+ };
75+
76+ all_map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
77+
78+ google.maps.event.addListener(all_map, 'click',function(me){
79+ codeLatLng(me.latLng);
80+ });
81+}
82+function codeLatLng(latlng) {
83+
84+ if (geocoder) {
85+ geocoder.geocode({'latLng': latlng}, function(results, status) {
86+ if (status == google.maps.GeocoderStatus.OK) {
87+ var text = latlng.lat() + ", " + latlng.lng();
88+ text += " at " + results[0]["formatted_address"];
89+ $("#geocode_info").html(text);
90+ /*
91+ $("#lat").html("<strong>Lat:</strong> "+latlng.lat());
92+ $("#lng").html("<strong>Lng:</strong> "+latlng.lng())
93+ var str = "";
94+ $.each(results, function(){
95+ str += "<h4>"+this.formatted_address+"</h4>";
96+ str += "types: "+this.types.join(", ")+"<br />";
97+ str += "address components: <ul>"
98+ $.each(this.address_components, function(){
99+ str +="<li>"+this.types.join(", ")+": "+this.long_name+"</li>";
100+ });
101+ str +="</ul>";
102+ });
103+ */
104+
105+ } else {
106+ alert("Geocoder failed due to: " + status);
107+ }
108+ });
109+ }
110+}
111+
112+function setMarkers( locations) {
113+ var app_name = "iPhone";
114+ var title = app_name;
115+ // Add markers to the map
116+
117+ // Marker sizes are expressed as a Size of X,Y
118+ // where the origin of the image (0,0) is located
119+ // in the top left of the image.
120+
121+ // Origins, anchor positions and coordinates of the marker
122+ // increase in the X direction to the right and in
123+ // the Y direction down.
124+ var image = new google.maps.MarkerImage('http://www.giveapp.jp/include/img/giveap_icon.gif',
125+ // This marker is 20 pixels wide by 32 pixels tall.
126+ new google.maps.Size(27, 27),
127+ // The origin for this image is 0,0.
128+ new google.maps.Point(0, 0),
129+ // The anchor for this image is the base of the flagpole at 0,32.
130+ new google.maps.Point(13, 20),
131+ // This image resize to 20,20
132+ new google.maps.Size(27, 27));
133+ var shadow = new google.maps.MarkerImage('./shade.png',
134+ // The shadow image is larger in the horizontal dimension
135+ // while the position and offset are the same as for the main image.
136+ new google.maps.Size(32, 20),
137+ new google.maps.Point(0,0),
138+ new google.maps.Point(16, 0));
139+ // Shapes define the clickable region of the icon.
140+ // The type defines an HTML &lt;area&gt; element 'poly' which
141+ // traces out a polygon as a series of X,Y points. The final
142+ // coordinate closes the poly by connecting to the first
143+ // coordinate.
144+ var shape = {
145+ coord: [1, 1, 1, 20, 18, 20, 18 , 1],
146+ type: 'poly'
147+ };
148+ var myLatLng = new google.maps.LatLng(locations[1], locations[2]);
149+ var marker = new google.maps.Marker({
150+ position: myLatLng,
151+ map: all_map,
152+ shadow: shadow,
153+ icon: image,
154+ shape: shape,
155+ title: title,
156+ zIndex: 3
157+ });
158+
159+}
160+
161+-->
162+</script>
163+<title>メイン画面</title>
164+
165+</head>
166+
167+<body>
168+<p>1秒のポーリング間隔で検索</p>
169+<div id="map_canvas" style="width:600px; height:550px"></div>
170+<input type="button" onclick="stop_interval()" value="stop"/>
171+<div id="test"></div>
172+</body>
173+</html>
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Show on old repository browser