void closeBlocking() throws IOException {
   state |= FLAG_CLOSED;
   try {
     if (buffer != null) {
       Channels.writeBlocking(channel, buffer);
     }
     channel.shutdownWrites();
     Channels.flushBlocking(channel);
   } finally {
     channel.close();
   }
 }
 @Override
 public int read(final byte[] b, final int off, final int len) throws IOException {
   if (anyAreSet(state, FLAG_CLOSED)) {
     throw UndertowServletMessages.MESSAGES.streamIsClosed();
   }
   if (anyAreSet(state, FLAG_FINISHED)) {
     return -1;
   }
   ByteBuffer buffer = ByteBuffer.wrap(b, off, len);
   if (listener == null) {
     int res = Channels.readBlocking(channel, buffer);
     if (res == -1) {
       state |= FLAG_FINISHED;
     }
     return res;
   } else {
     if (anyAreClear(state, FLAG_READY)) {
       throw UndertowServletMessages.MESSAGES.streamNotReady();
     }
     int res = channel.read(buffer);
     if (res == -1) {
       state |= FLAG_FINISHED;
     } else if (res == 0) {
       state &= ~FLAG_READY;
       channel.resumeReads();
     }
     return res;
   }
 }
  @Override
  public void write(final byte[] b, final int off, final int len) throws IOException {
    if (anyAreSet(state, FLAG_CLOSED)) {
      throw UndertowServletMessages.MESSAGES.streamIsClosed();
    }
    if (listener == null) {
      Channels.writeBlocking(channel, ByteBuffer.wrap(b, off, len));
    } else {
      if (anyAreClear(state, FLAG_READY)) {
        throw UndertowServletMessages.MESSAGES.streamNotReady();
      }
      int res;
      ByteBuffer buffer = ByteBuffer.wrap(b);
      do {
        res = channel.write(buffer);
        if (res == 0) {

          ByteBuffer copy = ByteBuffer.allocate(buffer.remaining());
          copy.put(buffer);
          copy.flip();
          this.buffer = copy;
          state = state & ~FLAG_READY;
          channel.resumeWrites();
          return;
        }
      } while (buffer.hasRemaining());
    }
  }
  public void renegotiateBufferRequest(HttpServerExchange exchange, SslClientAuthMode newAuthMode)
      throws IOException {
    int maxSize =
        exchange
            .getConnection()
            .getUndertowOptions()
            .get(UndertowOptions.MAX_BUFFERED_REQUEST_SIZE, 16384);
    if (maxSize <= 0) {
      throw new SSLPeerUnverifiedException("");
    }

    // first we need to read the request
    boolean requestResetRequired = false;
    StreamSourceChannel requestChannel = Connectors.getExistingRequestChannel(exchange);
    if (requestChannel == null) {
      requestChannel = exchange.getRequestChannel();
      requestResetRequired = true;
    }

    Pooled<ByteBuffer> pooled = exchange.getConnection().getBufferPool().allocate();
    boolean free = true; // if the pooled buffer should be freed
    int usedBuffers = 0;
    Pooled<ByteBuffer>[] poolArray = null;
    final int bufferSize = pooled.getResource().remaining();
    int allowedBuffers = ((maxSize + bufferSize - 1) / bufferSize);
    poolArray = new Pooled[allowedBuffers];
    poolArray[usedBuffers++] = pooled;
    try {
      int res;
      do {
        final ByteBuffer buf = pooled.getResource();
        res = Channels.readBlocking(requestChannel, buf);
        if (!buf.hasRemaining()) {
          if (usedBuffers == allowedBuffers) {
            throw new SSLPeerUnverifiedException("");
          } else {
            buf.flip();
            pooled = exchange.getConnection().getBufferPool().allocate();
            poolArray[usedBuffers++] = pooled;
          }
        }
      } while (res != -1);
      free = false;
      pooled.getResource().flip();
      Connectors.ungetRequestBytes(exchange, poolArray);
      renegotiateNoRequest(exchange, newAuthMode);
    } finally {
      if (free) {
        for (Pooled<ByteBuffer> buf : poolArray) {
          if (buf != null) {
            buf.free();
          }
        }
      }
      if (requestResetRequired) {
        exchange.requestChannel = null;
      }
    }
  }
 @Override
 public void flush() throws IOException {
   if (anyAreSet(state, FLAG_CLOSED)) {
     throw UndertowServletMessages.MESSAGES.streamIsClosed();
   }
   if (listener == null) {
     Channels.flushBlocking(channel);
   }
 }
Example #6
0
  private static <I extends StreamSourceChannel, O extends StreamSinkChannel> void done(
      I source,
      O sink,
      ChannelListener<? super I> sourceListener,
      ChannelListener<? super O> sinkListener) {
    Channels.setReadListener(source, sourceListener);
    if (sourceListener == null) {
      source.suspendReads();
    } else {
      source.wakeupReads();
    }

    Channels.setWriteListener(sink, sinkListener);
    if (sinkListener == null) {
      sink.suspendWrites();
    } else {
      sink.wakeupWrites();
    }
  }
 @Override
 public void sendBinary(final ByteBuffer partialByte, final boolean isLast) throws IOException {
   if (textFrameSender != null) {
     throw JsrWebSocketMessages.MESSAGES.cannotSendInMiddleOfFragmentedMessage();
   }
   if (binaryFrameSender == null) {
     binaryFrameSender = webSocketChannel.send(WebSocketFrameType.BINARY);
   }
   try {
     Channels.writeBlocking(binaryFrameSender, partialByte);
     if (isLast) {
       binaryFrameSender.shutdownWrites();
       Channels.flushBlocking(binaryFrameSender);
     }
   } finally {
     if (isLast) {
       binaryFrameSender = null;
     }
   }
 }
 @Override
 public void sendText(final String partialMessage, final boolean isLast) throws IOException {
   if (binaryFrameSender != null) {
     throw JsrWebSocketMessages.MESSAGES.cannotSendInMiddleOfFragmentedMessage();
   }
   if (textFrameSender == null) {
     textFrameSender = webSocketChannel.send(WebSocketFrameType.TEXT);
   }
   try {
     Channels.writeBlocking(textFrameSender, WebSocketUtils.fromUtf8String(partialMessage));
     if (isLast) {
       textFrameSender.shutdownWrites();
       Channels.flushBlocking(textFrameSender);
     }
   } finally {
     if (isLast) {
       textFrameSender = null;
     }
   }
 }
 @Override
 public void close() throws IOException {
   state |= FLAG_CLOSED;
   state &= ~FLAG_READY;
   if (listener == null) {
     channel.shutdownWrites();
     state |= FLAG_DELEGATE_SHUTDOWN;
     Channels.flushBlocking(channel);
   } else {
     if (buffer == null) {
       channel.shutdownWrites();
       state |= FLAG_DELEGATE_SHUTDOWN;
       if (!channel.flush()) {
         channel.resumeWrites();
       }
     }
   }
 }
