Java Code Examples for org.apache.mina.core.session.IoSession#containsAttribute()

The following examples show how to use org.apache.mina.core.session.IoSession#containsAttribute() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: CompressionFilter.java    From neoscada with Eclipse Public License 1.0 6 votes vote down vote up
@Override
protected Object doFilterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest)
        throws IOException {
    if (!compressOutbound) {
        return null;
    }

    if (session.containsAttribute(DISABLE_COMPRESSION_ONCE)) {
        // Remove the marker attribute because it is temporary.
        session.removeAttribute(DISABLE_COMPRESSION_ONCE);
        return null;
    }

    Zlib deflater = (Zlib) session.getAttribute(DEFLATER);
    if (deflater == null) {
        throw new IllegalStateException();
    }

    IoBuffer inBuffer = (IoBuffer) writeRequest.getMessage();
    if (!inBuffer.hasRemaining()) {
        // Ignore empty buffers
        return null;
    } else {
        return deflater.deflate(inBuffer);
    }
}
 
Example 2
Source File: BaseRTMPHandler.java    From red5-server-common with Apache License 2.0 6 votes vote down vote up
/** {@inheritDoc} */
public void connectionClosed(RTMPConnection conn) {
    log.debug("connectionClosed: {}", conn.getSessionId());
    if (conn.getStateCode() != RTMP.STATE_DISCONNECTED) {
        // inform any callbacks for pending calls that the connection is closed
        conn.sendPendingServiceCallsCloseError();
        // close the connection
        if (conn.getStateCode() != RTMP.STATE_DISCONNECTING) {
            conn.close();
        }
        // set as disconnected
        conn.setStateCode(RTMP.STATE_DISCONNECTED);
    }
    IoSession session = conn.getIoSession();
    if (session != null && session.containsAttribute(RTMPConnection.RTMP_CONN_MANAGER)) {
        @SuppressWarnings("unchecked")
        IConnectionManager<RTMPConnection> connManager = (IConnectionManager<RTMPConnection>) ((WeakReference<?>) session.getAttribute(RTMPConnection.RTMP_CONN_MANAGER)).get();
        if (connManager != null) {
            connManager.removeConnection(conn.getSessionId());
        } else {
            log.debug("Connection manager was not found in the session");
        }
    }
    log.trace("connectionClosed: {}", conn);
}
 
Example 3
Source File: DefaultPreprocessor.java    From sailfish-core with Apache License 2.0 6 votes vote down vote up
protected void addMessageTimeField(IMessage message, IMessageStructure msgStructure, IoSession session) {
    try {
        String secondsField = getSecondsField();
        String nanosField = getNanoField();
        if (isTimeMessage(msgStructure)) {
            if(msgStructure.getFields().containsKey(secondsField)) {
                session.setAttribute(ITCHMessageHelper.FIELD_SECONDS, message.getField(secondsField));
            } else {
                logger.warn("Message {} [{}] not contains field {}", message.getName(), message.getFieldNames(),
                        secondsField);
            }
        } else if(msgStructure.getFields().containsKey(ITCHMessageHelper.FAKE_FIELD_MESSAGE_TIME)
                && session.containsAttribute(ITCHMessageHelper.FIELD_SECONDS)
                && msgStructure.getFields().containsKey(nanosField)) {
            long seconds = ((Number) ObjectUtils.defaultIfNull(session.getAttribute(ITCHMessageHelper.FIELD_SECONDS), -1l)).longValue();
            if (seconds != -1l) {
                long nanoSeconds = ObjectUtils.defaultIfNull(message.getField(nanosField), 0L);
                LocalDateTime dateTime = toLocalDateTime(seconds, nanoSeconds);
                message.addField(ITCHMessageHelper.FAKE_FIELD_MESSAGE_TIME, dateTime);
            }
        }
    } catch (RuntimeException e) {
        logger.warn("{} field has not been add to message {} ", ITCHMessageHelper.FAKE_FIELD_MESSAGE_TIME, message.getName(), e);
    }
}
 
Example 4
Source File: LdapProtocolDecoder.java    From directory-ldap-api with Apache License 2.0 6 votes vote down vote up
/**
 * {@inheritDoc}
 */
