// // ======================================================================== // Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // // You may elect to redistribute this code under either of these licenses. // ======================================================================== // package org.eclipse.jetty.websocket.server.helper; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketAddress; import java.net.URI; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.TypeUtil; import org.junit.Assert; public class SafariD00 { private URI uri; private SocketAddress endpoint; private Socket socket; private OutputStream out; private InputStream in; public SafariD00(URI uri) { this.uri = uri; this.endpoint = new InetSocketAddress(uri.getHost(),uri.getPort()); } /** * Open the Socket to the destination endpoint and * * @return the open java Socket. * @throws IOException on test failure */ public Socket connect() throws IOException { socket = new Socket(); socket.connect(endpoint,1000); out = socket.getOutputStream(); in = socket.getInputStream(); return socket; } public void disconnect() throws IOException { socket.close(); } /** * Issue an Http websocket (Draft-0) upgrade request using the Safari particulars. * * @throws IOException on test failure */ public void issueHandshake() throws IOException { StringBuilder req = new StringBuilder(); req.append("GET ").append(uri.getPath()).append(" HTTP/1.1\r\n"); req.append("Upgrade: WebSocket\r\n"); req.append("Connection: Upgrade\r\n"); req.append("Host: ").append(uri.getHost()).append(":").append(uri.getPort()).append("\r\n"); req.append("Origin: http://www.google.com/\r\n"); req.append("Sec-WebSocket-Key1: 15{ft :6@87 0 M 5 c901\r\n"); req.append("Sec-WebSocket-Key2: 3? C;7~0 8 \" 3 2105 6 `_ {\r\n"); req.append("\r\n"); // System.out.printf("--- Request ---%n%s",req); byte reqBytes[] = req.toString().getBytes(StandardCharsets.UTF_8); byte hixieBytes[] = TypeUtil.fromHexString("e739617916c9daf3"); byte buf[] = new byte[reqBytes.length + hixieBytes.length]; System.arraycopy(reqBytes,0,buf,0,reqBytes.length); System.arraycopy(hixieBytes,0,buf,reqBytes.length,hixieBytes.length); // Send HTTP GET Request (with hixie bytes) out.write(buf,0,buf.length); out.flush(); // Read HTTP 101 Upgrade / Handshake Response InputStreamReader reader = new InputStreamReader(in); BufferedReader br = new BufferedReader(reader); socket.setSoTimeout(5000); boolean foundEnd = false; String line; while (!foundEnd) { line = br.readLine(); // System.out.printf("RESP: %s%n",line); Assert.assertThat(line, notNullValue()); if (line.length() == 0) { foundEnd = true; } } // Read expected handshake hixie bytes byte hixieHandshakeExpected[] = TypeUtil.fromHexString("c7438d956cf611a6af70603e6fa54809"); byte hixieHandshake[] = new byte[hixieHandshakeExpected.length]; int readLen = in.read(hixieHandshake,0,hixieHandshake.length); Assert.assertThat("Read hixie handshake bytes",readLen,is(hixieHandshake.length)); } public void sendMessage(String... msgs) throws IOException { int len = 0; for (String msg : msgs) { len += (msg.length() + 2); } ByteBuffer buf = ByteBuffer.allocate(len); for (String msg : msgs) { buf.put((byte)0x00); buf.put(msg.getBytes(StandardCharsets.UTF_8)); buf.put((byte)0xFF); } BufferUtil.writeTo(buf,out); out.flush(); } }