Example #10
0
 public void accept(final Pooled<ByteBuffer> pooledBuffer, final boolean eof)
     throws IOException {
   try {
     final ByteBuffer buffer = pooledBuffer.getResource();
     final ConnectedMessageChannel messageChannel =
         channel.getRemoteConnection().getChannel();
     if (eof) {
       // EOF flag (sync close)
       buffer.put(7, (byte) (buffer.get(7) | Protocol.MSG_FLAG_EOF));
       log.tracef("Sending message (with EOF) (%s) to %s", buffer, messageChannel);
     }
     if (cancelled) {
       buffer.put(7, (byte) (buffer.get(7) | Protocol.MSG_FLAG_CANCELLED));
       buffer.limit(8); // discard everything in the buffer
       log.trace("Message includes cancel flag");
     }
     synchronized (OutboundMessage.this) {
       int msgSize = buffer.remaining();
       window -= msgSize;
       while (window < msgSize) {
         try {
           log.trace("Message window is closed, waiting");
           OutboundMessage.this.wait();
         } catch (InterruptedException e) {
           Thread.currentThread().interrupt();
           throw new InterruptedIOException("Interrupted on write");
         }
       }
       log.trace("Message window is open, proceeding with send");
     }
     Channels.sendBlocking(messageChannel, buffer);
   } finally {
     pooledBuffer.free();
     if (eof) {
       channel.free(OutboundMessage.this);
     }
   }
 }
    public void handleEvent(final ConnectedMessageChannel channel) {
      final Pooled<ByteBuffer> pooledReceiveBuffer = connection.allocate();
      try {
        final ByteBuffer receiveBuffer = pooledReceiveBuffer.getResource();
        int res = 0;
        try {
          res = channel.receive(receiveBuffer);
        } catch (IOException e) {
          connection.handleException(e);
          return;
        }
        if (res == -1) {
          connection.handleException(client.abruptClose(connection));
          return;
        }
        if (res == 0) {
          return;
        }
        receiveBuffer.flip();
        boolean starttls = false;
        final Set<String> saslMechs = new LinkedHashSet<String>();
        final byte msgType = receiveBuffer.get();
        switch (msgType) {
          case Protocol.CONNECTION_ALIVE:
            {
              client.trace("Client received connection alive");
              return;
            }
          case Protocol.CONNECTION_CLOSE:
            {
              client.trace("Client received connection close request");
              connection.handleIncomingCloseRequest();
              return;
            }
          case Protocol.CAPABILITIES:
            {
              client.trace("Client received capabilities response");
              while (receiveBuffer.hasRemaining()) {
                final byte type = receiveBuffer.get();
                final int len = receiveBuffer.get() & 0xff;
                final ByteBuffer data = Buffers.slice(receiveBuffer, len);
                switch (type) {
                  case Protocol.CAP_VERSION:
                    {
                      final byte version = data.get();
                      client.tracef(
                          "Client received capability: version %d",
                          Integer.valueOf(version & 0xff));
                      // We only support version zero, so knowing the other side's version is not
                      // useful presently
                      break;
                    }
                  case Protocol.CAP_SASL_MECH:
                    {
                      final String mechName = Buffers.getModifiedUtf8(data);
                      client.tracef("Client received capability: SASL mechanism %s", mechName);
                      if (!failedMechs.contains(mechName)
                          && !disallowedMechs.contains(mechName)
                          && (allowedMechs == null || allowedMechs.contains(mechName))) {
                        client.tracef("SASL mechanism %s added to allowed set", mechName);
                        saslMechs.add(mechName);
                      }
                      break;
                    }
                  case Protocol.CAP_STARTTLS:
                    {
                      client.trace("Client received capability: STARTTLS");
                      starttls = true;
                      break;
                    }
                  default:
                    {
                      client.tracef(
                          "Client received unknown capability %02x", Integer.valueOf(type & 0xff));
                      // unknown, skip it for forward compatibility.
                      break;
                    }
                }
              }
              if (starttls) {
                // only initiate starttls if not forbidden by config
                if (optionMap.get(Options.SSL_STARTTLS, true)) {
                  // Prepare the request message body
                  final Pooled<ByteBuffer> pooledSendBuffer = connection.allocate();
                  final ByteBuffer sendBuffer = pooledSendBuffer.getResource();
                  sendBuffer.put(Protocol.STARTTLS);
                  sendBuffer.flip();
                  connection.setReadListener(new StartTls(serverName));
                  connection.send(pooledSendBuffer);
                  // all set
                  return;
                }
              }

              if (saslMechs.isEmpty()) {
                connection.handleException(
                    new SaslException("No more authentication mechanisms to try"));
                return;
              }
              // OK now send our authentication request
              final OptionMap optionMap = connection.getOptionMap();
              final String userName = optionMap.get(RemotingOptions.AUTHORIZE_ID);
              final Map<String, ?> propertyMap =
                  SaslUtils.createPropertyMap(
                      optionMap, Channels.getOption(channel, Options.SECURE, false));
              final SaslClient saslClient;
              try {
                saslClient =
                    AccessController.doPrivileged(
                        new PrivilegedExceptionAction<SaslClient>() {
                          public SaslClient run() throws SaslException {
                            return Sasl.createSaslClient(
                                saslMechs.toArray(new String[saslMechs.size()]),
                                userName,
                                "remote",
                                serverName,
                                propertyMap,
                                callbackHandler);
                          }
                        },
                        accessControlContext);
              } catch (PrivilegedActionException e) {
                final SaslException se = (SaslException) e.getCause();
                connection.handleException(se);
                return;
              }
              final String mechanismName = saslClient.getMechanismName();
              client.tracef("Client initiating authentication using mechanism %s", mechanismName);
              // Prepare the request message body
              final Pooled<ByteBuffer> pooledSendBuffer = connection.allocate();
              final ByteBuffer sendBuffer = pooledSendBuffer.getResource();
              sendBuffer.put(Protocol.AUTH_REQUEST);
              Buffers.putModifiedUtf8(sendBuffer, mechanismName);
              sendBuffer.flip();
              connection.send(pooledSendBuffer);
              connection.setReadListener(new Authentication(saslClient, serverName));
              return;
            }
          default:
            {
              client.unknownProtocolId(msgType);
              connection.handleException(client.invalidMessage(connection));
              return;
            }
        }
      } catch (BufferUnderflowException e) {
        connection.handleException(client.invalidMessage(connection));
        return;
      } catch (BufferOverflowException e) {
        connection.handleException(client.invalidMessage(connection));
        return;
      } finally {
        pooledReceiveBuffer.free();
      }
    }
Example #12
0
 public void flush() throws IOException {
   log.trace("Flushing message channel");
   Channels.flushBlocking(channel.getRemoteConnection().getChannel());
 }