示例#1
0
    @Override
    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {

      final NioSocketChannel ch = (NioSocketChannel) e.getChannel();
      NioWorker worker = ch.getWorker();

      // Choose a handler
      final HandlerHolder handler = handlerManager.chooseHandler(worker);

      if (handler == null) {
        // Ignore
        return;
      }

      VertxInternal.instance.executeOnContext(
          handler.contextID,
          new Runnable() {
            public void run() {
              VertxInternal.instance.setContextID(handler.contextID);
              NetSocket sock = new NetSocket(ch, handler.contextID, Thread.currentThread());
              socketMap.put(ch, sock);
              handler.handler.handle(sock);
            }
          });
    }
示例#2
0
  static void close(NioSocketChannel channel, ChannelFuture future) {
    NioWorker worker = channel.worker;

    boolean connected = channel.isConnected();
    boolean bound = channel.isBound();
    try {
      channel.socket.close();
      worker.cancelledKeys++;

      if (channel.setClosed()) {
        future.setSuccess();
        if (connected) {
          fireChannelDisconnected(channel);
        }
        if (bound) {
          fireChannelUnbound(channel);
        }

        cleanUpWriteBuffer(channel);
        fireChannelClosed(channel);
      } else {
        future.setSuccess();
      }
    } catch (Throwable t) {
      future.setFailure(t);
      fireExceptionCaught(channel, t);
    }
  }
示例#3
0
  private static void clearOpWrite(NioSocketChannel channel) {
    NioWorker worker = channel.worker;
    Selector selector = worker.selector;
    SelectionKey key = channel.socket.keyFor(selector);
    if (key == null) {
      return;
    }
    if (!key.isValid()) {
      close(key);
      return;
    }
    int interestOps;
    boolean changed = false;

    // interestOps can change at any time and at any thread.
    // Acquire a lock to avoid possible race condition.
    synchronized (channel.interestOpsLock) {
      interestOps = channel.getRawInterestOps();
      if ((interestOps & SelectionKey.OP_WRITE) != 0) {
        interestOps &= ~SelectionKey.OP_WRITE;
        key.interestOps(interestOps);
        changed = true;
      }
    }

    if (changed) {
      channel.setRawInterestOpsNow(interestOps);
    }
  }
示例#4
0
  @Override
  protected boolean read(SelectionKey k) {
    final SocketChannel ch = (SocketChannel) k.channel();
    final NioSocketChannel channel = (NioSocketChannel) k.attachment();

    final ReceiveBufferSizePredictor predictor =
        channel.getConfig().getReceiveBufferSizePredictor();
    final int predictedRecvBufSize = predictor.nextReceiveBufferSize();

    int ret = 0;
    int readBytes = 0;
    boolean failure = true;

    ByteBuffer bb = recvBufferPool.acquire(predictedRecvBufSize);
    try {
      while ((ret = ch.read(bb)) > 0) {
        readBytes += ret;
        if (!bb.hasRemaining()) {
          break;
        }
      }
      failure = false;
    } catch (ClosedChannelException e) {
      // Can happen, and does not need a user attention.
    } catch (Throwable t) {
      fireExceptionCaught(channel, t);
    }

    if (readBytes > 0) {
      bb.flip();

      final ChannelBufferFactory bufferFactory = channel.getConfig().getBufferFactory();
      final ChannelBuffer buffer = bufferFactory.getBuffer(readBytes);
      buffer.setBytes(0, bb);
      buffer.writerIndex(readBytes);

      recvBufferPool.release(bb);

      // Update the predictor.
      predictor.previousReceiveBufferSize(readBytes);

      // Fire the event.
      fireMessageReceived(channel, buffer);
    } else {
      recvBufferPool.release(bb);
    }

    if (ret < 0 || failure) {
      k.cancel(); // Some JDK implementations run into an infinite loop without this.
      close(channel, succeededFuture(channel));
      return false;
    }

    return true;
  }
示例#5
0
  private static void cleanUpWriteBuffer(NioSocketChannel channel) {
    Exception cause = null;
    boolean fireExceptionCaught = false;

    // Clean up the stale messages in the write buffer.
    synchronized (channel.writeLock) {
      MessageEvent evt = channel.currentWriteEvent;
      if (evt != null) {
        channel.currentWriteEvent = null;
        channel.currentWriteIndex = 0;

        // Create the exception only once to avoid the excessive overhead
        // caused by fillStackTrace.
        if (channel.isOpen()) {
          cause = new NotYetConnectedException();
        } else {
          cause = new ClosedChannelException();
        }
        evt.getFuture().setFailure(cause);
        fireExceptionCaught = true;
      }

      Queue<MessageEvent> writeBuffer = channel.writeBuffer;
      if (!writeBuffer.isEmpty()) {
        // Create the exception only once to avoid the excessive overhead
        // caused by fillStackTrace.
        if (cause == null) {
          if (channel.isOpen()) {
            cause = new NotYetConnectedException();
          } else {
            cause = new ClosedChannelException();
          }
        }

        for (; ; ) {
          evt = writeBuffer.poll();
          if (evt == null) {
            break;
          }
          evt.getFuture().setFailure(cause);
          fireExceptionCaught = true;
        }
      }
    }

    if (fireExceptionCaught) {
      fireExceptionCaught(channel, cause);
    }
  }
示例#6
0
  static void write(final NioSocketChannel channel, boolean mightNeedWakeup) {
    if (!channel.isConnected()) {
      cleanUpWriteBuffer(channel);
      return;
    }

    if (mightNeedWakeup && scheduleWriteIfNecessary(channel)) {
      return;
    }

    if (channel.inWriteNowLoop) {
      scheduleWriteIfNecessary(channel);
    } else {
      writeNow(channel, channel.getConfig().getWriteSpinCount());
    }
  }
示例#7
0
 @Override
 public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
   final NioSocketChannel ch = (NioSocketChannel) e.getChannel();
   final NetSocket sock = socketMap.get(ch);
   ch.close();
   final Throwable t = e.getCause();
   if (sock != null && t instanceof Exception) {
     VertxInternal.instance.executeOnContext(
         sock.getContextID(),
         new Runnable() {
           public void run() {
             sock.handleException((Exception) t);
           }
         });
   } else {
     t.printStackTrace();
   }
 }
示例#8
0
  private static boolean read(SelectionKey k) {
    ScatteringByteChannel ch = (ScatteringByteChannel) k.channel();
    NioSocketChannel channel = (NioSocketChannel) k.attachment();

    ReceiveBufferSizePredictor predictor = channel.getConfig().getReceiveBufferSizePredictor();
    ChannelBufferFactory bufferFactory = channel.getConfig().getBufferFactory();

    ChannelBuffer buffer = bufferFactory.getBuffer(predictor.nextReceiveBufferSize());

    int ret = 0;
    int readBytes = 0;
    boolean failure = true;
    try {
      while ((ret = buffer.writeBytes(ch, buffer.writableBytes())) > 0) {
        readBytes += ret;
        if (!buffer.writable()) {
          break;
        }
      }
      failure = false;
    } catch (AsynchronousCloseException e) {
      // Can happen, and does not need a user attention.
    } catch (Throwable t) {
      fireExceptionCaught(channel, t);
    }

    if (readBytes > 0) {
      // Update the predictor.
      predictor.previousReceiveBufferSize(readBytes);

      // Fire the event.
      fireMessageReceived(channel, buffer);
    }

    if (ret < 0 || failure) {
      close(k);
      return false;
    }

    return true;
  }
示例#9
0
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
      final NioSocketChannel ch = (NioSocketChannel) e.getChannel();
      final NetSocket sock = socketMap.remove(ch);
      ch.close();
      final Throwable t = e.getCause();

      log.error("Exception on netserver", t);

      if (sock != null && t instanceof Exception) {
        sock.getContext()
            .execute(
                new Runnable() {
                  public void run() {
                    sock.handleException((Exception) t);
                  }
                });
      } else {
        // Ignore - any exceptions not associated with any sock (e.g. failure in ssl handshake) will
        // be communicated explicitly
      }
    }
示例#10
0
    public void run() {
      SocketAddress localAddress = channel.getLocalAddress();
      SocketAddress remoteAddress = channel.getRemoteAddress();

      if (localAddress == null || remoteAddress == null) {
        if (future != null) {
          future.setFailure(new ClosedChannelException());
        }
        close(channel, succeededFuture(channel));
        return;
      }

      try {
        if (server) {
          channel.channel.configureBlocking(false);
        }

        synchronized (channel.interestOpsLock) {
          channel.channel.register(selector, channel.getRawInterestOps(), channel);
        }
        if (future != null) {
          channel.setConnected();
          future.setSuccess();
        }

        if (server || !((NioClientSocketChannel) channel).boundManually) {
          fireChannelBound(channel, localAddress);
        }
        fireChannelConnected(channel, remoteAddress);
      } catch (IOException e) {
        if (future != null) {
          future.setFailure(e);
        }
        close(channel, succeededFuture(channel));
        if (!(e instanceof ClosedChannelException)) {
          throw new ChannelException("Failed to register a socket to the selector.", e);
        }
      }
    }
示例#11
0
    @Override
    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {

      final NioSocketChannel ch = (NioSocketChannel) e.getChannel();
      NioWorker worker = ch.getWorker();

      // Choose a handler
      final HandlerHolder handler = handlerManager.chooseHandler(worker);

      if (handler == null) {
        // Ignore
        return;
      }

      if (tcpHelper.isSSL()) {
        SslHandler sslHandler = (SslHandler) ch.getPipeline().get("ssl");

        ChannelFuture fut = sslHandler.handshake();
        fut.addListener(
            new ChannelFutureListener() {

              public void operationComplete(ChannelFuture channelFuture) throws Exception {
                if (channelFuture.isSuccess()) {
                  connected(ch, handler);
                } else {
                  log.error(
                      "Client from origin "
                          + ch.getRemoteAddress()
                          + " failed to connect over ssl");
                }
              }
            });

      } else {
        connected(ch, handler);
      }
    }
