示例#1
0
        @Override
        protected void doSessionOpened(HttpSession readSession) throws Exception {
          IoFilterChain filterChain = readSession.getFilterChain();
          filterChain.addLast(CODEC_FILTER, new WsebFrameCodecFilter(0));

          ResourceAddress readAddress = readSession.getRemoteAddress();
          final WsebSession wsebSession = sessionMap.get(readAddress);
          assert (wsebSession != null);
          wsebSession.attachReader(readSession);

          if (wsebSession.getInactivityTimeout() > 0) {
            // Activate inactivity timeout only once read session is established
            currentSessionInactivityTracker.get().addSession(wsebSession);
          }

          readSession
              .getCloseFuture()
              .addListener(
                  new IoFutureListener<CloseFuture>() {
                    @Override
                    public void operationComplete(CloseFuture future) {
                      wsebSession.close(true);
                    }
                  });
        }
示例#2
0
  @Override
  protected void doMessageReceived(HttpAcceptSession session, Object message) throws Exception {
    // this can happen if there is an error
    if (!(message instanceof WsMessage)) {
      return;
    }

    WsebSession wsebSession = getSession(session);
    WsMessage wsebMessage = (WsMessage) message;
    IoFilterChain filterChain = wsebSession.getTransportSession().getFilterChain();

    switch (wsebMessage.getKind()) {
      case COMMAND:
        for (Command command : ((WsCommandMessage) wsebMessage).getCommands()) {
          if (command == Command.close()) {
            session.setWriteHeader(HEADER_CONTENT_LENGTH, "0");
            session.close(false);
            filterChain.fireMessageReceived(new WsCloseMessage());
            break;
          } else if (command == Command.reconnect()) {
            session.setWriteHeader(HEADER_CONTENT_LENGTH, "0");
            session.close(false);
            break;
          }
          // no-op (0x00) - continue reading commands
        }
        break;
      default:
        filterChain.fireMessageReceived(wsebMessage);
        break;
    }
  }
  public void addBridgeFilters(IoFilterChain bridgeFilterChain, WsebSession wsebSession) {
    bridgeFilterChain.addLast(CODEC_FILTER, codec);

    if (encoding != null) {
      bridgeFilterChain.addBefore(CODEC_FILTER, ENCODING_FILTER, encoding);
    }
  }
 @Override
 public void onPreAdd(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception {
   if (parent.contains(this)) {
     throw new IllegalArgumentException(
         "You can't add the same filter instance more than once.  Create another instance and add it.");
   }
   parent.getSession().setAttribute(STATE, new State());
   adjustReadBufferSize(parent.getSession());
 }
示例#5
0
  @Override
  public void onPreAdd(IoFilterChain parent, String name, NextFilter nextFilter) throws Exception {
    if (parent.contains(this)) {
      throw new IllegalArgumentException(
          "You can't add the same filter instance more than once.  Create another instance and add it.");
    }

    // Initialize the encoder and decoder
    initCodec(parent.getSession());
  }
示例#6
0
 @Override
 public void addBridgeFilters(IoFilterChain filterChain) {
   // setup logging filters for bridge session
   if (logger.isTraceEnabled()) {
     filterChain.addFirst(
         TRACE_LOGGING_FILTER, new ObjectLoggingFilter(logger, WsebProtocol.NAME + "#%s"));
   } else {
     filterChain.addFirst(
         FAULT_LOGGING_FILTER, new ExceptionLoggingFilter(logger, WsebProtocol.NAME + "#%s"));
   }
 }
示例#7
0
 public void addCompression() {
   IoFilterChain chain = ioSession.getFilterChain();
   String baseFilter = EXECUTOR_FILTER_NAME;
   if (chain.contains(TLS_FILTER_NAME)) {
     baseFilter = TLS_FILTER_NAME;
   }
   chain.addAfter(
       baseFilter,
       COMPRESSION_FILTER_NAME,
       new CompressionFilter(true, false, CompressionFilter.COMPRESSION_MAX));
 }
  /** Write all the pending messages */
  private void flush(long currentTime) {
    if (flushingSessions.isEmpty()) {
      return;
    }

    do {
      S session = flushingSessions.poll(); // the same one with firstSession

      if (session == null) {
        // Just in case ... It should not happen.
        break;
      }

      // Reset the Schedule for flush flag for this session,
      // as we are flushing it now
      session.unscheduledForFlush();

      SessionState state = getState(session);

      switch (state) {
        case OPENED:
          try {
            boolean flushedAll = flushNow(session, currentTime);

            if (flushedAll
                && !session.getWriteRequestQueue().isEmpty(session)
                && !session.isScheduledForFlush()) {
              scheduleFlush(session);
            }
          } catch (Exception e) {
            scheduleRemove(session);
            IoFilterChain filterChain = session.getFilterChain();
            filterChain.fireExceptionCaught(e);
          }

          break;

        case CLOSING:
          // Skip if the channel is already closed.
          break;

        case OPENING:
          // Retry later if session is not yet fully initialized.
          // (In case that Session.write() is called before addSession()
          // is processed)
          scheduleFlush(session);
          return;

        default:
          throw new IllegalStateException(String.valueOf(state));
      }

    } while (!flushingSessions.isEmpty());
  }
示例#9
0
  @Override
  public void onPreAdd(IoFilterChain parent, String name, NextFilter nextFilter)
      throws SSLException {
    if (parent.contains(SslFilter.class)) {
      throw new IllegalStateException("Only one " + SslFilter.class.getName() + " is permitted.");
    }

    IoSession session = parent.getSession();
    session.setAttribute(NEXT_FILTER, nextFilter);

    // Create an SSL handler and start handshake.
    SslHandler handler = new SslHandler(this, sslContext, (IoSessionEx) session, logger);
    session.setAttribute(SSL_HANDLER, handler);
  }
  private boolean removeNow(S session) {
    clearWriteRequestQueue(session);

    try {
      destroy(session);
      return true;
    } catch (Exception e) {
      IoFilterChain filterChain = session.getFilterChain();
      filterChain.fireExceptionCaught(e);
    } finally {
      clearWriteRequestQueue(session);
      ((AbstractIoService) session.getService()).getListeners().fireSessionDestroyed(session);
    }
    return false;
  }
示例#11
0
  @Override
  protected void doSessionOpened(final HttpAcceptSession session) throws Exception {
    WsebSession wsebSession = getSession(session);
    if (wsebSession == null || wsebSession.isClosing()) {
      session.close(false);
      return;
    }

    IoFilterChain filterChain = session.getFilterChain();

    filterChain.addLast(CODEC_FILTER, codec);

    // only supported for non-binary upstream
    if (utf8 != null) {
      // Note: encoding filter needs to be closer to the network than the codec filter
      String contentType = session.getReadHeader(HEADER_CONTENT_TYPE);
      if (CONTENT_TYPE_TEXT_PLAIN_CHARSET_UTF_8.equalsIgnoreCase(contentType)) {
        filterChain.addBefore(CODEC_FILTER, UTF8_FILTER, utf8);
      }
    }

    final CloseFuture wsebCloseFuture = wsebSession.getCloseFuture();
    final IoFutureListener<CloseFuture> listener =
        new IoFutureListener<CloseFuture>() {
          @Override
          public void operationComplete(CloseFuture future) {
            // Note: this reference to HTTP session is pinned by listener
            //       and must be removed to avoid a memory leak (see below)
            session.close(false);
          }
        };
    // detect when emulated session is closed to force upstream to close
    wsebCloseFuture.addListener(listener);
    // detect when upstream is closed to remove upstream reference from emulated session
    session
        .getCloseFuture()
        .addListener(
            new IoFutureListener<CloseFuture>() {
              @Override
              public void operationComplete(CloseFuture future) {
                // Note: a reference to the HTTP upstream session is pinned by listener
                //       and must be removed to avoid a memory leak (see above)
                wsebCloseFuture.removeListener(listener);
              }
            });

    wsebSession.attachReader(session);
  }
示例#12
0
 @Override
 public void onPostAdd(IoFilterChain parent, String name, NextFilter nextFilter)
     throws SSLException {
   if (autoStart) {
     initiateHandshake(nextFilter, parent.getSession());
   }
 }
  /** {@inheritDoc} */
  public void updateTrafficControl(S session) {
    //
    try {
      setInterestedInRead(session, !session.isReadSuspended());
    } catch (Exception e) {
      IoFilterChain filterChain = session.getFilterChain();
      filterChain.fireExceptionCaught(e);
    }

    try {
      setInterestedInWrite(
          session, !session.getWriteRequestQueue().isEmpty(session) && !session.isWriteSuspended());
    } catch (Exception e) {
      IoFilterChain filterChain = session.getFilterChain();
      filterChain.fireExceptionCaught(e);
    }
  }
示例#14
0
 @Override
 public void onPreRemove(IoFilterChain parent, String name, NextFilter nextFilter)
     throws SSLException {
   IoSession session = parent.getSession();
   stopSsl(session);
   session.removeAttribute(NEXT_FILTER);
   session.removeAttribute(SSL_HANDLER);
 }
  private void clearWriteRequestQueue(S session) {
    WriteRequestQueue writeRequestQueue = session.getWriteRequestQueue();
    WriteRequest req;

    List<WriteRequest> failedRequests = new ArrayList<WriteRequest>();

    if ((req = writeRequestQueue.poll(session)) != null) {
      Object message = req.getMessage();

      if (message instanceof IoBuffer) {
        IoBuffer buf = (IoBuffer) message;

        // The first unwritten empty buffer must be
        // forwarded to the filter chain.
        if (buf.hasRemaining()) {
          buf.reset();
          failedRequests.add(req);
        } else {
          IoFilterChain filterChain = session.getFilterChain();
          filterChain.fireMessageSent(req);
        }
      } else {
        failedRequests.add(req);
      }

      // Discard others.
      while ((req = writeRequestQueue.poll(session)) != null) {
        failedRequests.add(req);
      }
    }

    // Create an exception and notify.
    if (!failedRequests.isEmpty()) {
      WriteToClosedSessionException cause = new WriteToClosedSessionException(failedRequests);

      for (WriteRequest r : failedRequests) {
        session.decreaseScheduledBytesAndMessages(r);
        r.getFuture().setException(cause);
      }

      IoFilterChain filterChain = session.getFilterChain();
      filterChain.fireExceptionCaught(cause);
    }
  }
示例#16
0
        @Override
        protected void doMessageReceived(HttpSession readSession, Object message) throws Exception {
          ResourceAddress readAddress = BridgeSession.REMOTE_ADDRESS.get(readSession);
          WsebSession wsebSession = sessionMap.get(readAddress);

          // handle parallel closure of WSE session during streaming read
          if (wsebSession == null) {
            if (logger.isDebugEnabled()) {
              logger.debug(
                  String.format("Could not find WsebSession for read address:\n" + readAddress));
            }
            return;
          }

          WsMessage wsebMessage = (WsMessage) message;
          IoBufferEx messageBytes = wsebMessage.getBytes();
          IoFilterChain filterChain = wsebSession.getTransportSession().getFilterChain();

          switch (wsebMessage.getKind()) {
            case COMMAND:
              for (Command command : ((WsCommandMessage) wsebMessage).getCommands()) {
                if (command == Command.reconnect()) {
                  // received a RECONNECT command
                  wsebSession.detachReader(readSession);
                  // re-attach downstream for read
                  final BridgeConnector bridgeConnector =
                      bridgeServiceFactory.newBridgeConnector(readAddress);
                  bridgeConnector.connect(readAddress, selectReadHandler(readAddress), null);
                  break;
                } else if (command == Command.close()) {
                  // Following should take care of sending CLOSE response and closing reader
                  // (downstream)
                  // Close case was not handled before 3.5.9
                  filterChain.fireMessageReceived(new WsCloseMessage());
                  break;
                }
                // no-op (0x00) - continue reading commands
              }
              break;
            default:
              filterChain.fireMessageReceived(wsebMessage);
              break;
          }
        }
 @Override
 public void onPostRemove(IoFilterChain parent, String name, NextFilter nextFilter)
     throws Exception {
   parent.getSession().removeAttribute(STATE);
 }
 private void fireMessageSent(S session, WriteRequest req) {
   session.setCurrentWriteRequest(null);
   IoFilterChain filterChain = session.getFilterChain();
   filterChain.fireMessageSent(req);
 }
  private boolean flushNow(S session, long currentTime) {
    if (!session.isConnected()) {
      scheduleRemove(session);
      return false;
    }

    final boolean hasFragmentation = session.getTransportMetadata().hasFragmentation();

    final WriteRequestQueue writeRequestQueue = session.getWriteRequestQueue();

    // Set limitation for the number of written bytes for read-write
    // fairness. I used maxReadBufferSize * 3 / 2, which yields best
    // performance in my experience while not breaking fairness much.
    final int maxWrittenBytes =
        session.getConfig().getMaxReadBufferSize()
            + (session.getConfig().getMaxReadBufferSize() >>> 1);
    int writtenBytes = 0;
    WriteRequest req = null;

    try {
      // Clear OP_WRITE
      setInterestedInWrite(session, false);

      do {
        // Check for pending writes.
        req = session.getCurrentWriteRequest();

        if (req == null) {
          req = writeRequestQueue.poll(session);

          if (req == null) {
            break;
          }

          session.setCurrentWriteRequest(req);
        }

        int localWrittenBytes = 0;
        Object message = req.getMessage();

        if (message instanceof IoBuffer) {
          localWrittenBytes =
              writeBuffer(
                  session, req, hasFragmentation, maxWrittenBytes - writtenBytes, currentTime);

          if ((localWrittenBytes > 0) && ((IoBuffer) message).hasRemaining()) {
            // the buffer isn't empty, we re-interest it in writing
            writtenBytes += localWrittenBytes;
            setInterestedInWrite(session, true);
            return false;
          }
        } else if (message instanceof FileRegion) {
          localWrittenBytes =
              writeFile(
                  session, req, hasFragmentation, maxWrittenBytes - writtenBytes, currentTime);

          // Fix for Java bug on Linux
          // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5103988
          // If there's still data to be written in the FileRegion,
          // return 0 indicating that we need
          // to pause until writing may resume.
          if ((localWrittenBytes > 0) && (((FileRegion) message).getRemainingBytes() > 0)) {
            writtenBytes += localWrittenBytes;
            setInterestedInWrite(session, true);
            return false;
          }
        } else {
          throw new IllegalStateException(
              "Don't know how to handle message of type '"
                  + message.getClass().getName()
                  + "'.  Are you missing a protocol encoder?");
        }

        if (localWrittenBytes == 0) {
          // Kernel buffer is full.
          setInterestedInWrite(session, true);
          return false;
        }

        writtenBytes += localWrittenBytes;

        if (writtenBytes >= maxWrittenBytes) {
          // Wrote too much
          scheduleFlush(session);
          return false;
        }
      } while (writtenBytes < maxWrittenBytes);
    } catch (Exception e) {
      if (req != null) {
        req.getFuture().setException(e);
      }

      IoFilterChain filterChain = session.getFilterChain();
      filterChain.fireExceptionCaught(e);
      return false;
    }

    return true;
  }
示例#20
0
 protected final void removeFilter(IoFilterChain filterChain, String name) {
   if (filterChain.contains(name)) {
     filterChain.remove(name);
   }
 }
  private void read(S session) {
    IoSessionConfig config = session.getConfig();
    int bufferSize = config.getReadBufferSize();
    IoBuffer buf = IoBuffer.allocate(bufferSize);

    final boolean hasFragmentation = session.getTransportMetadata().hasFragmentation();

    try {
      int readBytes = 0;
      int ret;

      try {
        if (hasFragmentation) {

          while ((ret = read(session, buf)) > 0) {
            readBytes += ret;

            if (!buf.hasRemaining()) {
              break;
            }
          }
        } else {
          ret = read(session, buf);

          if (ret > 0) {
            readBytes = ret;
          }
        }
      } finally {
        buf.flip();
      }

      if (readBytes > 0) {
        IoFilterChain filterChain = session.getFilterChain();
        filterChain.fireMessageReceived(buf);
        buf = null;

        if (hasFragmentation) {
          if (readBytes << 1 < config.getReadBufferSize()) {
            session.decreaseReadBufferSize();
          } else if (readBytes == config.getReadBufferSize()) {
            session.increaseReadBufferSize();
          }
        }
      }

      if (ret < 0) {
        scheduleRemove(session);
      }
    } catch (Throwable e) {
      if (e instanceof IOException) {
        if (!(e instanceof PortUnreachableException)
            || !AbstractDatagramSessionConfig.class.isAssignableFrom(config.getClass())
            || ((AbstractDatagramSessionConfig) config).isCloseOnPortUnreachable()) {
          scheduleRemove(session);
        }
      }

      IoFilterChain filterChain = session.getFilterChain();
      filterChain.fireExceptionCaught(e);
    }
  }
示例#22
0
 protected final void removeFilter(IoFilterChain filterChain, IoFilter filter) {
   if (filterChain.contains(filter)) {
     filterChain.remove(filter);
   }
 }
示例#23
0
 @Override
 public void onPostRemove(IoFilterChain parent, String name, NextFilter nextFilter)
     throws Exception {
   // Clean everything
   disposeCodec(parent.getSession());
 }
 @Override
 protected void fireSessionIdle(IoFilterChain filterChain) {
   filterChain.fireSessionIdle(IdleStatus.WRITER_IDLE);
 }