Example usage for java.nio.channels SocketChannel close

List of usage examples for java.nio.channels SocketChannel close

Introduction

In this page you can find the example usage for java.nio.channels SocketChannel close.

Prototype

public final void close() throws IOException 

Source Link

Document

Closes this channel.

Usage

From source file:org.quickserver.net.server.QuickServer.java

/**
 * Starts server in non-blocking mode.//from  w w  w  . j ava2 s .  c  om
 * @since 1.4.5
 */
private void runNonBlocking(TheClient theClient) throws Exception {
    int selectCount = 0;
    Iterator iterator = null;
    SelectionKey key = null;
    ServerSocketChannel serverChannel = null;
    SocketChannel socketChannel = null;
    Socket client = null;
    ClientHandler _chPolled = null;
    boolean stopServerProcessed = false;
    int linger = getBasicConfig().getAdvancedSettings().getSocketLinger();
    registerChannelRequestMap = new HashMap();

    int socketTrafficClass = 0;
    if (getBasicConfig().getAdvancedSettings().getClientSocketTrafficClass() != null) {
        socketTrafficClass = Integer
                .parseInt(getBasicConfig().getAdvancedSettings().getClientSocketTrafficClass());
    }

    while (true) {
        selectCount = selector.select(500);
        //selectCount = selector.select();//for testing

        //check for any pending registerChannel req.
        synchronized (registerChannelRequestMap) {
            if (registerChannelRequestMap.size() > 0) {
                RegisterChannelRequest req = null;
                Object hashkey = null;
                iterator = registerChannelRequestMap.keySet().iterator();
                while (iterator.hasNext()) {
                    hashkey = iterator.next();
                    req = (RegisterChannelRequest) registerChannelRequestMap.get(hashkey);
                    req.register(getSelector());
                }
                iterator = null;
                registerChannelRequestMap.clear();
            } //if
        } //sync

        if (stopServer == true && stopServerProcessed == false) {
            logger.warning("Closing " + getName());
            serverSocketChannel.close();
            stopServerProcessed = true;

            server = null;
            serverSocketChannel = null;

            setServiceState(Service.STOPPED);
            logger.warning("Closed " + getName());

            processServerHooks(ServerHook.POST_SHUTDOWN);
        }

        if (stopServer == false && stopServerProcessed == true) {
            logger.finest("Server must have re-started.. will break");
            break;
        }

        if (selectCount == 0 && stopServerProcessed == true) {
            java.util.Set keyset = selector.keys();
            if (keyset.isEmpty() == true && getClientCount() <= 0) {
                break;
            } else {
                continue;
            }
        } else if (selectCount == 0) {
            continue;
        }

        iterator = selector.selectedKeys().iterator();
        while (iterator.hasNext()) {
            key = (SelectionKey) iterator.next();

            if (key.isValid() == false) {
                iterator.remove();
                continue;
            }

            if (key.isAcceptable() && stopServer == false) {
                logger.finest("Key is Acceptable");
                serverChannel = (ServerSocketChannel) key.channel();
                socketChannel = serverChannel.accept();

                if (socketChannel == null) {
                    iterator.remove();
                    continue;
                }

                client = socketChannel.socket();

                if (linger < 0) {
                    client.setSoLinger(false, 0);
                } else {
                    client.setSoLinger(true, linger);
                }

                client.setTcpNoDelay(getBasicConfig().getAdvancedSettings().getClientSocketTcpNoDelay());

                if (getBasicConfig().getAdvancedSettings().getClientSocketTrafficClass() != null) {
                    client.setTrafficClass(socketTrafficClass);//low delay=10
                }

                //logger.fine("ReceiveBufferSize: "+client.getReceiveBufferSize());

                if (getBasicConfig().getAdvancedSettings().getClientSocketSendBufferSize() != 0) {
                    client.setSendBufferSize(
                            getBasicConfig().getAdvancedSettings().getClientSocketSendBufferSize());
                    //logger.fine("SendBufferSize: "+client.getSendBufferSize());
                }

                if (checkAccessConstraint(client) == false) {
                    iterator.remove();
                    continue;
                }

                socketChannel.configureBlocking(false);
                theClient.setTrusted(getSkipValidation());
                theClient.setSocket(socketChannel.socket());
                theClient.setSocketChannel(socketChannel);

                if (clientDataClass != null) {
                    if (getClientDataPool() == null) {
                        clientData = (ClientData) clientDataClass.newInstance();
                    } else {
                        //borrow a object from pool
                        clientData = (ClientData) getClientDataPool().borrowObject();
                    }
                    theClient.setClientData(clientData);
                }

                //Check if max connection has reached
                if (getSkipValidation() != true && maxConnection != -1
                        && getClientHandlerPool().getNumActive() >= maxConnection) {
                    theClient.setClientEvent(ClientEvent.MAX_CON);
                } else {
                    theClient.setClientEvent(ClientEvent.ACCEPT);
                }

                try {
                    _chPolled = (ClientHandler) getClientHandlerPool().borrowObject();
                    logger.finest("Asking " + _chPolled.getName() + " to handle.");
                    _chPolled.handleClient(theClient);
                } catch (java.util.NoSuchElementException nsee) {
                    logger.warning("Could not borrow ClientHandler Object from pool. Error: " + nsee);
                    logger.warning("Closing SocketChannel [" + serverChannel.socket()
                            + "] since no ClientHandler available.");
                    socketChannel.close();
                }

                if (_chPolled != null) {
                    try {
                        getClientPool().addClient(_chPolled, true);
                    } catch (java.util.NoSuchElementException nsee) {
                        logger.warning("Could not borrow Thread from pool. Error: " + nsee);
                        //logger.warning("Closing SocketChannel ["+serverChannel.socket()+"] since no Thread available.");
                        //socketChannel.close();
                        //returnClientHandlerToPool(_chPolled);
                    }
                    _chPolled = null;
                }
                socketChannel = null;
                client = null;

                setSkipValidation(false);//reset it back
            } else if (key.isValid() && key.isReadable()) {
                boolean addedEvent = false;
                ClientHandler _ch = null;
                try {
                    _ch = (ClientHandler) key.attachment();
                    logger.finest("Key is Readable, removing OP_READ from interestOps for " + _ch.getName());
                    key.interestOps(key.interestOps() & (~SelectionKey.OP_READ));
                    _ch.addEvent(ClientEvent.READ);
                    addedEvent = true;
                    //_ch.setSelectionKey(key);
                    getClientPool().addClient(_ch);
                } catch (CancelledKeyException cke) {
                    logger.fine("Ignored Error - Key was Cancelled: " + cke);
                } catch (java.util.NoSuchElementException nsee) {
                    logger.finest("NoSuchElementException: " + nsee);
                    if (addedEvent)
                        _ch.removeEvent(ClientEvent.READ);
                    continue;//no need to remove the key
                }
                _ch = null;
            } else if (key.isValid() && key.isWritable()) {
                if (getClientPool().shouldNioWriteHappen() == false) {
                    continue; //no need to remove the key
                }
                boolean addedEvent = false;
                ClientHandler _ch = null;
                try {
                    _ch = (ClientHandler) key.attachment();
                    logger.finest("Key is Writable, removing OP_WRITE from interestOps for " + _ch.getName());
                    //remove OP_WRITE from interest set
                    key.interestOps(key.interestOps() & (~SelectionKey.OP_WRITE));
                    _ch.addEvent(ClientEvent.WRITE);
                    addedEvent = true;
                    //_ch.setSelectionKey(key);
                    getClientPool().addClient(_ch);
                } catch (CancelledKeyException cke) {
                    logger.fine("Ignored Error - Key was Cancelled: " + cke);
                } catch (java.util.NoSuchElementException nsee) {
                    logger.finest("NoSuchElementException: " + nsee);
                    if (addedEvent)
                        _ch.removeEvent(ClientEvent.WRITE);
                    continue;//no need to remove the key
                }
                _ch = null;
            } else if (stopServer == true && key.isAcceptable()) {
                //we will not accept this key
                setSkipValidation(false);//reset it back
            } else {
                logger.warning("Unknown key got in SelectionKey: " + key);
            }
            iterator.remove(); //Remove key

            Thread.yield();
        } //end of iterator
        iterator = null;
    } //end of loop
}

