All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gov.nist.javax.sip.stack.WebSocketHttpHandshake Maven / Gradle / Ivy

There is a newer version: 1.3.0-91
Show newest version
/*
 * Conditions Of Use
 *
 * This software was developed by employees of the National Institute of
 * Standards and Technology (NIST), an agency of the Federal Government.
 * Pursuant to title 15 Untied States Code Section 105, works of NIST
 * employees are not subject to copyright protection in the United States
 * and are considered to be in the public domain.  As a result, a formal
 * license is not needed to use the software.
 *
 * This software is provided by NIST as a service and is expressly
 * provided "AS IS."  NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
 * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
 * AND DATA ACCURACY.  NIST does not warrant or make any representations
 * regarding the use of the software or the results thereof, including but
 * not limited to the correctness, accuracy, reliability or usefulness of
 * the software.
 *
 * Permission to use this software is contingent upon your acceptance
 * of the terms of this agreement
 *
 * .
 *
 */
package android.gov.nist.javax.sip.stack;

import android.gov.nist.core.CommonLogger;
import android.gov.nist.core.LogLevels;
import android.gov.nist.core.StackLogger;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;

/**
 * Websocket handshake rev 13 and rev 8
 *
 */
public class WebSocketHttpHandshake {

	private static StackLogger logger = CommonLogger
			.getLogger(WebSocketHttpHandshake.class);
	
	private HashMap headers = new HashMap();

	public byte[] createHttpResponse(String request) throws Exception {
		
		if(logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) {
			logger.logDebug("Request=" + request);
		}
		InputStream is = new ByteArrayInputStream(request.getBytes());

		boolean isSecure = false;

		String line = readLine(is);

		if (line == null) {
			return null;
		}

		String[] parts = line.split(" ");
		if (parts.length >= 3) {
			headers.put("ctx", parts[1]);
		}
		while (!line.isEmpty()) {
			line = readLine(is);

			if (line == null) {
				continue;
			}

			if (line.isEmpty()) {
				continue;
			}

			parts = line.split(":", 2);
			if (parts.length != 2) {
				continue;
			}
			if (parts[0].toLowerCase().startsWith("sec-websocket-key")) {
				isSecure = true;
			}
			headers.put(parts[0].trim(), parts[1].trim());
		}
		if (isSecure) {
			byte[] key3 = new byte[8];
			is.read(key3);
		}

		//answer the handshake
		StringBuilder sb = new StringBuilder();
		String lineSeparator = "\r\n";
		sb.append("HTTP/1.1 101 Web Socket Protocol Handshake").append("\r\n");
		sb.append("Upgrade: WebSocket").append(lineSeparator);
		sb.append("Connection: Upgrade").append(lineSeparator);
		if (isSecure) {
			sb.append("Sec-");
		}

		sb.append("WebSocket-Origin: ").append(headers.get("Origin")).append(lineSeparator);


		if (isSecure) {
			sb.append("Sec-");
		}
		sb.append("WebSocket-Location: ws://").append(headers.get("Host")).
		append(headers.get("ctx")).append(lineSeparator);

		sb.append("Sec-WebSocket-Accept: ").append(computeRev13Response(headers.get("Sec-WebSocket-Key"))).append(lineSeparator);
		//sb.append("myheader: nothing");
		//.append("Sec-WebSocket-Protocol: chat")
		//        .append("Server: Kaazing Gateway\n" + 
		//        		"Date: Tue, 21 Aug 2012 00:59:35 GMT\n" + 
		//        		"Access-Control-Allow-Origin: http://www.websocket.org\n" + 
		//        		"Access-Control-Allow-Credentials: true\n" + 
		//        		"Access-Control-Allow-Headers: content-type\n" + 
		//        		"Access-Control-Allow-Headers: authorization\n" + 
		//        		"Access-Control-Allow-Headers: x-websocket-extensions\n" + 
		//        		"Access-Control-Allow-Headers: x-websocket-version\n" + 
		//        		"Access-Control-Allow-Headers: x-websocket-protocol\n");
		if (headers.get("Protocol") != null) {
			if (isSecure) {
				sb.append("Sec-");
			}
			sb.append("Protocol: ").append(headers.get("Protocol")).append(lineSeparator);
		}

		if (headers.get("Sec-WebSocket-Protocol") != null) {
			sb.append("Sec-WebSocket-Protocol: ").append(headers.get("Sec-WebSocket-Protocol")).append(lineSeparator);
		}
		sb.append(lineSeparator);

		String response = sb.toString();

		if(logger.isLoggingEnabled(LogLevels.TRACE_DEBUG)) {
			logger.logDebug("Response=" + response);
		}
		byte[] output = sb.toString().getBytes();

		return output;
	}

	public static String computeRev13Response(String key) throws IOException {
		key = key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
		MessageDigest md = null;
		try {
			md = MessageDigest.getInstance("SHA1");
			md.reset();
		} catch (NoSuchAlgorithmException ex) {
			// log.log(Level.SEVERE, "MD5 Algorithm not found", ex);
			ex.printStackTrace();
		}
		byte[] digest = md.digest(key.getBytes());
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
                String encodeBase64String = Base64.encodeBytes(digest);
		return encodeBase64String;
		
	}


	private String readLine(InputStream is) throws IOException {
		StringBuilder sb = new StringBuilder();

		int cr = '\r';
		int nl = '\n';

		boolean gotcr = false;

		while (true) {
			int input = is.read();

			if (input == -1) {
				return null;
			}

			if (input == cr) {
				gotcr = true;
				continue;
			}
			if (input == nl && gotcr) {
				break;
			} else if (input == nl) {
				//we do this only because the protocol
				//tells ut that there must be a cr before the nl.
				return null;
			}
			sb.append((char) input);
		}
		return sb.toString();
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy