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

org.objectfabric.NettyConnection Maven / Gradle / Ivy

The newest version!
/**
 * This file is part of ObjectFabric (http://objectfabric.org).
 *
 * ObjectFabric is licensed under the Apache License, Version 2.0, the terms
 * of which may be found at http://www.apache.org/licenses/LICENSE-2.0.html.
 * 
 * Copyright ObjectFabric Inc.
 * 
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

package org.objectfabric;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;

import org.jboss.netty.buffer.ByteBufferBackedChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
import org.objectfabric.CloseCounter.Callback;

class NettyConnection extends Connection {

    private final Channel _channel;

    private final boolean _webSocket;

    protected NettyConnection(Location location, Channel channel, boolean webSocket, Headers headers) {
        super(location, headers);

        _channel = channel;
        _webSocket = webSocket;

        onStarted();
    }

    @Override
    void onClose(Callback callback) {
        super.onClose(callback);

        _channel.close();
    }

    @Override
    protected Session onConnection(Headers headers) {
        if (location() instanceof Server) {
            InetSocketAddress source = (InetSocketAddress) _channel.getRemoteAddress();
            return ((Server) location()).onConnection(source, address(), headers, _channel);
        }

        return super.onConnection(headers);
    }

    final void read(ChannelBuffer buffer) {
        if (resumeRead()) {
            // TODO wrap if already a byte buffer
            while (buffer.readableBytes() != 0) {
                JVMBuff buff = (JVMBuff) Buff.getOrCreate();

                // To put remaining from last buffer
                buff.position(Buff.getLargestUnsplitable());
                int length = Math.min(buff.remaining(), buffer.readableBytes());
                buff.limit(Buff.getLargestUnsplitable() + length);
                buffer.getBytes(buffer.readerIndex(), buff.getByteBuffer());
                buffer.readerIndex(buffer.readerIndex() + length);
                buff.position(Buff.getLargestUnsplitable());

                read(buff);

                buff.recycle();
            }

            suspendRead();
        }
    }

    @Override
    protected void write() {
        Queue buffs = fill(0xffff);

        if (buffs != null) {
            // TODO Gather / send at once
            ChannelFuture future = null;

            for (;;) {
                final JVMBuff buff = (JVMBuff) buffs.poll();

                if (buff == null)
                    break;

                ByteBuffer defaultOrder = buff.getByteBuffer().duplicate();
                ChannelBuffer buffer = new ByteBufferBackedChannelBuffer(defaultOrder);
                Exception ex = null;

                try {
                    if (_webSocket)
                        future = _channel.write(new BinaryWebSocketFrame(buffer));
                    else
                        future = _channel.write(buffer);
                } catch (Exception e) {
                    ex = e;
                }

                if (ex != null) {
                    _channel.close();
                    return;
                }

                if (future == null || future.isDone())
                    buff.recycle();
                else {
                    if (Debug.THREADS)
                        ThreadAssert.exchangeGive(buff, buff);

                    future.addListener(new ChannelFutureListener() {

                        @Override
                        public void operationComplete(ChannelFuture _) throws Exception {
                            if (Debug.THREADS)
                                ThreadAssert.exchangeTake(buff);

                            buff.recycle();
                        }
                    });
                }
            }

            if (future == null || future.isDone())
                writeComplete();
            else {
                future.addListener(new ChannelFutureListener() {

                    @Override
                    public void operationComplete(ChannelFuture _) throws Exception {
                        writeComplete();
                    }
                });
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy