Beispiel #1
0
  @Override
  protected void doFlushMessageBuffer(Queue<Object> buf) throws Exception {
    if (state < 2) {
      throw new NotYetConnectedException();
    }
    if (state > 2) {
      throw new ClosedChannelException();
    }

    final LocalChannel peer = this.peer;
    assert peer != null;

    Queue<Object> out = peer.pipeline().inboundMessageBuffer();
    for (; ; ) {
      Object msg = buf.poll();
      if (msg == null) {
        break;
      }
      out.add(msg);
    }

    peer.eventLoop()
        .execute(
            new Runnable() {
              @Override
              public void run() {
                peer.pipeline().fireInboundBufferUpdated();
              }
            });
  }
Beispiel #2
0
  @Override
  protected void doClose() throws Exception {
    if (state > 2) {
      // Closed already
      return;
    }

    if (parent() == null) {
      LocalChannelRegistry.unregister(localAddress);
    }
    localAddress = null;
    state = 3;
    if (peer.isActive()) {
      peer.unsafe().close(peer.unsafe().voidFuture());
      peer = null;
    }
  }
Beispiel #3
0
  @Override
  protected void doWrite(ChannelOutboundBuffer in) throws Exception {
    switch (state) {
      case OPEN:
      case BOUND:
        throw new NotYetConnectedException();
      case CLOSED:
        throw new ClosedChannelException();
    }

    final LocalChannel peer = this.peer;
    final ChannelPipeline peerPipeline = peer.pipeline();
    final EventLoop peerLoop = peer.eventLoop();

    if (peerLoop == eventLoop()) {
      for (; ; ) {
        Object msg = in.current();
        if (msg == null) {
          break;
        }
        peer.inboundBuffer.add(msg);
        ReferenceCountUtil.retain(msg);
        in.remove();
      }
      finishPeerRead(peer, peerPipeline);
    } else {
      // Use a copy because the original msgs will be recycled by AbstractChannel.
      final Object[] msgsCopy = new Object[in.size()];
      for (int i = 0; i < msgsCopy.length; i++) {
        msgsCopy[i] = ReferenceCountUtil.retain(in.current());
        in.remove();
      }

      peerLoop.execute(
          new Runnable() {
            @Override
            public void run() {
              Collections.addAll(peer.inboundBuffer, msgsCopy);
              finishPeerRead(peer, peerPipeline);
            }
          });
    }
  }
Beispiel #4
0
  @Override
  protected void doRegister() throws Exception {
    // Check if both peer and parent are non-null because this channel was created by a
    // LocalServerChannel.
    // This is needed as a peer may not be null also if a LocalChannel was connected before and
    // deregistered / registered later again.
    //
    // See https://github.com/netty/netty/issues/2400
    if (peer != null && parent() != null) {
      // Store the peer in a local variable as it may be set to null if doClose() is called.
      // Because of this we also set registerInProgress to true as we check for this in doClose()
      // and make sure
      // we delay the fireChannelInactive() to be fired after the fireChannelActive() and so keep
      // the correct
      // order of events.
      //
      // See https://github.com/netty/netty/issues/2144
      final LocalChannel peer = this.peer;
      registerInProgress = true;
      state = State.CONNECTED;

      peer.remoteAddress = parent() == null ? null : parent().localAddress();
      peer.state = State.CONNECTED;

      // Always call peer.eventLoop().execute() even if peer.eventLoop().inEventLoop() is true.
      // This ensures that if both channels are on the same event loop, the peer's channelActive
      // event is triggered *after* this channel's channelRegistered event, so that this channel's
      // pipeline is fully initialized by ChannelInitializer before any channelRead events.
      peer.eventLoop()
          .execute(
              new Runnable() {
                @Override
                public void run() {
                  registerInProgress = false;
                  peer.pipeline().fireChannelActive();
                  peer.connectPromise.setSuccess();
                }
              });
    }
    ((SingleThreadEventExecutor) eventLoop()).addShutdownHook(shutdownHook);
  }
Beispiel #5
0
 private static void finishPeerRead(LocalChannel peer, ChannelPipeline peerPipeline) {
   if (peer.readInProgress) {
     peer.readInProgress = false;
     for (; ; ) {
       Object received = peer.inboundBuffer.poll();
       if (received == null) {
         break;
       }
       peerPipeline.fireChannelRead(received);
     }
     peerPipeline.fireChannelReadComplete();
   }
 }
Beispiel #6
0
  @Override
  protected void doClose() throws Exception {
    if (state != State.CLOSED) {
      // Update all internal state before the closeFuture is notified.
      if (localAddress != null) {
        if (parent() == null) {
          LocalChannelRegistry.unregister(localAddress);
        }
        localAddress = null;
      }
      state = State.CLOSED;
    }

    final LocalChannel peer = this.peer;
    if (peer != null && peer.isActive()) {
      // Need to execute the close in the correct EventLoop
      // See https://github.com/netty/netty/issues/1777
      EventLoop eventLoop = peer.eventLoop();

      // Also check if the registration was not done yet. In this case we submit the close to the
      // EventLoop
      // to make sure it is run after the registration completes.
      //
      // See https://github.com/netty/netty/issues/2144
      if (eventLoop.inEventLoop() && !registerInProgress) {
        peer.unsafe().close(unsafe().voidPromise());
      } else {
        peer.eventLoop()
            .execute(
                new Runnable() {
                  @Override
                  public void run() {
                    peer.unsafe().close(unsafe().voidPromise());
                  }
                });
      }
      this.peer = null;
    }
  }
Beispiel #7
0
  @Override
  protected Runnable doRegister() throws Exception {
    final LocalChannel peer = this.peer;
    Runnable postRegisterTask;

    if (peer != null) {
      state = 2;

      peer.remoteAddress = parent().localAddress();
      peer.state = 2;

      // Ensure the peer's channelActive event is triggered *after* this channel's
      // channelRegistered event is triggered, so that this channel's pipeline is fully
      // initialized by ChannelInitializer.
      final EventLoop peerEventLoop = peer.eventLoop();
      postRegisterTask =
          new Runnable() {
            @Override
            public void run() {
              peerEventLoop.execute(
                  new Runnable() {
                    @Override
                    public void run() {
                      peer.connectFuture.setSuccess();
                      peer.pipeline().fireChannelActive();
                    }
                  });
            }
          };
    } else {
      postRegisterTask = null;
    }

    ((SingleThreadEventLoop) eventLoop()).addShutdownHook(shutdownHook);

    return postRegisterTask;
  }
Beispiel #8
0
 LocalChannel(LocalServerChannel parent, EventLoop eventLoop, LocalChannel peer) {
   super(parent, eventLoop);
   this.peer = peer;
   localAddress = parent.localAddress();
   remoteAddress = peer.localAddress();
 }
Beispiel #9
0
 LocalChannel(LocalServerChannel parent, LocalChannel peer) {
   super(parent, null);
   this.peer = peer;
   localAddress = parent.localAddress();
   remoteAddress = peer.localAddress();
 }