示例#12
0
 /*
 Currently Netty does not provide all events for a connection on the same thread - e.g. connection open
 connection bound etc are provided on the acceptor thread.
 In vert.x we must ensure all events are executed on the correct event loop for the context
 This code will go away if Netty acts like a proper event loop.
  */
 public void runOnCorrectThread(NioSocketChannel nch, Runnable runnable) {
   nch.getWorker().executeInIoThread(runnable, false);
 }
示例#13
0
  static void setInterestOps(NioSocketChannel channel, ChannelFuture future, int interestOps) {
    boolean changed = false;
    try {
      // interestOps can change at any time and at any thread.
      // Acquire a lock to avoid possible race condition.
      synchronized (channel.interestOpsLock) {
        NioWorker worker = channel.worker;
        Selector selector = worker.selector;
        SelectionKey key = channel.socket.keyFor(selector);

        if (key == null || selector == null) {
          // Not registered to the worker yet.
          // Set the rawInterestOps immediately; RegisterTask will pick it up.
          channel.setRawInterestOpsNow(interestOps);
          return;
        }

        // Override OP_WRITE flag - a user cannot change this flag.
        interestOps &= ~Channel.OP_WRITE;
        interestOps |= channel.getRawInterestOps() & Channel.OP_WRITE;

        switch (CONSTRAINT_LEVEL) {
          case 0:
            if (channel.getRawInterestOps() != interestOps) {
              key.interestOps(interestOps);
              if (Thread.currentThread() != worker.thread
                  && worker.wakenUp.compareAndSet(false, true)) {
                selector.wakeup();
              }
              changed = true;
            }
            break;
          case 1:
          case 2:
            if (channel.getRawInterestOps() != interestOps) {
              if (Thread.currentThread() == worker.thread) {
                key.interestOps(interestOps);
                changed = true;
              } else {
                worker.selectorGuard.readLock().lock();
                try {
                  if (worker.wakenUp.compareAndSet(false, true)) {
                    selector.wakeup();
                  }
                  key.interestOps(interestOps);
                  changed = true;
                } finally {
                  worker.selectorGuard.readLock().unlock();
                }
              }
            }
            break;
          default:
            throw new Error();
        }
      }

      future.setSuccess();
      if (changed) {
        channel.setRawInterestOpsNow(interestOps);
        fireChannelInterestChanged(channel);
      }
    } catch (CancelledKeyException e) {
      // setInterestOps() was called on a closed channel.
      ClosedChannelException cce = new ClosedChannelException();
      future.setFailure(cce);
      fireExceptionCaught(channel, cce);
    } catch (Throwable t) {
      future.setFailure(t);
      fireExceptionCaught(channel, t);
    }
  }
示例#14
0
  private static void writeNow(NioSocketChannel channel, int writeSpinCount) {

    boolean open = true;
    boolean addOpWrite = false;
    boolean removeOpWrite = false;

    MessageEvent evt;
    ChannelBuffer buf;
    int bufIdx;
    int writtenBytes = 0;

    Queue<MessageEvent> writeBuffer = channel.writeBuffer;
    synchronized (channel.writeLock) {
      channel.inWriteNowLoop = true;
      evt = channel.currentWriteEvent;
      for (; ; ) {
        if (evt == null) {
          evt = writeBuffer.poll();
          if (evt == null) {
            channel.currentWriteEvent = null;
            removeOpWrite = true;
            break;
          }

          evt = consolidateComposite(evt);
          buf = (ChannelBuffer) evt.getMessage();
          bufIdx = buf.readerIndex();
        } else {
          buf = (ChannelBuffer) evt.getMessage();
          bufIdx = channel.currentWriteIndex;
        }

        try {
          for (int i = writeSpinCount; i > 0; i--) {
            int localWrittenBytes =
                buf.getBytes(bufIdx, channel.socket, buf.writerIndex() - bufIdx);

            if (localWrittenBytes != 0) {
              bufIdx += localWrittenBytes;
              writtenBytes += localWrittenBytes;
              break;
            }
          }

          if (bufIdx == buf.writerIndex()) {
            // Successful write - proceed to the next message.
            channel.currentWriteEvent = null;
            evt.getFuture().setSuccess();
            evt = null;
          } else {
            // Not written fully - perhaps the kernel buffer is full.
            channel.currentWriteEvent = evt;
            channel.currentWriteIndex = bufIdx;
            addOpWrite = true;
            break;
          }
        } catch (AsynchronousCloseException e) {
          // Doesn't need a user attention - ignore.
          channel.currentWriteEvent = evt;
          channel.currentWriteIndex = bufIdx;
        } catch (Throwable t) {
          channel.currentWriteEvent = null;
          evt.getFuture().setFailure(t);
          evt = null;
          fireExceptionCaught(channel, t);
          if (t instanceof IOException) {
            open = false;
            close(channel, succeededFuture(channel));
          }
        }
      }
      channel.inWriteNowLoop = false;
    }

    fireWriteComplete(channel, writtenBytes);

    if (open) {
      if (addOpWrite) {
        setOpWrite(channel);
      } else if (removeOpWrite) {
        clearOpWrite(channel);
      }
    }
  }