Search code examples
androidwebsocketjava-websockethandshaking

create a websocket handshake using android as server and a browser as client


i would like to be able to use the browser as an editor for sms on my android device (something like https://www.mysms.com). so i started to write an android app which acts as socket server and use the browser as client (such as http://www.websocket.org/echo.html). i was able to reach my app from that client and get messages from it, but im am having now problems with the WebSocket handshake (Sec-WebSocket-Key etc).

EDIT:

i followed this tutorial to write my android server: http://android-er.blogspot.co.at/2014/02/android-sercerclient-example-server.html

when i tried to reach that server from http://www.websocket.org/echo.html i got this js error: Error during WebSocket handshake: Invalid status line

EDIT:

so i added the header with the encoded key for the Sec-WebSocket-Accept: line

// get the key from the input 
InputStream inputStream = hostThreadSocket.getInputStream();
            String line = "";
            BufferedReader reader = null;
            try {
                reader = new BufferedReader(new InputStreamReader(inputStream));
                while ((line = reader.readLine()) != null) {
                    if(line.contains("Sec-WebSocket-Key:")){ // stop then the line containing the key is found
                        break;
                    }
                }

            } catch (IOException e) {
            }
String key = line.replace("Sec-WebSocket-Key:", "");

and encode the result with following method:

static String encodeString(String input)  {

    MessageDigest digest = null;
    try {
        digest = MessageDigest.getInstance("SHA-1");
        byte[] inputBytes = input.getBytes();
        byte[] hashBytes = digest.digest(inputBytes);
        return  Base64.encodeToString(hashBytes, Base64.DEFAULT);
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    return "";
}

and pass the header like following:

 String key = line.replace("Sec-WebSocket-Key:", "");
            key = key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
            key = encodeString(key).replace("\n", "");;

            String header = "HTTP/1.1 101 Switching Protocols\r\n" +
                    "Upgrade: websocket \r\n" +
                    "Connection: Upgrade \r\n" +
                    "Sec-WebSocket-Accept: " + key + "\r\n"+
                    "Sec-WebSocket-Protocol: chat\r\n\r\n" + msgReply;
            printStream.print(header);
            printStream.close();

the response header looks now like this:

Connection:Upgrade\r\n 
Sec-WebSocket-Accept:/Qg4DR68UCCo9VKy4vbDgswCU8Y=\r\n
Upgrade:websocket\r\n

but still i receive the error: failed: Error during WebSocket handshake: Incorrect 'Sec-WebSocket-Accept' header value


Solution

  • i finally could make the websocket handshake. i dont know exactly what changes braught me to the success, but this is the working code:

    InputStream inputStream = hostThreadSocket.getInputStream();
                String line = "";
                BufferedReader reader = null;
                try {
                    reader = new BufferedReader(new InputStreamReader(inputStream));
                    while ((line = reader.readLine()) != null) {
                        if (line.contains("Sec-WebSocket-Key: ")) { // check if its the header-line containing the websocket key
                            break;
                        }
                    }
                } catch (IOException e) {
                    Log.e(TAG_TEST, e.getMessage(), e);
                }
    
                Matcher matcher = pattern.matcher(line); // with pattern "Sec-WebSocket-Key:[ ]*([^\r^\n]*)" to parse the key out of the line
                boolean matches = matcher.matches();
                String key = matcher.group(1);
                key = key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; // adding the "magic string"
                key = encodeString(key);
    
                String header = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" +                       
                        "Upgrade: websocket\r\n" +
                        "Connection: Upgrade\r\n" +
                        "Sec-WebSocket-Accept:" + key + "\r\n\r\n";
                printStream.print(header);
    

    and this is the method i which encodes the key

    static String encodeString(String input) {
        MessageDigest digest = null;
        try {
            digest = MessageDigest.getInstance("SHA-1");
            byte[] inputBytes = input.getBytes();
            byte[] hashBytes = digest.digest(inputBytes);
            return Base64.encodeToString(hashBytes, Base64.NO_WRAP);
        } catch (NoSuchAlgorithmException e) {
            Log.e(TAG_TEST, e.getMessage(), e);
        }
        return "";
    }