io.jsync.http.impl.cgbystrom.FlashPolicyHandler.java Source code

Java tutorial

Introduction

Here is the source code for io.jsync.http.impl.cgbystrom.FlashPolicyHandler.java

Source

package io.jsync.http.impl.cgbystrom;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;

/**
 * A Flash policy file handler
 * Will detect connection attempts made by Adobe Flash clients and return a policy file response
 * <p>
 * After the policy has been sent, it will instantly close the connection.
 * If the first bytes sent are not a policy file request the handler will simply remove itself
 * from the pipeline.
 * <p>
 * Read more at http://www.adobe.com/devnet/articles/crossdomain_policy_file_spec.html
 * <p>
 * Example usage:
 * <code>
 * ChannelPipeline pipeline = Channels.pipeline();
 * pipeline.addLast("flashPolicy", new FlashPolicyHandler());
 * pipeline.addLast("decoder", new MyProtocolDecoder());
 * pipeline.addLast("encoder", new MyProtocolEncoder());
 * pipeline.addLast("handler", new MyBusinessLogicHandler());
 * </code>
 * <p>
 * For license see LICENSE file in this directory
 */
public class FlashPolicyHandler extends ChannelInboundHandlerAdapter {
    private static final String XML = "<cross-domain-policy><allow-access-from domain=\"*\" to-ports=\"*\" /></cross-domain-policy>";
    private ParseState state = ParseState.MAGIC1;

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf buffer = (ByteBuf) msg;
        int index = buffer.readerIndex();
        switch (state) {
        case MAGIC1:
            if (!buffer.isReadable()) {
                return;
            }
            final int magic1 = buffer.getUnsignedByte(index++);
            state = ParseState.MAGIC2;
            if (magic1 != '<') {
                ctx.fireChannelRead(buffer);
                ctx.pipeline().remove(this);
                return;
            }
            // fall through
        case MAGIC2:
            if (!buffer.isReadable()) {
                return;
            }
            final int magic2 = buffer.getUnsignedByte(index);
            if (magic2 != 'p') {
                ctx.fireChannelRead(buffer);
                ctx.pipeline().remove(this);
            } else {
                ctx.writeAndFlush(Unpooled.copiedBuffer(XML, CharsetUtil.UTF_8))
                        .addListener(ChannelFutureListener.CLOSE);
            }
        }
    }

    enum ParseState {
        MAGIC1, MAGIC2
    }
}