/** * Connection will be closed [onlyClose()] and onDisconnect() method will be executed on another * thread [DisconnectionThreadPool] after getDisconnectionDelay() time in ms. This method may only * be called by current Dispatcher Thread. * * @param con */ protected final void closeConnectionImpl(AConnection con) { /** * Test if this build should use assertion. If NetworkAssertion == false javac will remove this * code block */ if (Assertion.NetworkAssertion) assert Thread.currentThread() == this; if (con.onlyClose()) dcPool.scheduleDisconnection(new DisconnectionTask(con), con.getDisconnectionDelay()); }
/** * Parse data from buffer and prepare buffer for reading just one packet - call * processData(ByteBuffer b). * * @param con Connection * @param buf Buffer with packet data * @return True if packet was parsed. */ private boolean parse(AConnection con, ByteBuffer buf) { short sz = 0; try { sz = buf.getShort(); if (sz > 1) sz -= 2; ByteBuffer b = (ByteBuffer) buf.slice().limit(sz); b.order(ByteOrder.LITTLE_ENDIAN); /** read message fully */ buf.position(buf.position() + sz); return con.processData(b); } catch (IllegalArgumentException e) { log.warn( "Error on parsing input from client - account: " + con + " packet size: " + sz + " real size:" + buf.remaining(), e); return false; } }
/** * Write as much as possible data to socketChannel represented by SelectionKey key. If all data * were written key write interest will be disabled. * * @param key */ final void write(SelectionKey key) { SocketChannel socketChannel = (SocketChannel) key.channel(); AConnection con = (AConnection) key.attachment(); int numWrite; ByteBuffer wb = con.writeBuffer; /** We have not writted data */ if (wb.hasRemaining()) { try { numWrite = socketChannel.write(wb); } catch (IOException e) { closeConnectionImpl(con); return; } if (numWrite == 0) { log.info("Write " + numWrite + " ip: " + con.getIP()); return; } /** Again not all data was send */ if (wb.hasRemaining()) return; } while (true) { wb.clear(); boolean writeFailed = !con.writeData(wb); if (writeFailed) { wb.limit(0); break; } /** Attempt to write to the channel */ try { numWrite = socketChannel.write(wb); } catch (IOException e) { closeConnectionImpl(con); return; } if (numWrite == 0) { log.info("Write " + numWrite + " ip: " + con.getIP()); return; } /** not all data was send */ if (wb.hasRemaining()) return; } /** * Test if this build should use assertion. If NetworkAssertion == false javac will remove this * code block */ if (Assertion.NetworkAssertion) { assert !wb.hasRemaining(); } /** We wrote away all data, so we're no longer interested in writing on this socket. */ key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE); /** We wrote all data so we can close connection that is "PandingClose" */ if (con.isPendingClose()) closeConnectionImpl(con); }
/** * Register new client connected to this Dispatcher and set SelectionKey (result of registration) * as this key of given AConnection. * * @param ch * @param ops * @param att * @throws IOException */ public final void register(SelectableChannel ch, int ops, AConnection att) throws IOException { synchronized (gate) { selector.wakeup(); att.setKey(ch.register(selector, ops, att)); } }