From source file:org.openhab.binding.tcp.AbstractSocketChannelBinding.java

/**
 * @{inheritDoc}// w w w . jav a 2s  .c om
 */
@Override
protected void execute() {

    // Cycle through the Items and setup channels if required
    for (P provider : providers) {
        for (String itemName : provider.getItemNames()) {
            for (Command aCommand : ((P) provider).getAllCommands(itemName)) {

                String remoteHost = ((P) provider).getHost(itemName, aCommand);
                String remotePort = ((P) provider).getPortAsString(itemName, aCommand);
                Direction direction = ((P) provider).getDirection(itemName, aCommand);

                InetSocketAddress remoteAddress = null;
                if (!(remoteHost.equals("*") || remotePort.equals("*"))) {
                    remoteAddress = new InetSocketAddress(remoteHost, Integer.parseInt(remotePort));
                }

                Channel newChannel = null;
                Channel existingChannel = null;

                if (useAddressMask && (remoteHost.equals("*") || remotePort.equals("*"))) {
                    newChannel = new Channel(itemName, aCommand, remoteHost, remotePort,
                            ((P) provider).getDirection(itemName, aCommand), false, null, false, null);
                    existingChannel = channels.get(itemName, aCommand, direction, remoteHost, remotePort);
                } else {
                    newChannel = new Channel(itemName, aCommand, remoteAddress,
                            ((P) provider).getDirection(itemName, aCommand), false, null, false, null);
                    existingChannel = channels.get(itemName, aCommand, direction, remoteAddress);
                }

                if (existingChannel == null) {
                    if (direction == Direction.IN) {

                        boolean assigned = false;

                        if (useAddressMask && (remoteHost.equals("*") || remotePort.equals("*"))) {
                            logger.warn(
                                    "When using address masks we will not verify if we are already listening to similar incoming connections");
                            logger.info("We will accept data coming from the remote end {}:{}", remoteHost,
                                    remotePort);

                            channels.add(newChannel);
                        } else {

                            if (itemShareChannels) {
                                Channel firstChannel = channels.getFirstServed(itemName, direction,
                                        remoteAddress);
                                if (firstChannel != null) {
                                    newChannel.channel = firstChannel.channel;
                                    assigned = true;
                                }
                            }

                            if (bindingShareChannels) {
                                Channel firstChannel = channels.getFirstServed(direction, remoteAddress);
                                if (firstChannel != null) {
                                    newChannel.channel = firstChannel.channel;
                                    assigned = true;
                                }
                            }

                            if (directionsShareChannels) {
                                Channel firstChannel = channels.getFirstServed(remoteAddress);
                                if (firstChannel != null) {
                                    newChannel.channel = firstChannel.channel;
                                    assigned = true;
                                }
                            }

                            if (!assigned || newChannel.channel == null) {
                                if (channels.contains(itemName, aCommand, Direction.IN, remoteAddress)) {
                                    logger.warn("We already listen for incoming connections from {}",
                                            remoteAddress);
                                } else {
                                    logger.debug("Setting up the inbound channel {}", newChannel);
                                    channels.add(newChannel);
                                    logger.info("We will accept data coming from the remote end {}",
                                            remoteAddress);
                                }

                            }
                        }

                    } else if (direction == Direction.OUT) {

                        boolean assigned = false;

                        if (useAddressMask && (remoteHost.equals("*") || remotePort.equals("*"))) {
                            logger.error(
                                    "We do not accept outgoing connections for Items that do use address masks");
                        } else {

                            channels.add(newChannel);

                            if (newChannel.channel == null) {

                                if (itemShareChannels) {
                                    Channel firstChannel = channels.getFirstServed(itemName, direction,
                                            remoteAddress);
                                    if (firstChannel != null) {
                                        newChannel.channel = firstChannel.channel;
                                        assigned = true;
                                    }
                                }

                                if (bindingShareChannels) {
                                    Channel firstChannel = channels.getFirstServed(direction, remoteAddress);
                                    if (firstChannel != null) {
                                        newChannel.channel = firstChannel.channel;
                                        assigned = true;
                                    }
                                }

                                if (directionsShareChannels) {
                                    Channel firstChannel = channels.getFirstServed(remoteAddress);
                                    if (firstChannel != null) {
                                        newChannel.channel = firstChannel.channel;
                                        assigned = true;
                                    }
                                }

                                if (assigned) {
                                    logger.debug("Setting up the outbound assigned channel {} ", newChannel);
                                }

                                synchronized (this) {

                                    if (!assigned || newChannel.channel == null) {

                                        SocketChannel newSocketChannel = null;
                                        try {
                                            newSocketChannel = SocketChannel.open();
                                        } catch (IOException e2) {
                                            logger.error("An exception occurred while opening a channel: {}",
                                                    e2.getMessage());
                                        }

                                        try {
                                            newSocketChannel.socket().setKeepAlive(true);
                                            newSocketChannel.configureBlocking(false);
                                        } catch (IOException e) {
                                            logger.error(
                                                    "An exception occurred while configuring a channel: {}",
                                                    e.getMessage());
                                        }

                                        synchronized (selector) {
                                            selector.wakeup();
                                            int interestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE
                                                    | SelectionKey.OP_CONNECT;
                                            try {
                                                newSocketChannel.register(selector, interestSet);
                                            } catch (ClosedChannelException e1) {
                                                logger.error(
                                                        "An exception occurred while registering a selector: {}",
                                                        e1.getMessage());
                                            }
                                        }

                                        newChannel.channel = newSocketChannel;
                                        logger.debug("Setting up the outbound channel {}", newChannel);

                                        try {
                                            logger.info("Connecting the channel {} ", newChannel);
                                            newSocketChannel.connect(remoteAddress);
                                        } catch (IOException e) {
                                            logger.error("An exception occurred while connecting a channel: {}",
                                                    e.getMessage());
                                        }
                                    }
                                }
                            } else {
                                logger.info("There is already an active channel {} for the remote end {}",
                                        newChannel.channel, newChannel.remote);
                            }
                        }
                    }
                }
            }
        }
    }

    // Check on channels for which we have to process data
    synchronized (selector) {
        try {
            // Wait for an event
            selector.selectNow();
        } catch (IOException e) {
            logger.error("An exception occurred while Selecting ({})", e.getMessage());
        }
    }

    // Get list of selection keys with pending events
    Iterator<SelectionKey> it = selector.selectedKeys().iterator();

    // Process each key at a time
    while (it.hasNext()) {
        SelectionKey selKey = (SelectionKey) it.next();
        it.remove();

        if (selKey.isValid()) {
            if (selKey == listenerKey) {
                if (selKey.isAcceptable()) {

                    try {
                        SocketChannel newChannel = listenerChannel.accept();
                        logger.info("Received connection request from {}", newChannel.getRemoteAddress());

                        Channel firstChannel = channels.getFirstNotServed(Direction.IN,
                                (InetSocketAddress) newChannel.getRemoteAddress());

                        if (firstChannel != null) {

                            if (firstChannel.direction == Direction.IN) {

                                if (useAddressMask
                                        && (firstChannel.host.equals("*") || firstChannel.port.equals("*"))) {
                                    logger.info(
                                            "{}:{} is an allowed masked remote end. The channel will now be configured",
                                            firstChannel.host, firstChannel.port);
                                } else {
                                    logger.info(
                                            "{} is an allowed remote end. The channel will now be configured",
                                            firstChannel.remote);
                                }

                                if (firstChannel.channel == null || !firstChannel.channel.isOpen()) {

                                    firstChannel.channel = newChannel;
                                    firstChannel.isBlocking = false;
                                    firstChannel.buffer = null;

                                    if (itemShareChannels) {
                                        channels.replace(firstChannel.item, firstChannel.direction,
                                                (InetSocketAddress) newChannel.getRemoteAddress(),
                                                firstChannel.channel);
                                    }

                                    if (bindingShareChannels) {
                                        channels.replace(firstChannel.direction,
                                                (InetSocketAddress) newChannel.getRemoteAddress(),
                                                firstChannel.channel);
                                    }

                                    if (directionsShareChannels) {
                                        channels.replace((InetSocketAddress) newChannel.getRemoteAddress(),
                                                firstChannel.channel);
                                    }

                                    try {
                                        newChannel.configureBlocking(false);
                                        //setKeepAlive(true);
                                    } catch (IOException e) {
                                        logger.error("An exception occurred while configuring a channel: {}",
                                                e.getMessage());
                                    }

                                    synchronized (selector) {
                                        selector.wakeup();
                                        try {
                                            newChannel.register(selector, newChannel.validOps());
                                        } catch (ClosedChannelException e1) {
                                            logger.error(
                                                    "An exception occurred while registering a selector: {}",
                                                    e1.getMessage());
                                        }
                                    }

                                    Scheduler scheduler = null;
                                    try {
                                        scheduler = StdSchedulerFactory.getDefaultScheduler();
                                    } catch (SchedulerException e1) {
                                        logger.error(
                                                "An exception occurred while getting the Quartz scheduler: {}",
                                                e1.getMessage());
                                    }

                                    JobDataMap map = new JobDataMap();
                                    map.put("Channel", firstChannel);
                                    map.put("Binding", this);

                                    JobDetail job = newJob(ConfigureJob.class).withIdentity(
                                            Integer.toHexString(hashCode()) + "-Configure-"
                                                    + Long.toString(System.currentTimeMillis()),
                                            this.toString()).usingJobData(map).build();

                                    Trigger trigger = newTrigger().withIdentity(
                                            Integer.toHexString(hashCode()) + "-Configure-"
                                                    + Long.toString(System.currentTimeMillis()),
                                            this.toString()).startNow().build();

                                    try {
                                        if (job != null && trigger != null && selKey != listenerKey) {
                                            scheduler.scheduleJob(job, trigger);
                                        }
                                    } catch (SchedulerException e) {
                                        logger.error(
                                                "An exception occurred while scheduling a job with the Quartz Scheduler {}",
                                                e.getMessage());
                                    }

                                } else {
                                    logger.info(
                                            "We previously already accepted a connection from the remote end {} for this channel. Goodbye",
                                            firstChannel.remote);
                                    newChannel.close();
                                }
                            } else {
                                logger.info(
                                        "Disconnecting the remote end {} that tries to connect an outbound only port",
                                        newChannel.getRemoteAddress());
                                newChannel.close();
                            }
                        } else {
                            logger.info("Disconnecting the unallowed remote end {}",
                                    newChannel.getRemoteAddress());
                            newChannel.close();
                        }

                    } catch (IOException e) {
                        logger.error("An exception occurred while configuring a channel: {}", e.getMessage());
                    }
                }
            } else {

                SocketChannel theSocketChannel = (SocketChannel) selKey.channel();
                Channel theChannel = channels.get(theSocketChannel);

                if (selKey.isConnectable()) {
                    channels.setAllReconnecting(theSocketChannel, false);

                    boolean result = false;
                    boolean error = false;
                    try {
                        result = theSocketChannel.finishConnect();
                    } catch (NoConnectionPendingException e) {
                        // this channel is not connected and a connection operation
                        // has not been initiated
                        logger.warn("The channel  {} has no connection pending ({})", theSocketChannel,
                                e.getMessage());
                        error = true;
                    } catch (ClosedChannelException e) {
                        // If some other I/O error occurs
                        logger.warn("The channel  {} is closed ({})", theSocketChannel, e.getMessage());
                        error = true;
                    } catch (IOException e) {
                        // If some other I/O error occurs
                        logger.warn("The channel {} has encountered an unknown IO Exception: {}",
                                theSocketChannel, e.getMessage());
                        error = true;
                    }

                    if (error) {

                        Scheduler scheduler = null;
                        try {
                            scheduler = StdSchedulerFactory.getDefaultScheduler();
                        } catch (SchedulerException e1) {
                            logger.error("An exception occurred while getting the Quartz scheduler: {}",
                                    e1.getMessage());
                        }

                        JobDataMap map = new JobDataMap();
                        map.put("Channel", theChannel);
                        map.put("Binding", this);

                        JobDetail job = newJob(ReconnectJob.class)
                                .withIdentity(Integer.toHexString(hashCode()) + "-Reconnect-"
                                        + Long.toString(System.currentTimeMillis()), this.toString())
                                .usingJobData(map).build();

                        Trigger trigger = newTrigger()
                                .withIdentity(Integer.toHexString(hashCode()) + "-Reconnect-"
                                        + Long.toString(System.currentTimeMillis()), this.toString())
                                .startAt(futureDate(reconnectInterval, IntervalUnit.SECOND)).build();

                        try {
                            if (job != null && trigger != null && selKey != listenerKey) {
                                if (!theChannel.isReconnecting) {
                                    channels.setAllReconnecting(theSocketChannel, true);
                                    scheduler.scheduleJob(job, trigger);
                                }
                            }
                        } catch (SchedulerException e) {
                            logger.error(
                                    "An exception occurred while scheduling a job with the Quartz Scheduler {}",
                                    e.getMessage());
                        }

                    } else {
                        if (result) {
                            InetSocketAddress remote = null;
                            try {
                                remote = (InetSocketAddress) theSocketChannel.getRemoteAddress();
                            } catch (IOException e) {
                                logger.error(
                                        "An exception occurred while getting the remote address of channel {} ({})",
                                        theSocketChannel, e.getMessage());
                            }

                            logger.info("The channel for {} is now connected", remote);

                            if (itemShareChannels) {
                                channels.replace(theChannel.item, theChannel.direction, remote,
                                        theChannel.channel);
                            }

                            if (bindingShareChannels) {
                                channels.replace(theChannel.direction, remote, theChannel.channel);
                            }

                            if (directionsShareChannels) {
                                channels.replace(remote, theChannel.channel);
                            }

                            Scheduler scheduler = null;
                            try {
                                scheduler = StdSchedulerFactory.getDefaultScheduler();
                            } catch (SchedulerException e1) {
                                logger.error("An exception occurred while getting the Quartz scheduler: {}",
                                        e1.getMessage());
                            }

                            JobDataMap map = new JobDataMap();
                            map.put("Channel", theChannel);
                            map.put("Binding", this);

                            JobDetail job = newJob(ConfigureJob.class)
                                    .withIdentity(
                                            Integer.toHexString(hashCode()) + "-Configure-"
                                                    + Long.toString(System.currentTimeMillis()),
                                            this.toString())
                                    .usingJobData(map).build();

                            Trigger trigger = newTrigger()
                                    .withIdentity(
                                            Integer.toHexString(hashCode()) + "-Configure-"
                                                    + Long.toString(System.currentTimeMillis()),
                                            this.toString())
                                    .startNow().build();

                            try {
                                if (job != null && trigger != null && selKey != listenerKey) {
                                    scheduler.scheduleJob(job, trigger);
                                }
                            } catch (SchedulerException e) {
                                logger.error(
                                        "An exception occurred while scheduling a job with the Quartz Scheduler {}",
                                        e.getMessage());
                            }

                            job = newJob(ReconnectJob.class)
                                    .withIdentity(
                                            Integer.toHexString(hashCode()) + "-Reconnect-"
                                                    + Long.toString(System.currentTimeMillis()),
                                            this.toString())
                                    .usingJobData(map).build();

                            trigger = newTrigger()
                                    .withIdentity(
                                            Integer.toHexString(hashCode()) + "-Reconnect-"
                                                    + Long.toString(System.currentTimeMillis()),
                                            this.toString())
                                    .withSchedule(cronSchedule(reconnectCron)).build();

                            try {
                                if (job != null && trigger != null && selKey != listenerKey) {
                                    scheduler.scheduleJob(job, trigger);
                                }
                            } catch (SchedulerException e) {
                                logger.error(
                                        "An exception occurred while scheduling a job with the Quartz Scheduler {}",
                                        e.getMessage());
                            }
                        }
                    }

                } else if (selKey.isReadable()) {

                    ByteBuffer readBuffer = ByteBuffer.allocate(maximumBufferSize);
                    int numberBytesRead = 0;
                    boolean error = false;

                    try {
                        //TODO: Additional code to split readBuffer in multiple parts, in case the data send by the remote end is not correctly fragemented. Could be handed of to implementation class if for example, the buffer needs to be split based on a special character like line feed or carriage return
                        numberBytesRead = theSocketChannel.read(readBuffer);
                    } catch (NotYetConnectedException e) {
                        logger.warn("The channel for {} has no connection pending ({})", theChannel.remote,
                                e.getMessage());
                        if (!theSocketChannel.isConnectionPending()) {
                            error = true;
                        }
                    } catch (IOException e) {
                        // If some other I/O error occurs
                        logger.warn("The channel for {} has encountered an unknown IO Exception: {}",
                                theChannel.remote, e.getMessage());
                        error = true;
                    }

                    if (numberBytesRead == -1) {
                        try {
                            theSocketChannel.close();
                        } catch (IOException e) {
                            logger.warn("The channel for {} is closed ({})", theChannel.remote, e.getMessage());
                        }
                        error = true;
                    }

                    if (error) {
                        if (theChannel.direction == Direction.OUT) {

                            Scheduler scheduler = null;
                            try {
                                scheduler = StdSchedulerFactory.getDefaultScheduler();
                            } catch (SchedulerException e1) {
                                logger.error("An exception occurred while getting the Quartz scheduler: {}",
                                        e1.getMessage());
                            }

                            JobDataMap map = new JobDataMap();
                            map.put("Channel", theChannel);
                            map.put("Binding", this);

                            JobDetail job = newJob(ReconnectJob.class).withIdentity(
                                    Integer.toHexString(hashCode()) + "-Reconnect-"
                                            + Long.toString(System.currentTimeMillis()),
                                    "AbstractSocketChannelBinding").usingJobData(map).build();

                            Trigger trigger = newTrigger()
                                    .withIdentity(
                                            Integer.toHexString(hashCode()) + "-Reconnect-"
                                                    + Long.toString(System.currentTimeMillis()),
                                            "AbstractSocketChannelBinding")
                                    .startAt(futureDate(reconnectInterval, IntervalUnit.SECOND)).build();

                            try {
                                if (job != null && trigger != null && selKey != listenerKey) {
                                    if (!theChannel.isReconnecting) {
                                        channels.setAllReconnecting(theSocketChannel, true);
                                        scheduler.scheduleJob(job, trigger);
                                    }
                                }
                            } catch (SchedulerException e) {
                                logger.error(
                                        "An exception occurred while scheduling a job with the Quartz Scheduler {}",
                                        e.getMessage());
                            }

                        } else {
                            theChannel.channel = null;
                        }
                    } else {

                        ArrayList<Channel> channelsToServe = new ArrayList<Channel>();

                        channelsToServe = channels.getAll(theSocketChannel);

                        if (channelsToServe.size() > 0) {

                            readBuffer.flip();

                            boolean isBlocking = channels.isBlocking(theSocketChannel);

                            if (isBlocking) {
                                // if we are in a blocking operation, we get are now finished and we have to reset the flag. The read buffer will be returned to the instance
                                // that initiated the write opreation - it has to parse the buffer itself

                                theChannel = channels.getBlocking(theSocketChannel);
                                theChannel.buffer = readBuffer;
                                theChannel.isBlocking = false;

                            } else {
                                for (Channel aChannel : channelsToServe) {
                                    // if not, then we parse the buffer as ususal
                                    parseChanneledBuffer(aChannel, readBuffer);
                                }
                            }
                        } else {
                            try {
                                logger.warn(
                                        "No channel is active or defined for the data we received from {}. It will be discarded.",
                                        theSocketChannel.getRemoteAddress());
                            } catch (IOException e) {
                                logger.error(
                                        "An exception occurred while getting the remote address of the channel {} ({})",
                                        theSocketChannel, e.getMessage());
                            }
                        }
                    }

                } else if (selKey.isWritable()) {

                    boolean isBlocking = channels.isBlocking(theSocketChannel);

                    if (isBlocking) {
                        // if this channel is already flagged as being in a blocked write/read operation, we skip this selKey
                    } else {

                        // pick up a QueueElement for this channel, if any

                        WriteBufferElement theElement = null;

                        Iterator<WriteBufferElement> iterator = writeQueue.iterator();
                        while (iterator.hasNext()) {
                            WriteBufferElement anElement = iterator.next();
                            if (anElement.channel.channel.equals(theSocketChannel)) {
                                theElement = anElement;
                                break;
                            }
                        }

                        if (theElement != null && theElement.buffer != null) {

                            logger.debug("Picked {} from the queue", theElement);

                            if (theElement.isBlocking) {
                                theElement.channel.isBlocking = true;
                            }

                            boolean error = false;

                            theElement.buffer.rewind();
                            try {
                                logger.debug("Sending {} for the outbound channel {}->{}",
                                        new Object[] { new String(theElement.buffer.array()),
                                                theElement.channel.channel.getLocalAddress(),
                                                theElement.channel.channel.getRemoteAddress() });
                                theSocketChannel.write(theElement.buffer);
                            } catch (NotYetConnectedException e) {
                                logger.warn("The channel for {} has no connection pending ({})",
                                        theChannel.remote, e.getMessage());
                                if (!theSocketChannel.isConnectionPending()) {
                                    error = true;
                                }
                            } catch (ClosedChannelException e) {
                                // If some other I/O error occurs
                                logger.warn("The channel for {} is closed ({})", theChannel.remote,
                                        e.getMessage());
                                error = true;
                            } catch (IOException e) {
                                // If some other I/O error occurs
                                logger.warn("The channel for {} has encountered an unknown IO Exception: {}",
                                        theChannel.remote, e.getMessage());
                                error = true;
                            }

                            if (error) {

                                if (theElement.channel.direction == Direction.OUT) {

                                    Scheduler scheduler = null;
                                    try {
                                        scheduler = StdSchedulerFactory.getDefaultScheduler();
                                    } catch (SchedulerException e1) {
                                        logger.error(
                                                "An exception occurred while getting the Quartz scheduler: {}",
                                                e1.getMessage());
                                    }

                                    JobDataMap map = new JobDataMap();
                                    map.put("Channel", theElement.channel);
                                    map.put("Binding", this);

                                    JobDetail job = newJob(ReconnectJob.class).withIdentity(
                                            Integer.toHexString(hashCode()) + "-Reconnect-"
                                                    + Long.toString(System.currentTimeMillis()),
                                            "AbstractSocketChannelBinding").usingJobData(map).build();

                                    Trigger trigger = newTrigger()
                                            .withIdentity(
                                                    Integer.toHexString(hashCode()) + "-Reconnect-"
                                                            + Long.toString(System.currentTimeMillis()),
                                                    "AbstractSocketChannelBinding")
                                            .startAt(futureDate(reconnectInterval, IntervalUnit.SECOND))
                                            .build();

                                    try {
                                        if (job != null && trigger != null && selKey != listenerKey) {
                                            if (!theElement.channel.isReconnecting) {
                                                channels.setAllReconnecting(theSocketChannel, true);
                                                scheduler.scheduleJob(job, trigger);
                                            }
                                        }
                                    } catch (SchedulerException e) {
                                        logger.error(
                                                "An exception occurred while scheduling a job with the Quartz Scheduler {}",
                                                e.getMessage());
                                    }

                                } else {
                                    theElement.channel.channel = null;
                                }
                            } else {
                                if (theElement != null) {
                                    writeQueue.remove(theElement);
                                }

                            }
                        }
                    }
                }
            }
        }
    }
}

From source file:edu.hawaii.soest.kilonalu.adcp.ADCPSource.java

/**
 * A method that executes the streaming of data from the source to the RBNB
 * server after all configuration of settings, connections to hosts, and
 * thread initiatizing occurs.  This method contains the detailed code for 
 * streaming the data and interpreting the stream.
 *///ww  w .j a v a 2  s. com
protected boolean execute() {

    // do not execute the stream if there is no connection
    if (!isConnected())
        return false;

    boolean failed = false;

    SocketChannel socket = getSocketConnection();

    // while data are being sent, read them into the buffer
    try {
        // create four byte placeholders used to evaluate up to a four-byte 
        // window.  The FIFO layout looks like:
        //           -------------------------
        //   in ---> | One | Two |Three|Four |  ---> out
        //           -------------------------
        byte byteOne = 0x00, // set initial placeholder values
                byteTwo = 0x00, byteThree = 0x00, byteFour = 0x00;

        // Create a buffer that will store the ensemble bytes as they are read
        ByteBuffer ensembleBuffer = ByteBuffer.allocate(getBufferSize());

        // create a byte buffer to store bytes from the TCP stream
        ByteBuffer buffer = ByteBuffer.allocateDirect(getBufferSize());

        // add a channel of data that will be pushed to the server.  
        // Each ensemble will be sent to the Data Turbine as an rbnb frame.
        ChannelMap rbnbChannelMap = new ChannelMap();
        int channelIndex = rbnbChannelMap.Add(getRBNBChannelName());

        // while there are bytes to read from the socket ...
        while (socket.read(buffer) != -1 || buffer.position() > 0) {
            // prepare the buffer for reading
            buffer.flip();

            // while there are unread bytes in the ByteBuffer
            while (buffer.hasRemaining()) {
                byteOne = buffer.get();

                // Use a State Machine to process the byte stream.
                // Start building an rbnb frame for the entire ensemble, first by 
                // inserting a timestamp into the channelMap.  This time is merely
                // the time of insert into the data turbine, not the time of
                // observations of the measurements.  That time should be parsed out
                // of the ensemble in the Sink client code

                System.out.print("\rProcessed byte # " + ensembleByteCount + " "
                        + new String(Hex.encodeHex((new byte[] { byteOne }))) + " - log msg is: ");

                switch (state) {

                case 0: // find ensemble header id
                    if (byteOne == 0x7F && byteTwo == 0x7F) {
                        ensembleByteCount++; // add Header ID
                        ensembleChecksum += (byteTwo & 0xFF);
                        ensembleByteCount++; // add Data Source ID
                        ensembleChecksum += (byteOne & 0xFF);

                        state = 1;
                        break;

                    } else {
                        break;

                    }

                case 1: // find the Ensemble Length (LSB)
                    ensembleByteCount++; // add Ensemble Byte Count (LSB)
                    ensembleChecksum += (byteOne & 0xFF);

                    state = 2;
                    break;

                case 2: // find the Ensemble Length (MSB)
                    ensembleByteCount++; // add Ensemble Byte Count (MSB)
                    ensembleChecksum += (byteOne & 0xFF);

                    int upperEnsembleByte = (byteOne & 0xFF) << 8;
                    int lowerEnsembleByte = (byteTwo & 0xFF);
                    ensembleBytes = upperEnsembleByte + lowerEnsembleByte;
                    logger.debug("Number of Bytes in the Ensemble: " + ensembleBytes);

                    if (ensembleBuffer.remaining() > 0) {

                        ensembleBuffer.put(byteFour);
                        ensembleBuffer.put(byteThree);
                        ensembleBuffer.put(byteTwo);
                        ensembleBuffer.put(byteOne);
                    } else {

                        ensembleBuffer.compact();
                        ensembleBuffer.put(byteFour);
                        ensembleBuffer.put(byteThree);
                        ensembleBuffer.put(byteTwo);
                        ensembleBuffer.put(byteOne);
                    }

                    state = 3;
                    break;

                // verify that the header is real, not a random 0x7F7F
                case 3: // find the number of data types in the ensemble

                    // set the numberOfDataTypes byte
                    if (ensembleByteCount == NUMBER_OF_DATA_TYPES_OFFSET - 1) {
                        ensembleByteCount++;
                        ensembleChecksum += (byteOne & 0xFF);
                        numberOfDataTypes = (byteOne & 0xFF);
                        // calculate the number of bytes to the Fixed Leader ID
                        dataTypeOneOffset = 6 + (2 * numberOfDataTypes);

                        if (ensembleBuffer.remaining() > 0) {
                            ensembleBuffer.put(byteOne);

                        } else {
                            ensembleBuffer.compact();
                            ensembleBuffer.put(byteOne);

                        }
                        state = 4;
                        break;

                    } else {
                        ensembleByteCount++;
                        ensembleChecksum += (byteOne & 0xFF);

                        if (ensembleBuffer.remaining() > 0) {
                            ensembleBuffer.put(byteOne);

                        } else {
                            ensembleBuffer.compact();
                            ensembleBuffer.put(byteOne);

                        }

                        break;
                    }

                case 4: // find the offset to data type #1 and verify the header ID
                    if ((ensembleByteCount == dataTypeOneOffset + 1) && byteOne == 0x00 && byteTwo == 0x00) {
                        ensembleByteCount++;
                        ensembleChecksum += (byteOne & 0xFF);
                        // we are confident that the previous sequence of 0x7F7F is truly
                        // an headerID and not a random occurrence in the stream because
                        // we have identified the Fixed Leader ID (0x0000) the correct
                        // number of bytes beyond the 0x7F7F
                        headerIsVerified = true;

                        if (ensembleBuffer.remaining() > 0) {
                            ensembleBuffer.put(byteOne);

                        } else {
                            ensembleBuffer.compact();
                            ensembleBuffer.put(byteOne);

                        }

                        state = 5;
                        break;

                    } else {

                        if (ensembleByteCount > dataTypeOneOffset + 1) {
                            // We've hit a random 0x7F7F byte sequence that is not a true
                            // ensemble header id.  Reset the processing and look for the 
                            // next 0x7F7F sequence in the stream
                            ensembleByteCount = 0;
                            ensembleChecksum = 0;
                            dataTypeOneOffset = 0;
                            numberOfDataTypes = 0;
                            headerIsVerified = false;
                            ensembleBuffer.clear();
                            rbnbChannelMap.Clear();
                            channelIndex = rbnbChannelMap.Add(getRBNBChannelName());

                            byteOne = 0x00;
                            byteTwo = 0x00;
                            byteThree = 0x00;
                            byteFour = 0x00;

                            state = 0;

                            if (ensembleBuffer.remaining() > 0) {
                                ensembleBuffer.put(byteOne);

                            } else {
                                ensembleBuffer.compact();
                                ensembleBuffer.put(byteOne);

                            }

                            break;

                        } else {
                            // We are still parsing bytes between the purported header ID
                            // and fixed leader ID. Keep parsing until we hit the fixed
                            // leader ID, or until we are greater than the dataTypeOneOffset
                            // stated value.
                            ensembleByteCount++;
                            ensembleChecksum += (byteOne & 0xFF);

                            if (ensembleBuffer.remaining() > 0) {
                                ensembleBuffer.put(byteOne);

                            } else {
                                ensembleBuffer.compact();
                                ensembleBuffer.put(byteOne);

                            }

                            break;
                        }

                    }

                case 5: // read the rest of the bytes to the next Header ID 

                    // if we've made it to the next ensemble's header id, prepare to
                    // flush the data.  Also check that the calculated byte count 
                    // is greater than the recorded byte count in case of finding an
                    // arbitrary 0x7f 0x7f sequence in the data stream
                    if (byteOne == 0x7F && byteTwo == 0x7F && (ensembleByteCount == ensembleBytes + 3)
                            && headerIsVerified) {

                        // remove the last bytes from the count (byteOne and byteTwo)
                        ensembleByteCount -= 1;

                        // remove the last three bytes from the checksum: 
                        // the two checksum bytes are not included, and the two 0x7f 
                        //bytes belong to the next ensemble, and one of them was 
                        // previously added. Reset the buffer position due to this too.
                        //ensembleChecksum -= (byteOne   & 0xFF);
                        ensembleChecksum -= (byteTwo & 0xFF);
                        ensembleChecksum -= (byteThree & 0xFF);
                        ensembleChecksum -= (byteFour & 0xFF);
                        // We are consistently 1 byte over in the checksum.  Trim it.  We need to
                        // troubleshoot why this is. CSJ 12/18/2007
                        ensembleChecksum = ensembleChecksum - 1;

                        // jockey byteThree into LSB, byteFour into MSB
                        int upperChecksumByte = (byteThree & 0xFF) << 8;
                        int lowerChecksumByte = (byteFour & 0xFF);
                        int trueChecksum = upperChecksumByte + lowerChecksumByte;

                        if (ensembleBuffer.remaining() > 0) {
                            ensembleBuffer.put((byte) lowerChecksumByte);
                            ensembleBuffer.put((byte) (upperChecksumByte >> 8));
                        } else {
                            ensembleBuffer.compact();
                            ensembleBuffer.put((byte) lowerChecksumByte);
                            ensembleBuffer.put((byte) (upperChecksumByte >> 8));
                        }

                        // check if the calculated checksum (modulo 65535) is equal
                        // to the true checksum; if so, flush to the data turbine
                        // Also, if the checksums are off by 1 byte, also flush the
                        // data.  We need to troubleshoot this bug CSJ 06/11/2008
                        if (((ensembleChecksum % 65535) == trueChecksum)
                                || ((ensembleChecksum + 1) % 65535 == trueChecksum)
                                || ((ensembleChecksum - 1) % 65535 == trueChecksum)) {

                            // extract just the length of the ensemble bytes out of the
                            // ensemble buffer, and place it in the channel map as a 
                            // byte array.  Then, send it to the data turbine.
                            byte[] ensembleArray = new byte[ensembleByteCount];
                            ensembleBuffer.flip();
                            ensembleBuffer.get(ensembleArray);

                            // send the ensemble to the data turbine
                            rbnbChannelMap.PutTimeAuto("server");
                            rbnbChannelMap.PutDataAsByteArray(channelIndex, ensembleArray);
                            getSource().Flush(rbnbChannelMap);
                            logger.debug("flushed: " + ensembleByteCount + " " + "ens cksum: "
                                    + ensembleChecksum + "\t\t" + "ens pos: " + ensembleBuffer.position() + "\t"
                                    + "ens rem: " + ensembleBuffer.remaining() + "\t" + "buf pos: "
                                    + buffer.position() + "\t" + "buf rem: " + buffer.remaining() + "\t"
                                    + "state: " + state);
                            logger.info("Sent ADCP ensemble to the data turbine.");

                            // only clear all four bytes if we are not one or two bytes 
                            // from the end of the byte buffer (i.e. the header id 
                            // is split or is all in the previous buffer)
                            if (byteOne == 0x7f && byteTwo == 0x7f && ensembleByteCount > ensembleBytes
                                    && buffer.position() == 0) {
                                byteThree = 0x00;
                                byteFour = 0x00;
                                logger.debug("Cleared ONLY b3, b4.");
                            } else if (byteOne == 0x7f && ensembleByteCount > ensembleBytes
                                    && buffer.position() == 1) {
                                buffer.position(buffer.position() - 1);
                                byteTwo = 0x00;
                                byteThree = 0x00;
                                byteFour = 0x00;
                                logger.debug("Cleared ONLY b2, b3, b4.");

                            } else {
                                byteOne = 0x00;
                                byteTwo = 0x00;
                                byteThree = 0x00;
                                byteFour = 0x00;
                                logger.debug("Cleared ALL b1, b2, b3, b4.");
                            }

                            //rewind the position to before the next ensemble's header id
                            if (buffer.position() >= 2) {
                                buffer.position(buffer.position() - 2);
                                logger.debug("Moved position back two, now: " + buffer.position());
                            }

                            ensembleBuffer.clear();
                            ensembleByteCount = 0;
                            ensembleBytes = 0;
                            ensembleChecksum = 0;
                            state = 0;
                            break;

                        } else {

                            // The checksums don't match, move on 
                            logger.info("not equal: " + "calc chksum: " + (ensembleChecksum % 65535)
                                    + "\tens chksum: " + trueChecksum + "\tbuf pos: " + buffer.position()
                                    + "\tbuf rem: " + buffer.remaining() + "\tens pos: "
                                    + ensembleBuffer.position() + "\tens rem: " + ensembleBuffer.remaining()
                                    + "\tstate: " + state);

                            rbnbChannelMap.Clear();
                            channelIndex = rbnbChannelMap.Add(getRBNBChannelName());
                            ensembleBuffer.clear();
                            ensembleByteCount = 0;
                            ensembleChecksum = 0;
                            ensembleBuffer.clear();
                            state = 0;
                            break;
                        }

                    } else {

                        // still in the middle of the ensemble, keep adding bytes
                        ensembleByteCount++; // add each byte found
                        ensembleChecksum += (byteOne & 0xFF);

                        if (ensembleBuffer.remaining() > 0) {
                            ensembleBuffer.put(byteOne);

                        } else {
                            ensembleBuffer.compact();
                            ensembleBuffer.put(byteOne);

                        }

                        break;
                    }
                }
                // shift the bytes in the FIFO window
                byteFour = byteThree;
                byteThree = byteTwo;
                byteTwo = byteOne;

                logger.debug("remaining:\t" + buffer.remaining() + "\tstate:\t" + state + "\tens byte count:\t"
                        + ensembleByteCount + "\tens bytes:\t" + ensembleBytes + "\tver:\t" + headerIsVerified
                        + "\tbyte value:\t" + new String(Hex.encodeHex((new byte[] { byteOne }))));
            } //end while (more unread bytes)

            // prepare the buffer to read in more bytes from the stream
            buffer.compact();

        } // end while (more socket bytes to read)
        socket.close();

    } catch (IOException e) {
        // handle exceptions
        // In the event of an i/o exception, log the exception, and allow execute()
        // to return false, which will prompt a retry.
        failed = true;
        e.printStackTrace();
        return !failed;
    } catch (SAPIException sapie) {
        // In the event of an RBNB communication  exception, log the exception, 
        // and allow execute() to return false, which will prompt a retry.
        failed = true;
        sapie.printStackTrace();
        return !failed;
    }

    return !failed;
}