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

com.bugvm.websocket.drafts.Draft_75 Maven / Gradle / Ivy

There is a newer version: 1.2.9
Show newest version
/*
 * Copyright (c) 2010-2017 Nathan Rajlich
 *
 *  Permission is hereby granted, free of charge, to any person
 *  obtaining a copy of this software and associated documentation
 *  files (the "Software"), to deal in the Software without
 *  restriction, including without limitation the rights to use,
 *  copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the
 *  Software is furnished to do so, subject to the following
 *  conditions:
 *
 *  The above copyright notice and this permission notice shall be
 *  included in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 *  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 *  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *  OTHER DEALINGS IN THE SOFTWARE.
 */

package com.bugvm.websocket.drafts;

import com.bugvm.websocket.exceptions.InvalidDataException;
import com.bugvm.websocket.exceptions.InvalidFrameException;
import com.bugvm.websocket.exceptions.InvalidHandshakeException;
import com.bugvm.websocket.exceptions.LimitExedeedException;
import com.bugvm.websocket.exceptions.NotSendableException;
import com.bugvm.websocket.framing.CloseFrame;
import com.bugvm.websocket.framing.Framedata;
import com.bugvm.websocket.framing.TextFrame;
import com.bugvm.websocket.handshake.ClientHandshake;
import com.bugvm.websocket.handshake.ClientHandshakeBuilder;
import com.bugvm.websocket.handshake.HandshakeBuilder;
import com.bugvm.websocket.handshake.ServerHandshake;
import com.bugvm.websocket.handshake.ServerHandshakeBuilder;
import com.bugvm.websocket.util.Charsetfunctions;

import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

@Deprecated
public class Draft_75 extends Draft {

	/**
	 * The byte representing CR, or Carriage Return, or \r
	 */
	public static final byte CR = ( byte ) 0x0D;
	/**
	 * The byte representing LF, or Line Feed, or \n
	 */
	public static final byte LF = ( byte ) 0x0A;
	/**
	 * The byte representing the beginning of a WebSocket text frame.
	 */
	public static final byte START_OF_FRAME = ( byte ) 0x00;
	/**
	 * The byte representing the end of a WebSocket text frame.
	 */
	public static final byte END_OF_FRAME = ( byte ) 0xFF;

	/**
	 * Is only used to detect protocol violations
	 */
	protected boolean readingState = false;

	protected List readyframes = new LinkedList();
	protected ByteBuffer currentFrame;

	private final Random reuseableRandom = new Random();

	@Override
	public HandshakeState acceptHandshakeAsClient(ClientHandshake request, ServerHandshake response ) {
		return request.getFieldValue( "WebSocket-Origin" ).equals( response.getFieldValue( "Origin" ) ) && basicAccept( response ) ? HandshakeState.MATCHED : HandshakeState.NOT_MATCHED;
	}

	@Override
	public HandshakeState acceptHandshakeAsServer( ClientHandshake handshakedata ) {
		if( handshakedata.hasFieldValue( "Origin" ) && basicAccept( handshakedata ) ) {
			return HandshakeState.MATCHED;
		}
		return HandshakeState.NOT_MATCHED;
	}

	@Override
	public ByteBuffer createBinaryFrame( Framedata framedata ) {
		if( framedata.getOpcode() != Framedata.Opcode.TEXT ) {
			throw new RuntimeException( "only text frames supported" );
		}

		ByteBuffer pay = framedata.getPayloadData();
		ByteBuffer b = ByteBuffer.allocate( pay.remaining() + 2 );
		b.put( START_OF_FRAME );
		pay.mark();
		b.put( pay );
		pay.reset();
		b.put( END_OF_FRAME );
		b.flip();
		return b;
	}

	@Override
	public List createFrames( ByteBuffer binary, boolean mask ) {
		throw new RuntimeException( "not yet implemented" );
	}

	@Override
	public List createFrames( String text, boolean mask ) {
		TextFrame frame = new TextFrame();
		frame.setPayload( ByteBuffer.wrap( Charsetfunctions.utf8Bytes( text ) ) );
		frame.setTransferemasked( mask );
		try {
			frame.isValid();
		} catch ( InvalidDataException e ) {
			throw new NotSendableException( e );
		}
		return Collections.singletonList( ( Framedata ) frame );
	}

	@Override
	public ClientHandshakeBuilder postProcessHandshakeRequestAsClient(ClientHandshakeBuilder request ) throws InvalidHandshakeException {
		request.put( "Upgrade", "WebSocket" );
		request.put( "Connection", "Upgrade" );
		if( !request.hasFieldValue( "Origin" ) ) {
			request.put( "Origin", "random" + reuseableRandom.nextInt() );
		}

		return request;
	}

	@Override
	public HandshakeBuilder postProcessHandshakeResponseAsServer(ClientHandshake request, ServerHandshakeBuilder response ) throws InvalidHandshakeException {
		response.setHttpStatusMessage( "Web Socket Protocol Handshake" );
		response.put( "Upgrade", "WebSocket" );
		response.put( "Connection", request.getFieldValue( "Connection" ) ); // to respond to a Connection keep alive
		response.put( "WebSocket-Origin", request.getFieldValue( "Origin" ) );
		String location = "ws://" + request.getFieldValue( "Host" ) + request.getResourceDescriptor();
		response.put( "WebSocket-Location", location );
		// TODO handle Sec-WebSocket-Protocol and Set-Cookie
		return response;
	}

	protected List translateRegularFrame( ByteBuffer buffer ) throws InvalidDataException {

		while( buffer.hasRemaining() ) {
			byte newestByte = buffer.get();
			if( newestByte == START_OF_FRAME ) { // Beginning of Frame
				if( readingState )
					throw new InvalidFrameException( "unexpected START_OF_FRAME" );
				readingState = true;
			} else if( newestByte == END_OF_FRAME ) { // End of Frame
				if( !readingState )
					throw new InvalidFrameException( "unexpected END_OF_FRAME" );
				// currentFrame will be null if END_OF_FRAME was send directly after
				// START_OF_FRAME, thus we will send 'null' as the sent message.
				if( this.currentFrame != null ) {
					currentFrame.flip();
					TextFrame curframe = new TextFrame();
					curframe.setPayload( currentFrame );
					readyframes.add( curframe );
					this.currentFrame = null;
					buffer.mark();
				}
				readingState = false;
			} else if( readingState ) { // Regular frame data, add to current frame buffer //TODO This code is very expensive and slow
				if( currentFrame == null ) {
					currentFrame = createBuffer();
				} else if( !currentFrame.hasRemaining() ) {
					currentFrame = increaseBuffer( currentFrame );
				}
				currentFrame.put( newestByte );
			} else {
				return null;
			}
		}

		// if no error occurred this block will be reached
		/*if( readingState ) {
			checkAlloc(currentFrame.position()+1);
		}*/

		List frames = readyframes;
		readyframes = new LinkedList();
		return frames;
	}

	@Override
	public List translateFrame( ByteBuffer buffer ) throws InvalidDataException {
		List frames = translateRegularFrame( buffer );
		if( frames == null ) {
			throw new InvalidDataException( CloseFrame.PROTOCOL_ERROR );
		}
		return frames;
	}

	@Override
	public void reset() {
		readingState = false;
		this.currentFrame = null;
	}

	@Override
	public CloseHandshakeType getCloseHandshakeType() {
		return CloseHandshakeType.NONE;
	}

	public ByteBuffer createBuffer() {
		return ByteBuffer.allocate( INITIAL_FAMESIZE );
	}

	public ByteBuffer increaseBuffer( ByteBuffer full ) throws LimitExedeedException, InvalidDataException {
		full.flip();
		ByteBuffer newbuffer = ByteBuffer.allocate( checkAlloc( full.capacity() * 2 ) );
		newbuffer.put( full );
		return newbuffer;
	}

	@Override
	public Draft copyInstance() {
		return new Draft_75();
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy