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

com.taobao.api.internal.toplink.embedded.websocket.impl.WebSocketDraft06 Maven / Gradle / Ivy

The newest version!
/*
 * The MIT License
 * 
 * Copyright (c) 2011 Takahiro Hashimoto
 * 
 * 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.taobao.api.internal.toplink.embedded.websocket.impl;

import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
//import java.util.logging.Logger;


import com.taobao.api.internal.toplink.embedded.websocket.WebSocket;
import com.taobao.api.internal.toplink.embedded.websocket.exception.WebSocketException;
import com.taobao.api.internal.toplink.embedded.websocket.frame.Frame;
import com.taobao.api.internal.toplink.embedded.websocket.frame.FrameHeader;
import com.taobao.api.internal.toplink.embedded.websocket.frame.FrameParser;
import com.taobao.api.internal.toplink.embedded.websocket.frame.draft06.BinaryFrame;
import com.taobao.api.internal.toplink.embedded.websocket.frame.draft06.CloseFrame;
import com.taobao.api.internal.toplink.embedded.websocket.frame.draft06.FrameBuilderDraft06;
import com.taobao.api.internal.toplink.embedded.websocket.frame.draft06.FrameHeaderDraft06;
import com.taobao.api.internal.toplink.embedded.websocket.frame.draft06.TextFrame;
import com.taobao.api.internal.toplink.embedded.websocket.handler.*;
import com.taobao.api.internal.toplink.embedded.websocket.handshake.Handshake;
import com.taobao.api.internal.toplink.embedded.websocket.proxy.Proxy;
import com.taobao.api.internal.toplink.embedded.websocket.util.Base64;

import static com.taobao.api.internal.toplink.embedded.websocket.exception.ErrorCode.*;



/**
 * A simple websocket client
 * 
 *  this class is implement the WebSocket Draft06 specification.
 *  
 * @see draft-ietf-hybi-thewebsocketprotocol-06
 * @author t-hashimoto
 *
 */
public class WebSocketDraft06 extends WebSocketBase {
	
	/** The logger. */
	//private static Logger logger = Logger.getLogger(WebSocketDraft06.class.getName());
	
	/** The Constant VERSION. */
	private static final int VERSION = 6;
	
	/** The extensions. */
	protected Set extensions = new HashSet();
	
	/** The server extentions. */
	protected String[] serverExtentions;
	
	/** The send frame. */
	//volatile private boolean sendFrame;

	/**
	 * Instantiates a new web socket draft06.
	 *
	 * @param url the url
     * @param origin the origin
	 * @param handler the handler
	 * @param protocols the protocols
	 * @throws WebSocketException the web socket exception
	 */
	public WebSocketDraft06(String url, String origin, WebSocketHandler handler, String... protocols) throws WebSocketException {
		super(url, origin, handler, protocols);
	}
	
    /**
   	 * Instantiates a new web socket draft06.
   	 *
   	 * @param url the url
   	 * @param handler the handler
   	 * @param protocols the protocols
   	 * @throws WebSocketException the web socket exception
   	 */
   	public WebSocketDraft06(String url, WebSocketHandler handler, String... protocols) throws WebSocketException {
   		super(url, handler, protocols);
   	}

	/**
	 * Instantiates a new web socket draft06.
	 *
	 * @param url the url
     * @param origin the origin
	 * @param proxy the proxy
	 * @param handler the handler
	 * @param protocols the protocols
	 * @throws WebSocketException the web socket exception
	 */
	public WebSocketDraft06(String url, String origin, Proxy proxy, WebSocketHandler handler, String... protocols) throws WebSocketException {
		super(url, origin, proxy, handler, protocols);
	}

    /**
   	 * Instantiates a new web socket draft06.
   	 *
   	 * @param url the url
   	 * @param proxy the proxy
   	 * @param handler the handler
   	 * @param protocols the protocols
   	 * @throws WebSocketException the web socket exception
   	 */
   	public WebSocketDraft06(String url, Proxy proxy, WebSocketHandler handler, String... protocols) throws WebSocketException {
   		super(url, proxy, handler, protocols);
   	}

	/* (non-Javadoc)
	 * @see jp.a840.websocket.impl.WebSocketBase#initializePipeline(jp.a840.websocket.handler.WebSocketPipeline)
	 */
	@Override
	protected void initializePipeline(WebSocketPipeline pipeline) throws WebSocketException {
		pipeline.addStreamHandler(new MaskDraft06FrameStreamHandler());
		super.initializePipeline(pipeline);
		// Add base response handler
		pipeline.addStreamHandler(new StreamHandlerAdapter() {
			public void nextDownstreamHandler(WebSocket ws, ByteBuffer buffer,
					Frame frame, StreamHandlerChain chain) throws WebSocketException {
				if(frame instanceof CloseFrame){
					if(state == State.WAIT){
						chain.nextUpstreamHandler(ws, null, frame);
					}
					transitionTo(State.CLOSED);
				} else {
					WebSocketDraft06.this.handler.onMessage(ws, frame);
				}
			}

			public void nextHandshakeDownstreamHandler(WebSocket ws, ByteBuffer buffer,
					StreamHandlerChain chain) throws WebSocketException {
				// set response status
				responseHeader = getHandshake().getResponseHeader();
				responseStatus = getHandshake().getResponseStatus();
				transitionTo(State.WAIT);
				// HANDSHAKE -> WAIT
				WebSocketDraft06.this.handler.onOpen(WebSocketDraft06.this);
			}
		});		

	}
	
