// Path: influent-transport/src/main/java/influent/exception/InfluentIOException.java
// public final class InfluentIOException extends RuntimeException {
//   /**
//    * Constructs a new {@code InfluentIOException}.
//    *
//    * @param message the error message
//    * @param cause the cause
//    */
//   public InfluentIOException(final String message, final Throwable cause) {
//     super(message, cause);
//   }
// 
//   /**
//    * Constructs a new {@code InfluentIOException}.
//    *
//    * @param message the error message
//    */
//   public InfluentIOException(final String message) {
//     super(message);
//   }
// 
//   /** Constructs a new {@code InfluentIOException}. */
//   public InfluentIOException() {
//     super();
//   }
// }
// 
// Path: influent-transport/src/main/java/influent/internal/util/ThreadSafeQueue.java
// public final class ThreadSafeQueue<E> {
//   private final BlockingQueue<E> queue = new LinkedBlockingQueue<>();
// 
//   /**
//    * Adds an element to this {@code ThreadSafeQueue}.
//    *
//    * @param element the element to add
//    * @return {@code true} if the element was added to this queue, else {@code false}
//    * @throws ClassCastException if the class of the specified element prevents it from being added
//    *     to this queue
//    * @throws NullPointerException if the specified element is null
//    * @throws IllegalArgumentException if some property of the specified element prevents it from
//    *     being added to this queue
//    */
//   public boolean enqueue(final E element) {
//     return queue.offer(element);
//   }
// 
//   /**
//    * Removes the head element from this {@code ThreadSafeQueue}.
//    *
//    * @return the head element if this queue is non-empty, otherwise {@code null}
//    */
//   public E dequeue() {
//     return queue.poll();
//   }
// 
//   /**
//    * Peeks the head element.
//    *
//    * @return the head element if this queue is non-empty, otherwise {@code null}
//    */
//   public E peek() {
//     return queue.peek();
//   }
// 
//   /**
//    * Tests that this {@code ThreadSafeQueue} is empty.
//    *
//    * @return true if this {@code ThreadSafeQueue} is empty
//    */
//   public boolean isEmpty() {
//     return queue.isEmpty();
//   }
// 
//   /**
//    * Tests that this {@code ThreadSafeQueue} is non-empty.
//    *
//    * @return true if this {@code ThreadSafeQueue} is non-empty
//    */
//   public boolean nonEmpty() {
//     return !queue.isEmpty();
//   }
// }


import influent.exception.InfluentIOException;
import influent.internal.util.ThreadSafeQueue;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.EnumSet;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.net.ssl.SSLEngineResult;
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
import javax.net.ssl.SSLEngineResult.Status;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/*
 * Copyright 2016 okumin
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package influent.internal.nio;


/**
 * A non-blocking secure {@code SocketChannel}.
 *
 * <p>This implementation is naive and its performance is poor yet.
 */
public final class NioTcpTlsChannel implements NioTcpChannel {
  private static final Logger logger = LoggerFactory.getLogger(NioTcpTlsChannel.class);

  private final NioTcpPlaintextChannel channel;
  private final NioTlsEngine engine;

  private ByteBuffer inboundNetworkBuffer = newInboundNetworkBuffer();
// Path: influent-transport/src/main/java/influent/exception/InfluentIOException.java
// public final class InfluentIOException extends RuntimeException {
//   /**
//    * Constructs a new {@code InfluentIOException}.
//    *
//    * @param message the error message
//    * @param cause the cause
//    */
//   public InfluentIOException(final String message, final Throwable cause) {
//     super(message, cause);
//   }
// 
//   /**
//    * Constructs a new {@code InfluentIOException}.
//    *
//    * @param message the error message
//    */
//   public InfluentIOException(final String message) {
//     super(message);
//   }
// 
//   /** Constructs a new {@code InfluentIOException}. */
//   public InfluentIOException() {
//     super();
//   }
// }
// 
// Path: influent-transport/src/main/java/influent/internal/util/ThreadSafeQueue.java
// public final class ThreadSafeQueue<E> {
//   private final BlockingQueue<E> queue = new LinkedBlockingQueue<>();
// 
//   /**
//    * Adds an element to this {@code ThreadSafeQueue}.
//    *
//    * @param element the element to add
//    * @return {@code true} if the element was added to this queue, else {@code false}
//    * @throws ClassCastException if the class of the specified element prevents it from being added
//    *     to this queue
//    * @throws NullPointerException if the specified element is null
//    * @throws IllegalArgumentException if some property of the specified element prevents it from
//    *     being added to this queue
//    */
//   public boolean enqueue(final E element) {
//     return queue.offer(element);
//   }
// 
//   /**
//    * Removes the head element from this {@code ThreadSafeQueue}.
//    *
//    * @return the head element if this queue is non-empty, otherwise {@code null}
//    */
//   public E dequeue() {
//     return queue.poll();
//   }
// 
//   /**
//    * Peeks the head element.
//    *
//    * @return the head element if this queue is non-empty, otherwise {@code null}
//    */
//   public E peek() {
//     return queue.peek();
//   }
// 
//   /**
//    * Tests that this {@code ThreadSafeQueue} is empty.
//    *
//    * @return true if this {@code ThreadSafeQueue} is empty
//    */
//   public boolean isEmpty() {
//     return queue.isEmpty();
//   }
// 
//   /**
//    * Tests that this {@code ThreadSafeQueue} is non-empty.
//    *
//    * @return true if this {@code ThreadSafeQueue} is non-empty
//    */
//   public boolean nonEmpty() {
//     return !queue.isEmpty();
//   }
// }


// Path: influent-transport/src/main/java/influent/internal/nio/NioTcpTlsChannel.java
import influent.exception.InfluentIOException;
import influent.internal.util.ThreadSafeQueue;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.EnumSet;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.net.ssl.SSLEngineResult;
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
import javax.net.ssl.SSLEngineResult.Status;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/*
 * Copyright 2016 okumin
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package influent.internal.nio;


/**
 * A non-blocking secure {@code SocketChannel}.
 *
 * <p>This implementation is naive and its performance is poor yet.
 */
public final class NioTcpTlsChannel implements NioTcpChannel {
  private static final Logger logger = LoggerFactory.getLogger(NioTcpTlsChannel.class);

  private final NioTcpPlaintextChannel channel;
  private final NioTlsEngine engine;

  private ByteBuffer inboundNetworkBuffer = newInboundNetworkBuffer();
  private final ThreadSafeQueue<ByteBuffer> outboundNetworkBuffers = new ThreadSafeQueue<>();