public enum Role {
	CLIENT, SERVER
} public class IncompleteHandshakeException extends RuntimeException {

	private static final long serialVersionUID = 7906596804233893092L;
	private int newsize;

	public IncompleteHandshakeException() {
		this.newsize = 0;
	}

	public IncompleteHandshakeException(int newsize) {
		this.newsize = newsize;
	}

	public int getPreferedSize() {
		return newsize;
	}

} public class InvalidDataException extends Exception {
	/**
	 * Serializable
	 */
	private static final long serialVersionUID = 3731842424390998726L;

	private int closecode;

	public InvalidDataException(int closecode) {
		this.closecode = closecode;
	}

	public InvalidDataException(int closecode, String s) {
		super(s);
		this.closecode = closecode;
	}

	public InvalidDataException(int closecode, String s, Throwable t) {
		super(s, t);
		this.closecode = closecode;
	}

	public InvalidDataException(int closecode, Throwable t) {
		super(t);
		this.closecode = closecode;
	}

	public int getCloseCode() {
		return closecode;
	}

} public class InvalidHandshakeException extends InvalidDataException {

	/**
	 * Serializable
	 */
	private static final long serialVersionUID = -1426533877490484964L;

	public InvalidHandshakeException() {
		super(CloseFrame.PROTOCOL_ERROR);
	}

	public InvalidHandshakeException(String arg0) {
		super(CloseFrame.PROTOCOL_ERROR, arg0);
	}

	public InvalidHandshakeException(String arg0, Throwable arg1) {
		super(CloseFrame.PROTOCOL_ERROR, arg0, arg1);
	}

	public InvalidHandshakeException(Throwable arg0) {
		super(CloseFrame.PROTOCOL_ERROR, arg0);
	}

} public class LimitExedeedException extends InvalidDataException {

	/**
	 * Serializable
	 */
	private static final long serialVersionUID = 6908339749836826785L;

	public LimitExedeedException() {
		super(CloseFrame.TOOBIG);
	}

	public LimitExedeedException(String s) {
		super(CloseFrame.TOOBIG, s);
	}

} public interface CloseFrame extends Framedata {
	/**
	 * indicates a normal closure, meaning whatever purpose the connection was
	 * established for has been fulfilled.
	 */
	public static final int NORMAL = 1000;
	/**
	 * 1001 indicates that an endpoint is "going away", such as a server going
	 * down, or a browser having navigated away from a page.
	 */
	public static final int GOING_AWAY = 1001;
	/**
	 * 1002 indicates that an endpoint is terminating the connection due to a
	 * protocol error.
	 */
	public static final int PROTOCOL_ERROR = 1002;
	/**
	 * 1003 indicates that an endpoint is terminating the connection because it
	 * has received a type of data it cannot accept (e.g. an endpoint that
	 * understands only text data MAY send this if it receives a binary
	 * message).
	 */
	public static final int REFUSE = 1003;
	/* 1004: Reserved. The specific meaning might be defined in the future. */
	/**
	 * 1005 is a reserved value and MUST NOT be set as a status code in a Close
	 * control frame by an endpoint. It is designated for use in applications
	 * expecting a status code to indicate that no status code was actually
	 * present.
	 */
	public static final int NOCODE = 1005;
	/**
	 * 1006 is a reserved value and MUST NOT be set as a status code in a Close
	 * control frame by an endpoint. It is designated for use in applications
	 * expecting a status code to indicate that the connection was closed
	 * abnormally, e.g. without sending or receiving a Close control frame.
	 */
	public static final int ABNORMAL_CLOSE = 1006;
	/**
	 * 1007 indicates that an endpoint is terminating the connection because it
	 * has received data within a message that was not consistent with the type
	 * of the message (e.g., non-UTF-8 [RFC3629] data within a text message).
	 */
	public static final int NO_UTF8 = 1007;
	/**
	 * 1008 indicates that an endpoint is terminating the connection because it
	 * has received a message that violates its policy. This is a generic status
	 * code that can be returned when there is no other more suitable status
	 * code (e.g. 1003 or 1009), or if there is a need to hide specific details
	 * about the policy.
	 */
	public static final int POLICY_VALIDATION = 1008;
	/**
	 * 1009 indicates that an endpoint is terminating the connection because it
	 * has received a message which is too big for it to process.
	 */
	public static final int TOOBIG = 1009;
	/**
	 * 1010 indicates that an endpoint (client) is terminating the connection
	 * because it has expected the server to negotiate one or more extension,
	 * but the server didn't return them in the response message of the
	 * WebSocket handshake. The list of extensions which are needed SHOULD
	 * appear in the /reason/ part of the Close frame. Note that this status
	 * code is not used by the server, because it can fail the WebSocket
	 * handshake instead.
	 */
	public static final int EXTENSION = 1010;
	/**
	 * 1011 indicates that a server is terminating the connection because it
	 * encountered an unexpected condition that prevented it from fulfilling the
	 * request.
	 **/
	public static final int UNEXPECTED_CONDITION = 1011;
	/**
	 * 1015 is a reserved value and MUST NOT be set as a status code in a Close
	 * control frame by an endpoint. It is designated for use in applications
	 * expecting a status code to indicate that the connection was closed due to
	 * a failure to perform a TLS handshake (e.g., the server certificate can't
	 * be verified).
	 **/
	public static final int TLS_ERROR = 1015;

	/** The connection had never been established */
	public static final int NEVER_CONNECTED = -1;
	public static final int BUGGYCLOSE = -2;
	public static final int FLASHPOLICY = -3;

	public int getCloseCode() throws InvalidFrameException;

	public String getMessage() throws InvalidDataException;
} public interface Framedata {
	public enum Opcode {
		CONTINUOUS, TEXT, BINARY, PING, PONG, CLOSING
		// more to come
	}

	public abstract void append(Framedata nextframe)
			throws InvalidFrameException;

	public Opcode getOpcode();

	public ByteBuffer getPayloadData();// TODO the separation of the application
										// data and the extension data is yet to
										// be done

	public boolean getTransfereMasked();

	public boolean isFin();
} public enum Opcode {
	CONTINUOUS, TEXT, BINARY, PING, PONG, CLOSING
	// more to come
} public class FramedataImpl1 implements FrameBuilder {
	protected static byte[] emptyarray = {};
	protected boolean fin;
	protected Opcode optcode;
	private ByteBuffer unmaskedpayload;
	protected boolean transferemasked;

	public FramedataImpl1() {
	}

	/**
	 * Helper constructor which helps to create "echo" frames. The new object
	 * will use the same underlying payload data.
	 **/
	public FramedataImpl1(Framedata f) {
		fin = f.isFin();
		optcode = f.getOpcode();
		unmaskedpayload = f.getPayloadData();
		transferemasked = f.getTransfereMasked();
	}

	public FramedataImpl1(Opcode op) {
		this.optcode = op;
		unmaskedpayload = ByteBuffer.wrap(emptyarray);
	}

	@Override
	public void append(Framedata nextframe) throws InvalidFrameException {
		ByteBuffer b = nextframe.getPayloadData();
		if (unmaskedpayload == null) {
			unmaskedpayload = ByteBuffer.allocate(b.remaining());
			b.mark();
			unmaskedpayload.put(b);
			b.reset();
		} else {
			b.mark();
			unmaskedpayload.position(unmaskedpayload.limit());
			unmaskedpayload.limit(unmaskedpayload.capacity());

			if (b.remaining() > unmaskedpayload.remaining()) {
				ByteBuffer tmp = ByteBuffer.allocate(b.remaining()
						+ unmaskedpayload.capacity());
				unmaskedpayload.flip();
				tmp.put(unmaskedpayload);
				tmp.put(b);
				unmaskedpayload = tmp;

			} else {
				unmaskedpayload.put(b);
			}
			unmaskedpayload.rewind();
			b.reset();
		}
		fin = nextframe.isFin();
	}

	@Override
	public Opcode getOpcode() {
		return optcode;
	}

	@Override
	public ByteBuffer getPayloadData() {
		return unmaskedpayload;
	}

	@Override
	public boolean getTransfereMasked() {
		return transferemasked;
	}

	@Override
	public boolean isFin() {
		return fin;
	}

	@Override
	public void setFin(boolean fin) {
		this.fin = fin;
	}

	@Override
	public void setOptcode(Opcode optcode) {
		this.optcode = optcode;
	}

	@Override
	public void setPayload(ByteBuffer payload) throws InvalidDataException {
		unmaskedpayload = payload;
	}

	@Override
	public void setTransferemasked(boolean transferemasked) {
		this.transferemasked = transferemasked;
	}

	@Override
	public String toString() {
		return "Framedata{ optcode:"
				+ getOpcode()
				+ ", fin:"
				+ isFin()
				+ ", payloadlength:[pos:"
				+ unmaskedpayload.position()
				+ ", len:"
				+ unmaskedpayload.remaining()
				+ "], payload:"
				+ Arrays.toString(Charsetfunctions.utf8Bytes(new String(
						unmaskedpayload.array()))) + "/"+new String(
								unmaskedpayload.array())+"}";
	}

}
 public interface ClientHandshakeBuilder extends HandshakeBuilder,
		ClientHandshake {
	public void setResourceDescriptor(String resourceDescriptor);
} public interface HandshakeBuilder extends Handshakedata {
	public abstract void put(String name, String value);

	public abstract void setContent(byte[] content);
} public class HandshakeImpl1Client extends HandshakedataImpl1 implements
		ClientHandshakeBuilder {
	private String resourceDescriptor = "*";

	public HandshakeImpl1Client() {
	}

	@Override
	public String getResourceDescriptor() {
		return resourceDescriptor;
	}

	@Override
	public void setResourceDescriptor(String resourceDescriptor)
			throws IllegalArgumentException {
		if (resourceDescriptor == null)
			throw new IllegalArgumentException(
					"http resource descriptor must not be null");
		this.resourceDescriptor = resourceDescriptor;
	}
} public class HandshakeImpl1Server extends HandshakedataImpl1 implements
		ServerHandshakeBuilder {
	private short httpstatus;
	private String httpstatusmessage;

	public HandshakeImpl1Server() {
	}

	@Override
	public short getHttpStatus() {
		return httpstatus;
	}

	@Override
	public String getHttpStatusMessage() {
		return httpstatusmessage;
	}

	@Override
	public void setHttpStatus(short status) {
		httpstatus = status;
	}

	@Override
	public void setHttpStatusMessage(String message) {
		this.httpstatusmessage = message;
	}

} public interface Handshakedata {
	public byte[] getContent();

	public String getFieldValue(String name);

	public boolean hasFieldValue(String name);

	public Iterator<String> iterateHttpFields();
} public interface ServerHandshake extends Handshakedata {
	public short getHttpStatus();

	public String getHttpStatusMessage();
} public class Charsetfunctions {

	public static CodingErrorAction codingErrorAction = CodingErrorAction.REPORT;

	/*
	 * @return ASCII encoding in bytes
	 */
	public static byte[] asciiBytes(String s) {
		try {
			return s.getBytes("ASCII");
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
	}

	public static void main(String[] args) throws InvalidDataException {
		stringUtf8(utf8Bytes("\0"));
		stringAscii(asciiBytes("\0"));
	}

	public static String stringAscii(byte[] bytes) {
		return stringAscii(bytes, 0, bytes.length);
	}

	public static String stringAscii(byte[] bytes, int offset, int length) {
		try {
			return new String(bytes, offset, length, "ASCII");
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
	}

	public static String stringUtf8(byte[] bytes) throws InvalidDataException {
		return stringUtf8(ByteBuffer.wrap(bytes));
	}

	/*
	 * public static String stringUtf8( byte[] bytes, int off, int length )
	 * throws InvalidDataException { CharsetDecoder decode = Charset.forName(
	 * "UTF8" ).newDecoder(); decode.onMalformedInput( codingErrorAction );
	 * decode.onUnmappableCharacter( codingErrorAction ); //decode.replaceWith(
	 * "X" ); String s; try { s = decode.decode( ByteBuffer.wrap( bytes, off,
	 * length ) ).toString(); } catch ( CharacterCodingException e ) { throw new
	 * InvalidDataException( CloseFrame.NO_UTF8, e ); } return s; }
	 */

	public static String stringUtf8(ByteBuffer bytes)
			throws InvalidDataException {
		CharsetDecoder decode = Charset.forName("UTF8").newDecoder();
		decode.onMalformedInput(codingErrorAction);
		decode.onUnmappableCharacter(codingErrorAction);
		// decode.replaceWith( "X" );
		String s;
		try {
			bytes.mark();
			s = decode.decode(bytes).toString();
			bytes.reset();
		} catch (CharacterCodingException e) {
			throw new InvalidDataException(CloseFrame.NO_UTF8, e);
		}
		return s;
	}

	/*
	 * @return UTF-8 encoding in bytes
	 */
	public static byte[] utf8Bytes(String s) {
		try {
			return s.getBytes("UTF8");
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
	}

}
import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import org.java_websocket.WebSocket.Role;
import org.java_websocket.exceptions.IncompleteHandshakeException;
import org.java_websocket.exceptions.InvalidDataException;
import org.java_websocket.exceptions.InvalidHandshakeException;
import org.java_websocket.exceptions.LimitExedeedException;
import org.java_websocket.framing.CloseFrame;
import org.java_websocket.framing.FrameBuilder;
import org.java_websocket.framing.Framedata;
import org.java_websocket.framing.Framedata.Opcode;
import org.java_websocket.framing.FramedataImpl1;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.handshake.ClientHandshakeBuilder;
import org.java_websocket.handshake.HandshakeBuilder;
import org.java_websocket.handshake.HandshakeImpl1Client;
import org.java_websocket.handshake.HandshakeImpl1Server;
import org.java_websocket.handshake.Handshakedata;
import org.java_websocket.handshake.ServerHandshake;
import org.java_websocket.handshake.ServerHandshakeBuilder;
import org.java_websocket.util.Charsetfunctions;
package org.java_websocket.drafts;



/**
 * Base class for everything of a websocket specification which is not common
 * such as the way the handshake is read or frames are transfered.
 **/
public abstract class Draft {

	public enum CloseHandshakeType {
		NONE, ONEWAY, TWOWAY
	}

	public enum HandshakeState {
		/** Handshake matched this Draft successfully */
		MATCHED,
		/** Handshake is does not match this Draft */
		NOT_MATCHED
	}

	public static int MAX_FAME_SIZE = 1000 * 1;
	public static int INITIAL_FAMESIZE = 64;

	public static final byte[] FLASH_POLICY_REQUEST = Charsetfunctions
			.utf8Bytes("<policy-file-request/>\0");

	public static ByteBuffer readLine(ByteBuffer buf) {
		ByteBuffer sbuf = ByteBuffer.allocate(buf.remaining());
		byte prev = '0';
		byte cur = '0';
		while (buf.hasRemaining()) {
			prev = cur;
			cur = buf.get();
			sbuf.put(cur);
			if (prev == (byte) '\r' && cur == (byte) '\n') {
				sbuf.limit(sbuf.position() - 2);
				sbuf.position(0);
				return sbuf;

			}
		}
		// ensure that there wont be any bytes skipped
		buf.position(buf.position() - sbuf.position());
		return null;
	}

	public static String readStringLine(ByteBuffer buf) {
		ByteBuffer b = readLine(buf);
		return b == null ? null : Charsetfunctions.stringAscii(b.array(), 0,
				b.limit());
	}

	public static HandshakeBuilder translateHandshakeHttp(ByteBuffer buf,
			Role role) throws InvalidHandshakeException,
			IncompleteHandshakeException {
		HandshakeBuilder handshake;

		String line = readStringLine(buf);
		if (line == null)
			throw new IncompleteHandshakeException(buf.capacity() + 128);

		String[] firstLineTokens = line.split(" ", 3);// eg. HTTP/1.1 101
														// Switching the
														// Protocols
		if (firstLineTokens.length != 3) {
			throw new InvalidHandshakeException();
		}

		if (role == Role.CLIENT) {
			// translating/parsing the response from the SERVER
			handshake = new HandshakeImpl1Server();