# Class UnifiedServerSocket.UnifiedSocket

java.lang.Object
java.net.Socket
org.apache.zookeeper.server.quorum.UnifiedServerSocket.UnifiedSocket

All Implemented Interfaces:
  `Closeable, AutoCloseable`

Enclosing class:
  `UnifiedServerSocket`

public static class UnifiedServerSocket.UnifiedSocket extends Socket
The result of calling accept() on a UnifiedServerSocket. This is a Socket that doesn't know if it's using plaintext or SSL/TLS at the time when it is created. Calling a method that indicates a desire to read or write from the socket will cause the socket to detect if the connected client is attempting to establish a TLS or plaintext connection. This is done by doing a blocking read of 5 bytes off the socket and checking if the bytes look like the start of a TLS ClientHello message. If it looks like the client is attempting to connect with TLS, the internal socket is upgraded to a SSLSocket. If not, any bytes read from the socket are pushed back to the input stream, and the socket continues to be treated as a plaintext socket. The methods that trigger this behavior are:

- `getInputStream()`
- `getOutputStream()`
- `sendUrgentData(int)`

Calling other socket methods (i.e option setters such as `Socket.setTcpNoDelay(boolean)`) does not trigger mode detection. Because detecting the mode is a potentially blocking operation, it should not be done in the accepting thread. Attempting to read from or write to the socket in the accepting thread opens the caller up to a denial-of-service attack, in which a client connects and then does nothing. This would prevent any other clients from connecting. Passing the socket returned by accept() to a separate thread which handles all read and write operations protects against this DoS attack. Callers can check if the socket has been upgraded to TLS by calling `isSecureSocket()`, and can get the underlying SSLSocket by calling `getSslSocket()`.

## Method Summary

Modifier and Type
Method
Description
`void`
`bind(SocketAddress bindpoint)`
See `Socket.bind(SocketAddress)`.
`void`
`close()`
See `Socket.close()`.
`void`
`connect(SocketAddress endpoint)`
See `Socket.connect(SocketAddress)`.
`void`
`connect(SocketAddress endpoint, int timeout)`
See `Socket.connect(SocketAddress, int)`.
`SocketChannel`
`getChannel()`
See `Socket.getChannel()`.
`InetAddress`
`getInetAddress()`
See `Socket.getInetAddress()`.
`InputStream`
`getInputStream()`
See `Socket.getInputStream()`.
`boolean`
`getKeepAlive()`
See `Socket.getKeepAlive()`.
`InetAddress`
`getLocalAddress()`
See `Socket.getLocalAddress()`.
`int`
`getLocalPort()`
See `Socket.getLocalPort()`.
`SocketAddress`
`getLocalSocketAddress()`
See `Socket.getLocalSocketAddress()`.
`boolean`
`getOOBInline()`
See `Socket.getOOBInline()`.
`OutputStream`
`getOutputStream()`
See `Socket.getOutputStream()`.
`int`
`getPort()`
See `Socket.getPort()`.
`int`
`getReceiveBufferSize()`
See `Socket.getReceiveBufferSize()`.
`SocketAddress`
`getRemoteSocketAddress()`
See `Socket.getRemoteSocketAddress()`.
`boolean`
`getReuseAddress()`
See `Socket.getReuseAddress()`.
`int`
`getSendBufferSize()`
See `Socket.getSendBufferSize()`.
`int`
`getSoLinger()`
See `Socket.getSoLinger()`.
`int`
`getSoTimeout()`
See `Socket.getSoTimeout()`.
`SSLSocket`
`getSslSocket()`
Returns the underlying SSLSocket if the mode is TLS.
`boolean`
`getTcpNoDelay()`
See `Socket.getTcpNoDelay()`.
`int`
`getTrafficClass()`
See `Socket.getTrafficClass()`.
`boolean`
`isBound()`
See `Socket.isBound()`.
`boolean`
`isClosed()`
See `Socket.isClosed()`.
`boolean`
`isConnected()`
See `Socket.isConnected()`.
`boolean`
`isInputShutdown()`
See `Socket.isInputShutdown()`.
`boolean`
`isModeKnown()`
Returns true if the socket mode is not yet known.
`boolean`
`isOutputShutdown()`
See `Socket.isOutputShutdown()`.
`boolean`
`isPlaintextSocket()`
Returns true if the socket mode has been determined to be PLAINTEXT.
`boolean`
`isSecureSocket()`
Returns true if the socket mode has been determined to be TLS.
`void`
`sendUrgentData(int data)`
See `Socket.sendUrgentData(int)`.
`void`
`setKeepAlive(boolean on)`
See `Socket.setKeepAlive(boolean)`.
`void`
`setOOBInline(boolean on)`
See `Socket.setOOBInline(boolean)`.
`void`
`setPerformancePreferences(int connectionTime, int latency, int bandwidth)`
See `Socket.setPerformancePreferences(int, int, int)`.
`void`
`setReceiveBufferSize(int size)`
See `Socket.setReceiveBufferSize(int)`.
`void`
`setReuseAddress(boolean on)`
See `Socket.setReuseAddress(boolean)`.
`void`
`setSendBufferSize(int size)`
See `Socket.setSendBufferSize(int)`.
`void`
`setSoLinger(boolean on, int linger)`
See `Socket.setSoLinger(boolean, int)`.
`void`
`setSoTimeout(int timeout)`
See `Socket.setSoTimeout(int)`.
`void`
`setTcpNoDelay(boolean on)`
See `Socket.setTcpNoDelay(boolean)`.
`void`
`setTrafficClass(int tc)`
See `Socket.setTrafficClass(int)`.
`void`
`shutdownInput()`
See `Socket.shutdownInput()`.
`void`
`shutdownOutput()`
See `Socket.shutdownOutput()`.
`String`
`toString()`
See `Socket.toString()`.

