public static IRubyObject doAccept(RubySocket sock, ThreadContext context, boolean ex) { Ruby runtime = context.runtime; Channel channel = sock.getChannel(); try { if (channel instanceof ServerSocketChannel) { ServerSocketChannel serverChannel = (ServerSocketChannel) sock.getChannel(); SocketChannel socket = serverChannel.accept(); if (socket == null) { // This appears to be undocumented in JDK; null as a sentinel value // for a nonblocking accept with nothing available. We raise for Ruby. // indicates that no connection is available in non-blocking mode if (!ex) return runtime.newSymbol("wait_readable"); throw runtime.newErrnoEAGAINReadableError("accept(2) would block"); } RubySocket rubySocket = new RubySocket(runtime, runtime.getClass("Socket")); rubySocket.initFromServer(runtime, sock, socket); return runtime.newArray( rubySocket, new Addrinfo(runtime, runtime.getClass("Addrinfo"), socket.getRemoteAddress())); } throw runtime.newErrnoENOPROTOOPTError(); } catch (IllegalBlockingModeException e) { // indicates that no connection is available in non-blocking mode if (!ex) return runtime.newSymbol("wait_readable"); throw runtime.newErrnoEAGAINReadableError("accept(2) would block"); } catch (IOException e) { throw sockerr(runtime, e.getLocalizedMessage(), e); } }
@Override public Void call() throws Exception { ServerSocketChannel clientConnection = (ServerSocketChannel) selectionKey.channel(); SocketChannel channel = clientConnection.accept(); if (channel != null) { channel.configureBlocking(false); LOGGER.info( String.format("%s accepted client connection from %s", name, channel.getRemoteAddress())); try { final HttpRequest.HttpRequestWrapper requestWrapper = requestParser.parse(read(channel)); MethodHandler handler = RequestHandlerFactory.newInstance(requestWrapper.getRequestLine().getMethod()); HttpResponse.HttpResponseWrapper responseWrapper = handler.handle(requestWrapper); write(channel, responseWrapper); } finally { channel.close(); } LOGGER.info(String.format("%s is done.", name)); } return null; }
/** Handle a read event from a socket specified by the key. */ private void read(SelectionKey key) throws IOException { SocketChannel socketChannel = (SocketChannel) key.channel(); SocketAddress remoteAdr = socketChannel.socket().getRemoteSocketAddress(); // Clear out our read buffer so it's ready for new data readBuffer.clear(); // Attempt to read off the channel int numRead; try { numRead = socketChannel.read(readBuffer); } catch (IOException e) { // The remote forcibly closed the connection, cancel // the selection key and close the channel. key.cancel(); socketChannel.close(); clients.remove(remoteAdr); pendingWriteData.remove(socketChannel); logger.fine( "Connection forcibly closed(" + remoteAdr + ")! Remaining connections: " + clients.size()); throw new IOException("Remote forcibly closed the connection"); } if (numRead == -1) { // Remote entity shut the socket down cleanly. Do the // same from our end and cancel the channel. key.channel().close(); key.cancel(); clients.remove(remoteAdr); pendingWriteData.remove(socketChannel); logger.fine("Connection Closed(" + remoteAdr + ")! Remaining connections: " + clients.size()); throw new IOException("Remote closed the connection"); } // Make a correctly sized copy of the data before handing it to the client // byte[] rspByteData = new byte[numRead]; // System.arraycopy(readBuffer.array(), 0, rspByteData, 0, numRead); try { Object rspData = Converter.toObject(readBuffer.array()); // Hand the data off to our worker thread if (worker != null) { logger.finer("Handling incoming message..."); worker.processData(this, socketChannel.getRemoteAddress(), rspData); } else { logger.fine("No worker set, message unhandled!"); } } catch (Exception e) { e.printStackTrace(); } }
private void write(SelectionKey key) throws IOException { SocketChannel socketChannel = (SocketChannel) key.channel(); // System.out.println("outsocketaddress: : // "+socketChannel.getRemoteAddress()); outgoingdata(socketChannel.getRemoteAddress().toString(), socketChannel, TcpTxTunnel); /* ByteBuffer dummyResponse = ByteBuffer.wrap("ok".getBytes("UTF-8")); socketChannel.write(dummyResponse); if (dummyResponse.remaining() > 0) { System.err.print("Filled UP"); }*/ key.interestOps(SelectionKey.OP_READ | SelectionKey.OP_WRITE); }
/** Finnish an ongoing remote connection establishment procedure */ private void establishConnection(SelectionKey key) { SocketChannel socketChannel = (SocketChannel) key.channel(); try { // Finalize/Finish the connection. socketChannel.finishConnect(); // Register an interest in writing on this channel key.interestOps(SelectionKey.OP_WRITE); registerSocketChannel(socketChannel); logger.fine("Connection established(" + socketChannel.getRemoteAddress() + ")"); } catch (IOException e) { // Cancel the channel's registration with our selector e.printStackTrace(); key.cancel(); } }
/** Handle an accept event from a remote host. Channel can only be a server socket. */ private void accept(SelectionKey key) throws IOException { // For an accept to be pending the channel must be a server socket channel. ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel(); // Accept the connection and make it non-blocking SocketChannel socketChannel = serverSocketChannel.accept(); socketChannel.socket().setReuseAddress(true); socketChannel.configureBlocking(false); // Register the new SocketChannel with our Selector, indicating // we'd like to be notified when there's data waiting to be read socketChannel.register(selector, SelectionKey.OP_READ); // adds the client to the clients list registerSocketChannel(socketChannel); logger.fine( "New Connection(" + socketChannel.getRemoteAddress() + ")!!! Count: " + clients.size()); }
private void processSelectedKeys() { for (SelectionKey key : selector.selectedKeys()) { try { if (!key.isValid()) continue; if (key.isAcceptable()) { SocketChannel acceptedChannel = serverChannel.accept(); if (acceptedChannel == null) continue; acceptedChannel.configureBlocking(false); SelectionKey readKey = acceptedChannel.register(selector, SelectionKey.OP_READ); MainServer.clientMap.put(readKey, new ClientSession(readKey, acceptedChannel)); LOG.info( "New client ip=" + acceptedChannel.getRemoteAddress() + ", total clients=" + MainServer.clientMap.size()); } else if (key.isReadable()) { ClientSession sesh = MainServer.getClientMap().get(key); if (sesh == null) continue; reader.read(sesh); } else if (key.isWritable()) { ClientSession sesh = MainServer.getClientMap().get(key); if (sesh == null) continue; sender.send(sesh); } } catch (Throwable t) { LOG.severe("NetServerThread exception: " + t.getMessage()); } } }
private void read(SelectionKey key) throws IOException { SocketChannel socketChannel = (SocketChannel) key.channel(); // Clear out our read buffer so it's ready for new data readBuffer.clear(); // Attempt to read off the channel int numRead; try { numRead = socketChannel.read(readBuffer); } catch (IOException e) { key.cancel(); socketChannel.close(); System.out.println("Forceful shutdown"); return; } if (numRead == -1) { System.out.println("Graceful shutdown"); key.channel().close(); key.cancel(); return; } // System.out.println("TEST: "+socketChannel.getRemoteAddress()+ "DATA: "+ // readBuffer.toString()); incomingdata(socketChannel.getRemoteAddress().toString(), readBuffer, TcpRxTunnel); socketChannel.register(selector, SelectionKey.OP_WRITE); numMessages++; if (numMessages % 100000 == 0) { long elapsed = System.currentTimeMillis() - loopTime; loopTime = System.currentTimeMillis(); System.out.println(elapsed); } }
@Override public SocketAddress getRemoteAddress() throws IOException { return socketChannel.getRemoteAddress(); }