@Override protected void doProcessing() { SocketChannel socketChannel; while ((socketChannel = accepted.poll()) != null) { U.debug("incoming connection", "address", socketChannel.socket().getRemoteSocketAddress()); try { SelectionKey newKey = socketChannel.register(selector, SelectionKey.OP_READ); RapidoidConnection conn = connections.get(); conn.key = newKey; if (isProtocolListener) { conn.setListener((ConnectionListener) protocol); } newKey.attach(conn); } catch (ClosedChannelException e) { U.warn("Closed channel", e); } } synchronized (done) { for (int i = 0; i < done.size(); i++) { RapidoidConnection conn = done.get(i); if (conn.key != null && conn.key.isValid()) { conn.key.interestOps(SelectionKey.OP_WRITE); } } done.clear(); } }
@Override protected void writeOP(SelectionKey key) throws IOException { RapidoidConnection conn = (RapidoidConnection) key.attachment(); SocketChannel socketChannel = (SocketChannel) key.channel(); checkOnSameThread(); try { int wrote = conn.output.writeTo(socketChannel); conn.output.deleteBefore(wrote); boolean complete = conn.output.size() == 0; if (conn.closeAfterWrite() && complete) { close(conn); } else { if (complete) { key.interestOps(SelectionKey.OP_READ); } else { key.interestOps(SelectionKey.OP_READ + SelectionKey.OP_WRITE); } conn.wrote(complete); } } catch (IOException e) { close(conn); } }
private void close(SelectionKey key) { try { RapidoidConnection conn = (RapidoidConnection) key.attachment(); if (key.isValid()) { SocketChannel socketChannel = (SocketChannel) key.channel(); socketChannel.close(); key.attach(null); key.cancel(); } if (conn != null) { if (!conn.closed) { U.trace("Closing connection", "connection", conn); conn.closed = true; assert conn.key == key; conn.key = null; connections.release(conn); } } } catch (IOException e) { e.printStackTrace(); } }
private int processMsgs(RapidoidConnection conn) { int reqN = 0; while (reqN < MAX_PIPELINED && conn.input().hasRemaining() && processNext(conn)) { reqN++; } return reqN; }
@Override protected void readOP(SelectionKey key) throws IOException { SocketChannel socketChannel = (SocketChannel) key.channel(); RapidoidConnection conn = (RapidoidConnection) key.attachment(); int read; try { read = conn.input.append(socketChannel); } catch (Exception e) { read = -1; } if (read == -1) { // the other end closed the connection close(key); return; } processMsgs(conn); conn.completedInputPos = conn.input.position(); }
private boolean processNext(RapidoidConnection conn) { int pos = conn.input().position(); int limit = conn.input().limit(); try { protocol.process(conn); return true; } catch (IncompleteReadException e) { // input not ready, so recover conn.input().position(pos); conn.input().limit(limit); // FIXME recover output position } catch (ProtocolException e) { conn.write(U.or(e.getMessage(), "Protocol error!")); conn.error(); conn.close(true); } catch (Throwable e) { U.error("Failed to process message!", e); conn.close(true); } return false; }