private int fillReadBuffer(boolean block) throws IOException { int nRead; NioChannel channel = getSocket(); socketBufferHandler.configureReadBufferForWrite(); if (block) { Selector selector = null; try { selector = pool.get(); } catch (IOException x) { // Ignore } try { NioEndpoint.NioSocketWrapper att = (NioEndpoint.NioSocketWrapper) channel.getAttachment(); if (att == null) { throw new IOException("Key must be cancelled."); } nRead = pool.read( socketBufferHandler.getReadBuffer(), channel, selector, att.getReadTimeout()); } finally { if (selector != null) { pool.put(selector); } } } else { nRead = channel.read(socketBufferHandler.getReadBuffer()); if (nRead == -1) { throw new EOFException(); } } return nRead; }
/** * Registers a newly created socket with the poller. * * @param socket The newly created socket */ public void register(final NioChannel socket) { socket.setPoller(this); NioSocketWrapper ka = new NioSocketWrapper(socket, NioEndpoint.this); socket.setSocketWrapper(ka); ka.setPoller(this); ka.setReadTimeout(getSocketProperties().getSoTimeout()); ka.setWriteTimeout(getSocketProperties().getSoTimeout()); ka.setKeepAliveLeft(NioEndpoint.this.getMaxKeepAliveRequests()); ka.setSecure(isSSLEnabled()); ka.setReadTimeout(getSoTimeout()); ka.setWriteTimeout(getSoTimeout()); PollerEvent r = eventCache.pop(); ka.interestOps(SelectionKey.OP_READ); // this is what OP_REGISTER turns into. if (r == null) r = new PollerEvent(socket, ka, OP_REGISTER); else r.reset(socket, ka, OP_REGISTER); addEvent(r); }
/** * Add specified socket and associated pool to the poller. The socket will be added to a * temporary array, and polled first after a maximum amount of time equal to pollTime (in most * cases, latency will be much lower, however). * * @param socket to add to the poller * @param interestOps Operations for which to register this socket with the Poller */ public void add(final NioChannel socket, final int interestOps) { PollerEvent r = eventCache.pop(); if (r == null) r = new PollerEvent(socket, null, interestOps); else r.reset(socket, null, interestOps); addEvent(r); if (close) { NioEndpoint.NioSocketWrapper ka = (NioEndpoint.NioSocketWrapper) socket.getAttachment(); processSocket(ka, SocketEvent.STOP, false); } }
private void close(NioChannel socket, SelectionKey key) { try { if (socket.getPoller().cancelledKey(key) != null) { // SocketWrapper (attachment) was removed from the // key - recycle the key. This can only happen once // per attempted closure so it is used to determine // whether or not to return the key to the cache. // We do NOT want to do this more than once - see BZ // 57340 / 57943. if (running && !paused) { if (!nioChannels.push(socket)) { socket.free(); } } } } catch (Exception x) { log.error("", x); } }
@Override public void deliver(Channel channel, byte[] bytes) { ByteBuffer buffer = ByteBuffer.allocate(bytes.length); buffer.put(bytes); buffer.flip(); int length = buffer.getInt(); byte messageID = buffer.get(); switch (messageID) { case 0: byte[] deliver_array = new byte[length - 9]; int sender_id = buffer.getInt(); int lamport_timestamp = buffer.getInt(); buffer.get(deliver_array, 0, deliver_array.length); /*for (int i = 0; i < deliver_array.length; i++) { System.out.print(deliver_array[i] + " "); }*/ System.out.println("\n" + "---------------------------------------------------"); break; case 3: sender_id = buffer.getInt(); lamport_timestamp = buffer.getInt(); /*Si on est à l'origine du BroadcastJoin, on envoie d'abord la liste des autres peers avant de nous même se bloquer*/ if (engine.getId() == sender_id) { engine.setTimestamp(engine.getTimestamp() + 1); Message m = new MemberListMessage(engine.getTimestamp(), engine.getId(), engine.getPeersList()); byte[] message_array = m.sendMessage(); for (Channel other_channel : engine.getChannelList()) { if (((NioChannel) other_channel).isNouveauvenu()) { other_channel.send(message_array, 0, message_array.length); ((NioChannel) other_channel).setNouveauvenu(false); } } } ((NioChannel) channel).setBlocked(true); break; } }
/** * Process the specified connection. * * @param socket The socket channel * @return <code>true</code> if the socket was correctly configured and processing may continue, * <code>false</code> if the socket needs to be close immediately */ protected boolean setSocketOptions(SocketChannel socket) { // Process the connection try { // disable blocking, APR style, we are gonna be polling it socket.configureBlocking(false); Socket sock = socket.socket(); socketProperties.setProperties(sock); NioChannel channel = nioChannels.pop(); if (channel == null) { SocketBufferHandler bufhandler = new SocketBufferHandler( socketProperties.getAppReadBufSize(), socketProperties.getAppWriteBufSize(), socketProperties.getDirectBuffer()); if (isSSLEnabled()) { channel = new SecureNioChannel(socket, bufhandler, selectorPool, this); } else { channel = new NioChannel(socket, bufhandler); } } else { channel.setIOChannel(socket); channel.reset(); } getPoller0().register(channel); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); try { log.error("", t); } catch (Throwable tt) { ExceptionUtils.handleThrowable(tt); } // Tell to close the socket return false; } return true; }
@Override public void run() { if (interestOps == OP_REGISTER) { try { socket .getIOChannel() .register(socket.getPoller().getSelector(), SelectionKey.OP_READ, socketWrapper); } catch (Exception x) { log.error(sm.getString("endpoint.nio.registerFail"), x); } } else { final SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector()); try { if (key == null) { // The key was cancelled (e.g. due to socket closure) // and removed from the selector while it was being // processed. Count down the connections at this point // since it won't have been counted down when the socket // closed. socket.socketWrapper.getEndpoint().countDownConnection(); } else { final NioSocketWrapper socketWrapper = (NioSocketWrapper) key.attachment(); if (socketWrapper != null) { // we are registering the key to start with, reset the fairness counter. int ops = key.interestOps() | interestOps; socketWrapper.interestOps(ops); key.interestOps(ops); } else { socket.getPoller().cancelledKey(key); } } } catch (CancelledKeyException ckx) { try { socket.getPoller().cancelledKey(key); } catch (Exception ignore) { } } } }
public SendfileState processSendfile( SelectionKey sk, NioSocketWrapper socketWrapper, boolean calledByProcessor) { NioChannel sc = null; try { unreg(sk, socketWrapper, sk.readyOps()); SendfileData sd = socketWrapper.getSendfileData(); if (log.isTraceEnabled()) { log.trace("Processing send file for: " + sd.fileName); } if (sd.fchannel == null) { // Setup the file channel File f = new File(sd.fileName); if (!f.exists()) { cancelledKey(sk); return SendfileState.ERROR; } @SuppressWarnings("resource") // Closed when channel is closed FileInputStream fis = new FileInputStream(f); sd.fchannel = fis.getChannel(); } // Configure output channel sc = socketWrapper.getSocket(); // TLS/SSL channel is slightly different WritableByteChannel wc = ((sc instanceof SecureNioChannel) ? sc : sc.getIOChannel()); // We still have data in the buffer if (sc.getOutboundRemaining() > 0) { if (sc.flushOutbound()) { socketWrapper.updateLastWrite(); } } else { long written = sd.fchannel.transferTo(sd.pos, sd.length, wc); if (written > 0) { sd.pos += written; sd.length -= written; socketWrapper.updateLastWrite(); } else { // Unusual not to be able to transfer any bytes // Check the length was set correctly if (sd.fchannel.size() <= sd.pos) { throw new IOException( "Sendfile configured to " + "send more data than was available"); } } } if (sd.length <= 0 && sc.getOutboundRemaining() <= 0) { if (log.isDebugEnabled()) { log.debug("Send file complete for: " + sd.fileName); } socketWrapper.setSendfileData(null); try { sd.fchannel.close(); } catch (Exception ignore) { } // For calls from outside the Poller, the caller is // responsible for registering the socket for the // appropriate event(s) if sendfile completes. if (!calledByProcessor) { if (sd.keepAlive) { if (log.isDebugEnabled()) { log.debug("Connection is keep alive, registering back for OP_READ"); } reg(sk, socketWrapper, SelectionKey.OP_READ); } else { if (log.isDebugEnabled()) { log.debug("Send file connection is being closed"); } close(sc, sk); } } return SendfileState.DONE; } else { if (log.isDebugEnabled()) { log.debug("OP_WRITE for sendfile: " + sd.fileName); } if (calledByProcessor) { add(socketWrapper.getSocket(), SelectionKey.OP_WRITE); } else { reg(sk, socketWrapper, SelectionKey.OP_WRITE); } return SendfileState.PENDING; } } catch (IOException x) { if (log.isDebugEnabled()) log.debug("Unable to complete sendfile request:", x); if (!calledByProcessor && sc != null) { close(sc, sk); } else { cancelledKey(sk); } return SendfileState.ERROR; } catch (Throwable t) { log.error("", t); if (!calledByProcessor && sc != null) { close(sc, sk); } else { cancelledKey(sk); } return SendfileState.ERROR; } }
@Override protected void doRun() { NioChannel socket = socketWrapper.getSocket(); SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector()); try { int handshake = -1; try { if (key != null) { // For STOP there is no point trying to handshake as the // Poller has been stopped. if (socket.isHandshakeComplete() || event == SocketEvent.STOP) { handshake = 0; } else { handshake = socket.handshake(key.isReadable(), key.isWritable()); // The handshake process reads/writes from/to the // socket. status may therefore be OPEN_WRITE once // the handshake completes. However, the handshake // happens when the socket is opened so the status // must always be OPEN_READ after it completes. It // is OK to always set this as it is only used if // the handshake completes. event = SocketEvent.OPEN_READ; } } } catch (IOException x) { handshake = -1; if (log.isDebugEnabled()) log.debug("Error during SSL handshake", x); } catch (CancelledKeyException ckx) { handshake = -1; } if (handshake == 0) { SocketState state = SocketState.OPEN; // Process the request from this socket if (event == null) { state = getHandler().process(socketWrapper, SocketEvent.OPEN_READ); } else { state = getHandler().process(socketWrapper, event); } if (state == SocketState.CLOSED) { close(socket, key); } } else if (handshake == -1) { close(socket, key); } else if (handshake == SelectionKey.OP_READ) { socketWrapper.registerReadInterest(); } else if (handshake == SelectionKey.OP_WRITE) { socketWrapper.registerWriteInterest(); } } catch (CancelledKeyException cx) { socket.getPoller().cancelledKey(key); } catch (VirtualMachineError vme) { ExceptionUtils.handleThrowable(vme); } catch (Throwable t) { log.error("", t); socket.getPoller().cancelledKey(key); } finally { socketWrapper = null; event = null; // return to cache if (running && !paused) { processorCache.push(this); } } }
public NioSocketWrapper(NioChannel channel, NioEndpoint endpoint) { super(channel, endpoint); pool = endpoint.getSelectorPool(); socketBufferHandler = channel.getBufHandler(); }