### Methods inherited from class Socket

`setSocketImplFactory`

### Methods inherited from class Object

`clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait`

## Method Details

### isSecureSocket

public boolean isSecureSocket()
Returns true if the socket mode has been determined to be TLS.

Returns:
  true if the mode is TLS, false if it is UNKNOWN or PLAINTEXT.

### isPlaintextSocket

public boolean isPlaintextSocket()
Returns true if the socket mode has been determined to be PLAINTEXT.

Returns:
  true if the mode is PLAINTEXT, false if it is UNKNOWN or TLS.

### isModeKnown

public boolean isModeKnown()
Returns true if the socket mode is not yet known.

Returns:
  true if the mode is UNKNOWN, false if it is PLAINTEXT or TLS.

### getSslSocket

public SSLSocket getSslSocket() throws IOException
Returns the underlying SSLSocket if the mode is TLS. If the mode is UNKNOWN, causes mode detection which is a potentially blocking operation. If the mode ends up being PLAINTEXT, this will throw a SocketException, so callers are advised to only call this method after checking that `isSecureSocket()` returned true.

Returns:
  the underlying SSLSocket if the mode is known to be TLS.
Throws:
  `IOException` - if detecting the socket mode fails
  `SocketException` - if the mode is PLAINTEXT.

### connect

public void connect(SocketAddress endpoint) throws IOException
See `Socket.connect(SocketAddress)`. Calling this method does not trigger mode detection.

Overrides:
  `connect` in class `Socket`
Throws:
  `IOException`

### connect

public void connect(SocketAddress endpoint, int timeout) throws IOException
See `Socket.connect(SocketAddress, int)`. Calling this method does not trigger mode detection.

Overrides:
  `connect` in class `Socket`
Throws:
  `IOException`

### bind

public void bind(SocketAddress bindpoint) throws IOException
See `Socket.bind(SocketAddress)`. Calling this method does not trigger mode detection.

Overrides:
  `bind` in class `Socket`
Throws:
  `IOException`

### getInetAddress

public InetAddress getInetAddress()
See `Socket.getInetAddress()`. Calling this method does not trigger mode detection.

Overrides:
  `getInetAddress` in class `Socket`

### getLocalAddress

public InetAddress getLocalAddress()
See `Socket.getLocalAddress()`. Calling this method does not trigger mode detection.

Overrides:
  `getLocalAddress` in class `Socket`

### getPort

public int getPort()
See `Socket.getPort()`. Calling this method does not trigger mode detection.

Overrides:
  `getPort` in class `Socket`

### getLocalPort