@Override
public void decode( IoSession session, IoBuffer in, ProtocolDecoderOutput out ) throws Exception
{
    @SuppressWarnings("unchecked")
    LdapMessageContainer<AbstractMessage> messageContainer =
        ( LdapMessageContainer<AbstractMessage> )
        session.getAttribute( LdapDecoder.MESSAGE_CONTAINER_ATTR );

    if ( session.containsAttribute( LdapDecoder.MAX_PDU_SIZE_ATTR ) )
    {
        int maxPDUSize = ( Integer ) session.getAttribute( LdapDecoder.MAX_PDU_SIZE_ATTR );

        messageContainer.setMaxPDUSize( maxPDUSize );
    }

    List<Message> decodedMessages = new ArrayList<>();
    ByteBuffer buf = in.buf();

    decode( buf, messageContainer, decodedMessages );

    for ( Message message : decodedMessages )
    {
        out.write( message );
    }
}
 
Example 5
Source File: HttpServerDecoderImpl.java    From game-server with MIT License 6 votes vote down vote up
/** {@inheritDoc} */
@Override
protected boolean doDecode(IoSession session, IoBuffer msg, ProtocolDecoderOutput out) throws Exception {
	/**
	 * 消息已经解析
	 * 谷歌浏览器一次请求存在多次收到消息,还额外请求了/favicon.ico路径
	 */
	if (session.containsAttribute(HTTP_REQUEST)) {
		return false;
	}
	msg.mark();
	HttpRequestImpl rq = parseHttpRequestHead(msg.buf(), msg);
	if (rq != null) {
		out.write(rq);
		session.setAttribute(HTTP_REQUEST, rq);
		// LOG.info("解析成功");
		return true;
	}
	msg.reset();
	return false;
}
 
Example 6
Source File: ClientProtocolDecoder.java    From game-server with MIT License 6 votes vote down vote up
/**
 * 检测玩家消息发送频率
 * 
 * @author JiangZhiYong
 * @QQ 359135103 2017年8月21日 下午1:47:58
 * @param session
 */
private boolean checkMsgFrequency(IoSession session) {
	int count = 0;
	long startTime = 0L;
	if (session.containsAttribute(START_TIME)) {
		startTime = (long) session.getAttribute(START_TIME);
	}
	if (session.containsAttribute(RECEIVE_COUNT)) {
		count = (int) session.getAttribute(RECEIVE_COUNT);
	}
	long interval= session.getLastReadTime() - startTime;
	if (interval > 1000L) {
		if (count > getMaxCountPerSecond()) {
			MsgUtil.close(session, "%s %d--> %dms内消息过于频繁:%d,超过次数:%d", MsgUtil.getIp(session),session.getId(),interval, count,
					getMaxCountPerSecond());
			return false;
		}
		startTime = session.getLastReadTime();
		count = 0;
		session.setAttribute(START_TIME, startTime);
	}
	count++;
	session.setAttribute(RECEIVE_COUNT, count);
	return true;
}
 
Example 7
Source File: ServerManager.java    From game-server with MIT License 5 votes vote down vote up
/**
 * 注册服务器信息
 * 
 * @param serverInfo
 */
public ServerInfo registerServer(ServerMessage.ServerInfo serverInfo, IoSession session) {
	Map<Integer, ServerInfo> map = servers.get(ServerType.valueof(serverInfo.getType()));
	if (map == null) {
		map = new ConcurrentHashMap<>();
		servers.put(ServerType.valueof(serverInfo.getType()), map);
	}
	ServerInfo info = map.get(serverInfo.getId());
	if (info == null) {
		info = new ServerInfo();
		map.put(serverInfo.getId(), info);
	}
	info.setHttpPort(serverInfo.getHttpport());
	info.setId(serverInfo.getId());
	info.setIp(serverInfo.getIp());
	info.setMaxUserCount(serverInfo.getMaxUserCount());
	info.setName(serverInfo.getName());
	info.setOnline(serverInfo.getOnline());
	info.setPort(serverInfo.getPort());
	// info.setState(serverInfo.getState());
	info.setType(serverInfo.getType());
	info.setWwwip(serverInfo.getWwwip());
	info.onIoSessionConnect(session);
	info.setFreeMemory(serverInfo.getFreeMemory());
	info.setTotalMemory(serverInfo.getTotalMemory());
	info.setVersion(serverInfo.getVersion());

	if (!session.containsAttribute(ClusterTcpServer.SERVER_INFO)) {
		session.setAttribute(ClusterTcpServer.SERVER_INFO, info);
	}
	return info;
}
 
Example 8
Source File: SslFilter.java    From jane with GNU Lesser General Public License v3.0 5 votes vote down vote up
@Override
public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception {
	SslHandler sslHandler = getSslSessionHandler(session);

	try {
		boolean needsFlush = true;
		synchronized (sslHandler) {
			if (!isSslStarted(session))
				sslHandler.scheduleFilterWrite(nextFilter, writeRequest);
			else if (session.containsAttribute(DISABLE_ENCRYPTION_ONCE)) { // don't encrypt the data if encryption is disabled
				session.removeAttribute(DISABLE_ENCRYPTION_ONCE); // remove the marker attribute because it is temporary
				sslHandler.scheduleFilterWrite(nextFilter, writeRequest);
			} else { // otherwise, encrypt the buffer
				if (sslHandler.isWritingEncryptedData())
					sslHandler.scheduleFilterWrite(nextFilter, writeRequest); // data already encrypted; simply return buffer
				else if (sslHandler.isHandshakeComplete()) { // SSL encrypt
					sslHandler.encrypt(((IoBuffer)writeRequest.writeRequestMessage()).buf());
					IoBuffer encryptedBuffer = sslHandler.fetchOutNetBuffer();
					sslHandler.scheduleFilterWrite(nextFilter, new EncryptedWriteRequest(writeRequest, encryptedBuffer));
				} else {
					if (session.isConnected())
						sslHandler.schedulePreHandshakeWriteRequest(nextFilter, writeRequest); // handshake not complete yet
					needsFlush = false;
				}
			}
		}

		if (needsFlush)
			sslHandler.flushScheduledEvents();
	} catch (SSLException se) {
		sslHandler.release();
		throw se;
	}
}
 
Example 9
Source File: MessageChannelCodecFilter.java    From neoscada with Eclipse Public License 1.0 5 votes vote down vote up
private CharsetEncoder getCharsetEncoder ( final IoSession session )
{
    if ( session.containsAttribute ( "charsetEncoder" ) )
    {
        return (CharsetEncoder)session.getAttribute ( "charsetEncoder" );
    }

    final CharsetEncoder encoder = Charset.forName ( "UTF-8" ).newEncoder ();
    session.setAttribute ( "charsetEncoder", encoder );
    return encoder;
}
 
Example 10
Source File: MessageChannelCodecFilter.java    From neoscada with Eclipse Public License 1.0 5 votes vote down vote up
private CharsetDecoder getCharsetDecoder ( final IoSession session )
{
    if ( session.containsAttribute ( "charsetDecoder" ) )
    {
        return (CharsetDecoder)session.getAttribute ( "charsetDecoder" );
    }

    final CharsetDecoder decoder = Charset.forName ( "UTF-8" ).newDecoder ();
    session.setAttribute ( "charsetDecoder", decoder );
    return decoder;
}
 
Example 11
Source File: KeepAliveFilter.java    From neoscada with Eclipse Public License 1.0 5 votes vote down vote up
@Override
public void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status) throws Exception {
    if (status == interestedIdleStatus) {
        if (!session.containsAttribute(WAITING_FOR_RESPONSE)) {
            Object pingMessage = messageFactory.getRequest(session);
            if (pingMessage != null) {
                nextFilter.filterWrite(session, new DefaultWriteRequest(pingMessage));

                // If policy is OFF, there's no need to wait for
                // the response.
                if (getRequestTimeoutHandler() != KeepAliveRequestTimeoutHandler.DEAF_SPEAKER) {
                    markStatus(session);
                    if (interestedIdleStatus == IdleStatus.BOTH_IDLE) {
                        session.setAttribute(IGNORE_READER_IDLE_ONCE);
                    }
                } else {
                    resetStatus(session);
                }
            }
        } else {
            handlePingTimeout(session);
        }
    } else if (status == IdleStatus.READER_IDLE) {
        if (session.removeAttribute(IGNORE_READER_IDLE_ONCE) == null) {
            if (session.containsAttribute(WAITING_FOR_RESPONSE)) {
                handlePingTimeout(session);
            }
        }
    }

    if (forwardEvent) {
        nextFilter.sessionIdle(session, status);
    }
}
 
Example 12
Source File: SslFilter.java    From jane with GNU Lesser General Public License v3.0 5 votes vote down vote up
private WriteFuture initiateClosure(NextFilter nextFilter, IoSession session, boolean needFuture) throws Exception {
	SslHandler sslHandler = getSslSessionHandler(session);
	WriteFuture future;

	// if already shutdown
	try {
		synchronized (sslHandler) {
			if (!sslHandler.closeOutbound())
				return DefaultWriteFuture.newNotWrittenFuture(session, new IllegalStateException("SSL session is shutdown already"));

			// there might be data to write out here?
			future = sslHandler.writeNetBuffer(nextFilter, needFuture);
			if (needFuture && future == null)
				future = DefaultWriteFuture.newWrittenFuture(session);

			if (sslHandler.isInboundDone())
				sslHandler.destroy();
		}

		if (session.containsAttribute(USE_NOTIFICATION))
			sslHandler.scheduleMessageReceived(nextFilter, SESSION_UNSECURED);
	} catch (SSLException se) {
		sslHandler.release();
		throw se;
	}

	return future;
}
 
Example 13
Source File: RTMPEIoFilter.java    From red5-client with Apache License 2.0 5 votes vote down vote up
@Override
public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest request) throws Exception {
    RTMPMinaConnection conn = (RTMPMinaConnection) RTMPConnManager.getInstance().getConnectionBySessionId((String) session.getAttribute(RTMPConnection.RTMP_SESSION_ID));
    // filter based on current connection state
    if (conn.getState().getState() == RTMP.STATE_CONNECTED && session.containsAttribute(RTMPConnection.RTMPE_CIPHER_OUT)) {
        Cipher cipher = (Cipher) session.getAttribute(RTMPConnection.RTMPE_CIPHER_OUT);
        IoBuffer message = (IoBuffer) request.getMessage();
        if (!message.hasRemaining()) {
            if (log.isTraceEnabled()) {
                log.trace("Ignoring empty message");
            }
            nextFilter.filterWrite(session, request);
        } else {
            if (log.isDebugEnabled()) {
                log.debug("Encrypting message: {}", message);
            }
            byte[] plain = new byte[message.remaining()];
            message.get(plain);
            message.clear();
            message.free();
            // encrypt and write
            byte[] encrypted = cipher.update(plain);
            IoBuffer messageEncrypted = IoBuffer.wrap(encrypted);
            if (log.isDebugEnabled()) {
                log.debug("Encrypted message: {}", messageEncrypted);
            }
            nextFilter.filterWrite(session, new EncryptedWriteRequest(request, messageEncrypted));
        }
    } else {
        log.trace("Non-encrypted message");
        nextFilter.filterWrite(session, request);
    }
}
 
Example 14
Source File: TestTupleDecoder.java    From streamsx.topology with Apache License 2.0 5 votes vote down vote up
/**
 * Decode bytes an attribute at a time, once enough information exists to
 * maintain a tuple This code maintains state in the session as attributes,
 * namely:
 * <UL>
 * <LI>tuple - The partially initialized tuple to be sent to the next
 * handler in the chain.
 * <LI>attributeIndex - The next attribute to be decoded
 * </UL>
 */
@Override
protected boolean doDecode(IoSession session, IoBuffer in,
        ProtocolDecoderOutput out) throws Exception {

    Integer testerId = null;

    if (!session.containsAttribute("testerId")) {
        if (in.remaining() < 4)
            return false;

        testerId = in.getInt();
    }

    if (!in.prefixedDataAvailable(4)) {
        if (testerId != null)
            session.setAttribute("testerId", testerId);
        return false;
    }

    if (testerId == null) {
        testerId = (Integer) session.removeAttribute("testerId");
    }

    int tupleLength = in.getInt();

    byte[] tupleData = new byte[tupleLength];
    in.get(tupleData);

    out.write(new TestTuple(testerId, tupleData));

    return in.remaining() >= 4;
}
 
Example 15
Source File: WebSocketEncoder.java    From game-server with MIT License 5 votes vote down vote up
/** {@inheritDoc} */
@Override
public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
    boolean isHandshakeResponse = message instanceof WebSocketHandShakeResponse;
    boolean isDataFramePacket = message instanceof WebSocketCodecPacket;
    boolean isRemoteWebSocket = session.containsAttribute(WebSocketUtils.SessionAttribute) && (true==(Boolean)session.getAttribute(WebSocketUtils.SessionAttribute));
    IoBuffer resultBuffer;
    if(isHandshakeResponse){
        WebSocketHandShakeResponse response = (WebSocketHandShakeResponse)message;
        resultBuffer = buildWSResponseBuffer(response);
    }
    else if(isDataFramePacket){
        WebSocketCodecPacket packet = (WebSocketCodecPacket)message;
        resultBuffer = isRemoteWebSocket ? buildWSDataFrameBuffer(packet.getPacket()) : packet.getPacket();
    }else if(message instanceof Message) {	//自定义protobuf,消息头只有ID,无长度,和app客户端不一致
    	Message msg=(Message)message;
    	int msgId=MsgUtil.getMessageID(msg);
    	byte[] msgData=msg.toByteArray();
    	IoBuffer iobuffer = IoBuffer.allocate(4+msgData.length);
    	iobuffer.putInt(msgId);
    	iobuffer.put(msgData);
    	iobuffer.rewind();
    	resultBuffer=isRemoteWebSocket?buildWSDataFrameBuffer(iobuffer):iobuffer;
    }else if(message instanceof byte[]) {  //已经包含消息ID
    	 byte[] data = (byte[]) message;
         IoBuffer buf = IoBuffer.allocate(data.length);
         buf.put(data);
         buf.rewind();
         resultBuffer=isRemoteWebSocket?buildWSDataFrameBuffer(buf):buf;
    }
    else{
        throw (new Exception("message not a websocket type"));
    }
    
    out.write(resultBuffer);
}
 
Example 16
Source File: WebSocketDecoder.java    From game-server with MIT License 4 votes vote down vote up
/** {@inheritDoc} */
    @Override
    protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {        
        IoBuffer resultBuffer;
        if(!session.containsAttribute(WebSocketUtils.SessionAttribute)){
            // first message on a new connection. see if its from a websocket or a 
            // native socket.
            if(tryWebSockeHandShake(session, in, out)){
                // websocket handshake was successful. Don't write anything to output
                // as we want to abstract the handshake request message from the handler.
                in.position(in.limit());
                return true;
            }
            else{
                // message is from a native socket. Simply wrap and pass through.
                resultBuffer = IoBuffer.wrap(in.array(), 0, in.limit());
                in.position(in.limit());
                session.setAttribute(WebSocketUtils.SessionAttribute, false);
            }
            out.write(resultBuffer);
        }
        else if(session.containsAttribute(WebSocketUtils.SessionAttribute) && true==(Boolean)session.getAttribute(WebSocketUtils.SessionAttribute)){            
            // there is incoming data from the websocket. Decode and send to handler or next filter.     
            int startPos = in.position();
            resultBuffer = buildWSDataBuffer(in, session);
            if(resultBuffer == null){
                // There was not enough data in the buffer to parse. Reset the in buffer
                // position and wait for more data before trying again.
                in.position(startPos);
                return false;
            }
            //转换为byte数组
//            int int1 = resultBuffer.getInt();
           out.write(resultBuffer.array());
        }
        else{
            // session is known to be from a native socket. So
            // simply wrap and pass through.
            resultBuffer = IoBuffer.wrap(in.array(), 0, in.limit());    
            in.position(in.limit());
            out.write(resultBuffer);
        }                        
        return true;
    }
 
Example 17
Source File: SslFilter.java    From neoscada with Eclipse Public License 1.0 4 votes vote down vote up
@Override
public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws SSLException {
    if (LOGGER.isDebugEnabled()) {
        LOGGER.debug("{}: Writing Message : {}", getSessionInfo(session), writeRequest);
    }

    boolean needsFlush = true;
    SslHandler handler = getSslSessionHandler(session);
    synchronized (handler) {
        if (!isSslStarted(session)) {
            handler.scheduleFilterWrite(nextFilter, writeRequest);
        }
        // Don't encrypt the data if encryption is disabled.
        else if (session.containsAttribute(DISABLE_ENCRYPTION_ONCE)) {
            // Remove the marker attribute because it is temporary.
            session.removeAttribute(DISABLE_ENCRYPTION_ONCE);
            handler.scheduleFilterWrite(nextFilter, writeRequest);
        } else {
            // Otherwise, encrypt the buffer.
            IoBuffer buf = (IoBuffer) writeRequest.getMessage();

            if (handler.isWritingEncryptedData()) {
                // data already encrypted; simply return buffer
                handler.scheduleFilterWrite(nextFilter, writeRequest);
            } else if (handler.isHandshakeComplete()) {
                // SSL encrypt
                int pos = buf.position();
                handler.encrypt(buf.buf());
                buf.position(pos);
                IoBuffer encryptedBuffer = handler.fetchOutNetBuffer();
                handler.scheduleFilterWrite(nextFilter, new EncryptedWriteRequest(writeRequest, encryptedBuffer));
            } else {
                if (session.isConnected()) {
                    // Handshake not complete yet.
                    handler.schedulePreHandshakeWriteRequest(nextFilter, writeRequest);
                }
                needsFlush = false;
            }
        }
    }

    if (needsFlush) {
        handler.flushScheduledEvents();
    }
}
 
Example 18
Source File: Sessions.java    From neoscada with Eclipse Public License 1.0 4 votes vote down vote up
public static boolean isLittleEndian ( final IoSession session )
{
    return session.containsAttribute ( ATTR_LITTLE_ENDIAN );
}
 
Example 19
Source File: WebSocketDecoder.java    From red5-websocket with Apache License 2.0 4 votes vote down vote up
@Override
protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
    IoBuffer resultBuffer;
    WebSocketConnection conn = (WebSocketConnection) session.getAttribute(Constants.CONNECTION);
    if (conn == null) {
        log.debug("Decode start pos: {}", in.position());
        // first message on a new connection, check if its from a websocket or a native socket
        if (doHandShake(session, in)) {
            log.debug("Decode end pos: {} limit: {}", in.position(), in.limit());
            // websocket handshake was successful. Don't write anything to output as we want to abstract the handshake request message from the handler
            if (in.position() != in.limit()) {
                in.position(in.limit());
            }
            return true;
        } else if (session.containsAttribute(Constants.WS_HANDSHAKE)) {
            // more still expected to come in before HS is completed
            return false;
        } else {
            // message is from a native socket. Simply wrap and pass through
            resultBuffer = IoBuffer.wrap(in.array(), 0, in.limit());
            in.position(in.limit());
            out.write(resultBuffer);
        }
    } else if (conn.isWebConnection()) {
        // grab decoding state
        DecoderState decoderState = (DecoderState) session.getAttribute(DECODER_STATE_KEY);
        if (decoderState == null) {
            decoderState = new DecoderState();
            session.setAttribute(DECODER_STATE_KEY, decoderState);
        }
        // there is incoming data from the websocket, decode it
        decodeIncommingData(in, session);
        // this will be null until all the fragments are collected
        WSMessage message = (WSMessage) session.getAttribute(DECODED_MESSAGE_KEY);
        if (log.isDebugEnabled()) {
            log.debug("State: {} message: {}", decoderState, message);
        }
        if (message != null) {
            // set the originating connection on the message
            message.setConnection(conn);
            // write the message
            out.write(message);
            // remove decoded message
            session.removeAttribute(DECODED_MESSAGE_KEY);
        } else {
            // there was not enough data in the buffer to parse
            return false;
        }
    } else {
        // session is known to be from a native socket. So simply wrap and pass through
        byte[] arr = new byte[in.remaining()];
        in.get(arr);
        out.write(IoBuffer.wrap(arr));
    }
    return true;
}
 
Example 20
Source File: WebSocketDecoder.java    From red5-websocket with Apache License 2.0 4 votes vote down vote up
/**
 * Try parsing the message as a websocket handshake request. If it is such a request, then send the corresponding handshake response (as in Section 4.2.2 RFC 6455).
 */