	/* (non-Javadoc)
	 * @see jp.a840.websocket.impl.WebSocketBase#newHandshakeInstance()
	 */
	@Override
	protected Handshake newHandshakeInstance(){
		return new Handshake() {
			/**
			 * Create a handshake requtest
			 * 
			 * 
			 * Sample (Draft06)
			 * client => server
			 *   GET /chat HTTP/1.1
			 *   Host: server.example.com
			 *   Upgrade: websocket
			 *   Connection: Upgrade
			 *   Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
			 *   Sec-WebSocket-Origin: http://example.com
			 *   Sec-WebSocket-Protocol: chat, superchat
			 *   Sec-WebSocket-Version:6
			 * 
* */ @Override public ByteBuffer createHandshakeRequest() throws WebSocketException { // Send GET request to server StringBuilder sb = new StringBuilder(); sb.append("GET " + path + " HTTP/1.1\r\n"); addHeader(sb, "Host", endpointAddress.getHostName()); addHeader(sb, "Upgrade", "websocket"); addHeader(sb, "Connection", "Upgrade"); addHeader(sb, "Sec-WebSocket-Key", generateWebSocketKey()); if (origin != null) { addHeader(sb, "Sec-WebSocket-Origin", origin); } if (protocols != null && protocols.length > 0) { addHeader(sb, "Sec-WebSocket-Protocol", join(",", protocols)); } // TODO Sec-WebSocket-Extensions if(extensions.size() > 0){ addHeader(sb, "Sec-WebSocket-Extensions", join(",", extensions)); } addHeader(sb, "Sec-WebSocket-Version", String.valueOf(getWebSocketVersion())); sb.append("\r\n"); return ByteBuffer.wrap(sb.toString().getBytes()); } /** * check handshake response * *
			 * server => client
			 * HTTP/1.1 101 Switching Protocols
			 * Upgrade: websocket
			 * Connection: Upgrade
			 * Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
			 * Sec-WebSocket-Protocol: chat
			 * 
* * @param buffer */ @Override protected boolean parseHandshakeResponseHeader(ByteBuffer buffer) throws WebSocketException { if(!super.parseHandshakeResponseHeader(buffer)){ return false; } if(!"websocket".equalsIgnoreCase(this.getResponseHeader().getHeaderValue("upgrade"))){ throw new WebSocketException(E3600, responseHeader.getHeaderValue("upgrade")); } if(!"upgrade".equalsIgnoreCase(this.getResponseHeader().getHeaderValue("connection"))){ throw new WebSocketException(E3601, responseHeader.getHeaderValue("connection")); } if(!this.getResponseHeader().containsHeader("sec-websocket-accept")){ throw new WebSocketException(E3602); } String protocolStr = this.getResponseHeader().getHeaderValue("sec-websocket-protocol"); if(protocolStr != null){ serverProtocols = protocolStr.split(","); } String extensionsStr = this.getResponseHeader().getHeaderValue("sec-websocket-extensions"); if(extensionsStr != null){ serverExtentions = extensionsStr.split(","); } return true; } }; } /** * Generate web socket key. * * @return the string */ private String generateWebSocketKey(){ try{ MessageDigest md = MessageDigest.getInstance("SHA-1"); return Base64.encodeToString(md.digest(UUID.randomUUID().toString().getBytes()), false); }catch(NoSuchAlgorithmException e){ return null; } } /* (non-Javadoc) * @see jp.a840.websocket.impl.WebSocketBase#newFrameParserInstance() */ @Override protected FrameParser newFrameParserInstance() { return new FrameParser() { private FrameHeaderDraft06 previousCreatedFrameHeader; @Override protected FrameHeader createFrameHeader(ByteBuffer chunkData) { FrameHeaderDraft06 header = FrameBuilderDraft06.createFrameHeader(chunkData, previousCreatedFrameHeader); if(!header.isContinuation()){ previousCreatedFrameHeader = header; } return header; } @Override protected Frame createFrame(FrameHeader h, byte[] bodyData) { return FrameBuilderDraft06.createFrame((FrameHeaderDraft06)h, bodyData); } }; } @Override public Frame createFrame(byte[] bytes) throws WebSocketException { return new BinaryFrame(bytes); } /* (non-Javadoc) * @see jp.a840.websocket.impl.WebSocketBase#createFrame(java.lang.String) */ @Override public Frame createFrame(String str) throws WebSocketException { return new TextFrame(str); } /* (non-Javadoc) * @see jp.a840.websocket.impl.WebSocketBase#getWebSocketVersion() */ @Override protected int getWebSocketVersion() { return VERSION; } /** * Adds the extension. * * @param extension the extension */ public void addExtension(String extension){ extensions.add(extension); } /** * Removes the extension. * * @param extension the extension */ public void removeExtension(String extension){ extensions.remove(extension); } /* (non-Javadoc) * @see jp.a840.websocket.impl.WebSocketBase#closeWebSocket() */ @Override protected void closeWebSocket() throws WebSocketException { transitionTo(State.CLOSING); pipeline.sendUpstream(this, null, new CloseFrame()); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy