Package org.jboss.xnio.nio

Source Code of org.jboss.xnio.nio.NioUdpSocketChannelImpl

/*
* JBoss, Home of Professional Open Source
* Copyright 2008, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/

package org.jboss.xnio.nio;

import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.CancelledKeyException;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectionKey;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;

import org.jboss.xnio.IoHandler;
import org.jboss.xnio.log.Logger;
import org.jboss.xnio.channels.ChannelOption;
import org.jboss.xnio.channels.Configurable;
import org.jboss.xnio.channels.MultipointReadResult;
import org.jboss.xnio.channels.UdpChannel;
import org.jboss.xnio.channels.UnsupportedOptionException;

/**
*
*/
public class NioUdpSocketChannelImpl implements UdpChannel {

    private static final Logger log = Logger.getLogger("org.jboss.xnio.nio.udp.server.channel");

    private final DatagramChannel datagramChannel;
    private final NioHandle readHandle;
    private final NioHandle writeHandle;
    private final IoHandler<? super UdpChannel> handler;

    private final AtomicBoolean callFlag = new AtomicBoolean(false);
    private final NioXnio nioXnio;
    private final AtomicLong globalBytesRead;
    private final AtomicLong globalBytesWritten;
    private final AtomicLong globalMessagesRead;
    private final AtomicLong globalMessagesWritten;
    final AtomicLong bytesRead = new AtomicLong();
    final AtomicLong bytesWritten = new AtomicLong();
    final AtomicLong messagesRead = new AtomicLong();
    final AtomicLong messagesWritten = new AtomicLong();

    NioUdpSocketChannelImpl(final NioXnio nioXnio, final DatagramChannel datagramChannel, final IoHandler<? super UdpChannel> handler, final Executor executor, final AtomicLong globalBytesRead, final AtomicLong globalBytesWritten, final AtomicLong globalMessagesRead, final AtomicLong globalMessagesWritten) throws IOException {
        this.nioXnio = nioXnio;
        this.globalBytesRead = globalBytesRead;
        this.globalBytesWritten = globalBytesWritten;
        this.globalMessagesRead = globalMessagesRead;
        this.globalMessagesWritten = globalMessagesWritten;
        if (executor != null) {
            readHandle = nioXnio.addReadHandler(datagramChannel, new ReadHandler(), executor);
            writeHandle = nioXnio.addWriteHandler(datagramChannel, new WriteHandler(), executor);
        } else {
            readHandle = nioXnio.addReadHandler(datagramChannel, new ReadHandler());
            writeHandle = nioXnio.addWriteHandler(datagramChannel, new WriteHandler());
        }
        this.datagramChannel = datagramChannel;
        this.handler = handler;
    }

    public SocketAddress getLocalAddress() {
        return datagramChannel.socket().getLocalSocketAddress();
    }

    public MultipointReadResult<SocketAddress> receive(final ByteBuffer buffer) throws IOException {
        final int o = buffer.remaining();
        final SocketAddress sourceAddress = datagramChannel.receive(buffer);
        if (sourceAddress == null) {
            return null;
        } else {
            final int t = o - buffer.remaining();
            globalMessagesRead.incrementAndGet();
            messagesRead.incrementAndGet();
            globalBytesRead.addAndGet((long) t);
            bytesRead.addAndGet((long) t);
            return new MultipointReadResult<SocketAddress>() {
                public SocketAddress getSourceAddress() {
                    return sourceAddress;
                }

                public SocketAddress getDestinationAddress() {
                    return null;
                }
            };
        }
    }

    public boolean isOpen() {
        return datagramChannel.isOpen();
    }

    public void close() throws IOException {
        if (!callFlag.getAndSet(true)) {
            log.trace("Closing %s", this);
            try {
                datagramChannel.close();
            } finally {
                nioXnio.removeManaged(this);
                HandlerUtils.<UdpChannel>handleClosed(handler, this);
            }
        }
    }

    public boolean send(final SocketAddress target, final ByteBuffer buffer) throws IOException {
        int ret = datagramChannel.send(buffer, target);
        if (ret != 0) {
            globalMessagesWritten.incrementAndGet();
            messagesWritten.incrementAndGet();
            globalBytesWritten.addAndGet((long) ret);
            bytesWritten.addAndGet((long) ret);
            return true;
        } else {
            return false;
        }
    }

    public boolean send(final SocketAddress target, final ByteBuffer[] dsts) throws IOException {
        return send(target, dsts, 0, dsts.length);
    }

    public boolean send(final SocketAddress target, final ByteBuffer[] dsts, final int offset, final int length) throws IOException {
        // todo - gather not supported in NIO.1 so we have to fake it...
        long total = 0L;
        for (int i = 0; i < length; i++) {
            total += dsts[offset + i].remaining();
        }
        if (total > Integer.MAX_VALUE) {
            throw new IOException("Source data is too large");
        }
        ByteBuffer buf = ByteBuffer.allocate((int)total);
        for (int i = 0; i < length; i++) {
            buf.put(dsts[offset + i]);
        }
        buf.flip();
        return send(target, buf);
    }

    public void suspendReads() {
        try {
            readHandle.suspend();
        } catch (CancelledKeyException ex) {
            // ignore
        }
    }

    public void suspendWrites() {
        try {
            writeHandle.suspend();
        } catch (CancelledKeyException ex) {
            // ignore
        }
    }

    public void resumeReads() {
        try {
            readHandle.resume(SelectionKey.OP_READ);
        } catch (CancelledKeyException ex) {
            // ignore
        }
    }

    public void resumeWrites() {
        try {
            writeHandle.resume(SelectionKey.OP_WRITE);
        } catch (CancelledKeyException ex) {
            // ignore
        }
    }

    public void shutdownReads() throws IOException {
        throw new UnsupportedOperationException("Shutdown reads");
    }

    public void shutdownWrites() throws IOException {
        throw new UnsupportedOperationException("Shutdown writes");
    }

    public void awaitReadable() throws IOException {
        SelectorUtils.await(nioXnio, datagramChannel, SelectionKey.OP_READ);
    }

    public void awaitReadable(final long time, final TimeUnit timeUnit) throws IOException {
        SelectorUtils.await(nioXnio, datagramChannel, SelectionKey.OP_READ, time, timeUnit);
    }

    public void awaitWritable() throws IOException {
        SelectorUtils.await(nioXnio, datagramChannel, SelectionKey.OP_WRITE);
    }

    public void awaitWritable(final long time, final TimeUnit timeUnit) throws IOException {
        SelectorUtils.await(nioXnio, datagramChannel, SelectionKey.OP_WRITE, time, timeUnit);
    }

    public Key join(final InetAddress group, final NetworkInterface iface) throws IOException {
        throw new UnsupportedOperationException("Multicast join");
    }

    public Key join(final InetAddress group, final NetworkInterface iface, final InetAddress source) throws IOException {
        throw new UnsupportedOperationException("Multicast join");
    }

    public <T> T getOption(final ChannelOption<T> option) throws UnsupportedOptionException, IOException {
        throw new UnsupportedOptionException("No options supported");
    }

    public Set<ChannelOption<?>> getOptions() {
        return Collections.emptySet();
    }

    public <T> Configurable setOption(final ChannelOption<T> option, final T value) throws IllegalArgumentException, IOException {
        throw new UnsupportedOptionException("No options supported");
    }

    public IoHandler<? super UdpChannel> getHandler() {
        return handler;
    }

    public final class ReadHandler implements Runnable {
        public void run() {
            HandlerUtils.<UdpChannel>handleReadable(handler, NioUdpSocketChannelImpl.this);
        }
    }

    public final class WriteHandler implements Runnable {
        public void run() {
            HandlerUtils.<UdpChannel>handleWritable(handler, NioUdpSocketChannelImpl.this);
        }
    }

    @Override
    public String toString() {
        return String.format("UDP socket channel (NIO) <%s> @ %s", Integer.toString(hashCode(), 16), getLocalAddress());
    }
}
TOP

Related Classes of org.jboss.xnio.nio.NioUdpSocketChannelImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.