@SuppressWarnings("unchecked")
private boolean doHandShake(IoSession session, IoBuffer in) {
    if (log.isDebugEnabled()) {
        log.debug("Handshake: {}", in);
    }
    // incoming data
    byte[] data = null;
    // check for existing HS data
    if (session.containsAttribute(Constants.WS_HANDSHAKE)) {
        byte[] tmp = (byte[]) session.getAttribute(Constants.WS_HANDSHAKE);
        // size to hold existing and incoming
        data = new byte[tmp.length + in.remaining()];
        System.arraycopy(tmp, 0, data, 0, tmp.length);
        // get incoming bytes
        in.get(data, tmp.length, in.remaining());
    } else {
        // size for incoming bytes
        data = new byte[in.remaining()];
        // get incoming bytes
        in.get(data);
    }
    // ensure the incoming data is complete (ends with crlfcrlf)
    byte[] tail = Arrays.copyOfRange(data, data.length - 4, data.length);
    if (!Arrays.equals(tail, Constants.END_OF_REQ)) {
        // accumulate the HS data
        session.setAttribute(Constants.WS_HANDSHAKE, data);
        return false;
    }
    // create the connection obj
    WebSocketConnection conn = new WebSocketConnection(session);
    // mark as secure if using ssl
    if (session.getFilterChain().contains("sslFilter")) {
        conn.setSecure(true);
    }
    try {
        Map<String, Object> headers = parseClientRequest(conn, new String(data));
        if (log.isTraceEnabled()) {
            log.trace("Header map: {}", headers);
        }
        if (!headers.isEmpty() && headers.containsKey(Constants.WS_HEADER_KEY)) {
            // add the headers to the connection, they may be of use to implementers
            conn.setHeaders(headers);
            // add query string parameters
            if (headers.containsKey(Constants.URI_QS_PARAMETERS)) {
                conn.setQuerystringParameters((Map<String, Object>) headers.remove(Constants.URI_QS_PARAMETERS));
            }
            // check the version
            if (!"13".equals(headers.get(Constants.WS_HEADER_VERSION))) {
                log.info("Version 13 was not found in the request, communications may fail");
            }
            // get the path 
            String path = conn.getPath();
            // get the scope manager
            WebSocketScopeManager manager = (WebSocketScopeManager) session.getAttribute(Constants.MANAGER);
            if (manager == null) {
                WebSocketPlugin plugin = (WebSocketPlugin) PluginRegistry.getPlugin("WebSocketPlugin");
                manager = plugin.getManager(path);
            }
            // store manager in the current session
            session.setAttribute(Constants.MANAGER, manager);
            // TODO add handling for extensions

            // TODO expand handling for protocols requested by the client, instead of just echoing back
            if (headers.containsKey(Constants.WS_HEADER_PROTOCOL)) {
                boolean protocolSupported = false;
                String protocol = (String) headers.get(Constants.WS_HEADER_PROTOCOL);
                log.debug("Protocol '{}' found in the request", protocol);
                // add protocol to the connection
                conn.setProtocol(protocol);
                // TODO check listeners for "protocol" support
                Set<IWebSocketDataListener> listeners = manager.getScope(path).getListeners();
                for (IWebSocketDataListener listener : listeners) {
                    if (listener.getProtocol().equals(protocol)) {
                        //log.debug("Scope has listener support for the {} protocol", protocol);
                        protocolSupported = true;
                        break;
                    }
                }
                log.debug("Scope listener does{} support the '{}' protocol", (protocolSupported ? "" : "n't"), protocol);
            }
            // add connection to the manager
            manager.addConnection(conn);
            // prepare response and write it to the directly to the session
            HandshakeResponse wsResponse = buildHandshakeResponse(conn, (String) headers.get(Constants.WS_HEADER_KEY));
            // pass the handshake response to the ws connection so it can be sent outside the io thread and allow the decode to complete
            conn.sendHandshakeResponse(wsResponse);
            // remove the chunk attr
            session.removeAttribute(Constants.WS_HANDSHAKE);
            return true;
        }
        // set connection as native / direct
        conn.setType(ConnectionType.DIRECT);
    } catch (Exception e) {
        // input is not a websocket handshake request
        log.warn("Handshake failed", e);
    }
    return false;
}