public int getLocalPort()
See `Socket.getLocalPort()`. Calling this method does not trigger mode detection.

Overrides:
  `getLocalPort` in class `Socket`

### getRemoteSocketAddress

public SocketAddress getRemoteSocketAddress()
See `Socket.getRemoteSocketAddress()`. Calling this method does not trigger mode detection.

Overrides:
  `getRemoteSocketAddress` in class `Socket`

### getLocalSocketAddress

public SocketAddress getLocalSocketAddress()
See `Socket.getLocalSocketAddress()`. Calling this method does not trigger mode detection.

Overrides:
  `getLocalSocketAddress` in class `Socket`

### getChannel

public SocketChannel getChannel()
See `Socket.getChannel()`. Calling this method does not trigger mode detection.

Overrides:
  `getChannel` in class `Socket`

### getInputStream

public InputStream getInputStream() throws IOException
See `Socket.getInputStream()`. If the socket mode has not yet been detected, the first read from the returned input stream will trigger mode detection, which is a potentially blocking operation. This means the accept() thread should avoid reading from this input stream if possible.

Overrides:
  `getInputStream` in class `Socket`
Throws:
  `IOException`

### getOutputStream

public OutputStream getOutputStream() throws IOException
See `Socket.getOutputStream()`. If the socket mode has not yet been detected, the first read from the returned input stream will trigger mode detection, which is a potentially blocking operation. This means the accept() thread should avoid reading from this input stream if possible.

Overrides:
  `getOutputStream` in class `Socket`
Throws:
  `IOException`

### setTcpNoDelay

public void setTcpNoDelay(boolean on) throws SocketException
See `Socket.setTcpNoDelay(boolean)`. Calling this method does not trigger mode detection.

Overrides:
  `setTcpNoDelay` in class `Socket`
Throws:
  `SocketException`

### getTcpNoDelay

public boolean getTcpNoDelay() throws SocketException
See `Socket.getTcpNoDelay()`. Calling this method does not trigger mode detection.

Overrides:
  `getTcpNoDelay` in class `Socket`
Throws:
  `SocketException`

### setSoLinger

public void setSoLinger(boolean on, int linger) throws SocketException
See `Socket.setSoLinger(boolean, int)`. Calling this method does not trigger mode detection.

Overrides:
  `setSoLinger` in class `Socket`
Throws:
  `SocketException`

### getSoLinger

public int getSoLinger() throws SocketException
See `Socket.getSoLinger()`. Calling this method does not trigger mode detection.

Overrides:
  `getSoLinger` in class `Socket`
Throws:
  `SocketException`

### sendUrgentData

public void sendUrgentData(int data) throws IOException
See `Socket.sendUrgentData(int)`. Calling this method triggers mode detection, which is a potentially blocking operation, so it should not be done in the accept() thread.

Overrides:
  `sendUrgentData` in class `Socket`
Throws:
  `IOException`

### setOOBInline

public void setOOBInline(boolean on) throws SocketException
See `Socket.setOOBInline(boolean)`. Calling this method does not trigger mode detection.

Overrides:
  `setOOBInline` in class `Socket`
Throws:
  `SocketException`

### getOOBInline

public boolean getOOBInline() throws SocketException
See `Socket.getOOBInline()`. Calling this method does not trigger mode detection.

Overrides:
  `getOOBInline` in class `Socket`
Throws:
  `SocketException`

### setSoTimeout

public void setSoTimeout(int timeout) throws SocketException
See `Socket.setSoTimeout(int)`. Calling this method does not trigger mode detection.

Overrides:
  `setSoTimeout` in class `Socket`
Throws:
  `SocketException`

### getSoTimeout

public int getSoTimeout() throws SocketException
See `Socket.getSoTimeout()`. Calling this method does not trigger mode detection.

Overrides:
  `getSoTimeout` in class `Socket`
Throws:
  `SocketException`

### setSendBufferSize

public void setSendBufferSize(int size) throws SocketException
See `Socket.setSendBufferSize(int)`. Calling this method does not trigger mode detection.

Overrides:
  `setSendBufferSize` in class `Socket`
Throws:
  `SocketException`

### getSendBufferSize

public int getSendBufferSize() throws SocketException
See `Socket.getSendBufferSize()`. Calling this method does not trigger mode detection.

Overrides:
  `getSendBufferSize` in class `Socket`
Throws:
  `SocketException`

### setReceiveBufferSize

public void setReceiveBufferSize(int size) throws SocketException
See `Socket.setReceiveBufferSize(int)`. Calling this method does not trigger mode detection.

Overrides:
  `setReceiveBufferSize` in class `Socket`
Throws:
  `SocketException`

### getReceiveBufferSize

public int getReceiveBufferSize() throws SocketException
See `Socket.getReceiveBufferSize()`. Calling this method does not trigger mode detection.

Overrides:
  `getReceiveBufferSize` in class `Socket`
Throws:
  `SocketException`

### setKeepAlive

public void setKeepAlive(boolean on) throws SocketException
See `Socket.setKeepAlive(boolean)`. Calling this method does not trigger mode detection.

Overrides:
  `setKeepAlive` in class `Socket`
Throws:
  `SocketException`

### getKeepAlive

public boolean getKeepAlive() throws SocketException
See `Socket.getKeepAlive()`. Calling this method does not trigger mode detection.

Overrides:
  `getKeepAlive` in class `Socket`
Throws:
  `SocketException`

### setTrafficClass

public void setTrafficClass(int tc) throws SocketException
See `Socket.setTrafficClass(int)`. Calling this method does not trigger mode detection.

Overrides:
  `setTrafficClass` in class `Socket`
Throws:
  `SocketException`

### getTrafficClass

public int getTrafficClass() throws SocketException
See `Socket.getTrafficClass()`. Calling this method does not trigger mode detection.

Overrides:
  `getTrafficClass` in class `Socket`
Throws:
  `SocketException`

### setReuseAddress

public void setReuseAddress(boolean on) throws SocketException
See `Socket.setReuseAddress(boolean)`. Calling this method does not trigger mode detection.

Overrides:
  `setReuseAddress` in class `Socket`
Throws:
  `SocketException`

### getReuseAddress

public boolean getReuseAddress() throws SocketException
See `Socket.getReuseAddress()`. Calling this method does not trigger mode detection.

Overrides:
  `getReuseAddress` in class `Socket`
Throws:
  `SocketException`

### close

public void close() throws IOException
See `Socket.close()`. Calling this method does not trigger mode detection.

Specified by:
  `close` in interface `AutoCloseable`
Specified by:
  `close` in interface `Closeable`
Overrides:
  `close` in class `Socket`
Throws:
  `IOException`

### shutdownInput

public void shutdownInput() throws IOException
See `Socket.shutdownInput()`. Calling this method does not trigger mode detection.

Overrides:
  `shutdownInput` in class `Socket`
Throws:
  `IOException`

### shutdownOutput

public void shutdownOutput() throws IOException
See `Socket.shutdownOutput()`. Calling this method does not trigger mode detection.

Overrides:
  `shutdownOutput` in class `Socket`
Throws:
  `IOException`

### toString

public String toString()
See `Socket.toString()`. Calling this method does not trigger mode detection.

Overrides:
  `toString` in class `Socket`

### isConnected

public boolean isConnected()
See `Socket.isConnected()`. Calling this method does not trigger mode detection.

Overrides:
  `isConnected` in class `Socket`

### isBound

public boolean isBound()
See `Socket.isBound()`. Calling this method does not trigger mode detection.

Overrides:
  `isBound` in class `Socket`

### isClosed

public boolean isClosed()
See `Socket.isClosed()`. Calling this method does not trigger mode detection.

Overrides:
  `isClosed` in class `Socket`

### isInputShutdown

public boolean isInputShutdown()
See `Socket.isInputShutdown()`. Calling this method does not trigger mode detection.

Overrides:
  `isInputShutdown` in class `Socket`

### isOutputShutdown

public boolean isOutputShutdown()
See `Socket.isOutputShutdown()`. Calling this method does not trigger mode detection.

Overrides:
  `isOutputShutdown` in class `Socket`

### setPerformancePreferences

public void setPerformancePreferences(int connectionTime, int latency, int bandwidth)
See `Socket.setPerformancePreferences(int, int, int)`. Calling this method does not trigger mode detection.

Overrides:
  `setPerformancePreferences` in class `Socket`