public class NetworkConfigurationDiscoveryProcess extends Object
This class implements the STUN Discovery Process as described by section 10.1 of rfc 3489.
The flow makes use of three tests. In test I, the client sends a STUN Binding Request to a server, without any flags set in the CHANGE-REQUEST attribute, and without the RESPONSE-ADDRESS attribute. This causes the server to send the response back to the address and port that the request came from. In test II, the client sends a Binding Request with both the "change IP" and "change port" flags from the CHANGE-REQUEST attribute set. In test III, the client sends a Binding Request with only the "change port" flag set.
The client begins by initiating test I. If this test yields no response, the client knows right away that it is not capable of UDP connectivity. If the test produces a response, the client examines the MAPPED-ADDRESS attribute. If this address and port are the same as the local IP address and port of the socket used to send the request, the client knows that it is not natted. It executes test II.
If a response is received, the client knows that it has open access to the Internet (or, at least, its behind a firewall that behaves like a full-cone NAT, but without the translation). If no response is received, the client knows its behind a symmetric UDP firewall.
In the event that the IP address and port of the socket did not match the MAPPED-ADDRESS attribute in the response to test I, the client knows that it is behind a NAT. It performs test II. If a response is received, the client knows that it is behind a full-cone NAT. If no response is received, it performs test I again, but this time, does so to the address and port from the CHANGED-ADDRESS attribute from the response to test I. If the IP address and port returned in the MAPPED-ADDRESS attribute are not the same as the ones from the first test I, the client knows its behind a symmetric NAT. If the address and port are the same, the client is either behind a restricted or port restricted NAT. To make a determination about which one it is behind, the client initiates test III. If a response is received, its behind a restricted NAT, and if no response is received, its behind a port restricted NAT.
This procedure yields substantial information about the operating condition of the client application. In the event of multiple NATs between the client and the Internet, the type that is discovered will be the type of the most restrictive NAT between the client and the Internet. The types of NAT, in order of restrictiveness, from most to least, are symmetric, port restricted cone, restricted cone, and full cone.
Typically, a client will re-do this discovery process periodically to detect changes, or look for inconsistent results. It is important to note that when the discovery process is redone, it should not generally be done from the same local address and port used in the previous discovery process. If the same local address and port are reused, bindings from the previous test may still be in existence, and these will invalidate the results of the test. Using a different local address and port for subsequent tests resolves this problem. An alternative is to wait sufficiently long to be confident that the old bindings have expired (half an hour should more than suffice).
Modifier and Type | Field and Description |
---|---|
private TransportAddress |
localAddress
The point where we'll be listening.
|
private static Logger |
logger
Our class logger.
|
private BlockingRequestSender |
requestSender
A utility used to flatten the multi thread architecture of the Stack
and execute the discovery process in a synchronized manner
|
private TransportAddress |
serverAddress
The address of the stun server
|
private IceSocketWrapper |
sock
The DatagramSocket that we are going to be running the
discovery process through.
|
private boolean |
started
Indicates whether the underlying stack has been initialized and started
and that the discoverer is operational.
|
private StunStack |
stunStack
The StunStack used by this instance for the purposes of STUN
communication.
|
Constructor and Description |
---|
NetworkConfigurationDiscoveryProcess(StunStack stunStack,
TransportAddress localAddress,
TransportAddress serverAddress)
Initializes a StunAddressDiscoverer with a specific
StunStack.
|
Modifier and Type | Method and Description |
---|---|
private void |
checkStarted()
Makes shure the discoverer is operational and throws an
StunException.ILLEGAL_STATE if that is not the case.
|
StunDiscoveryReport |
determineAddress()
Implements the discovery process itself (see class description).
|
private StunMessageEvent |
doTestI(TransportAddress serverAddress)
Sends a binding request to the specified server address.
|
private StunMessageEvent |
doTestII(TransportAddress serverAddress)
Sends a binding request to the specified server address with both change
IP and change port flags are set to true.
|
private StunMessageEvent |
doTestIII(TransportAddress serverAddress)
Sends a binding request to the specified server address with only change
port flag set to true and change IP flag - to false.
|
void |
shutDown()
Shuts down the underlying stack and prepares the object for garbage
collection.
|
void |
start()
Puts the discoverer into an operational state.
|
private static final Logger logger
private boolean started
private TransportAddress localAddress
private TransportAddress serverAddress
private BlockingRequestSender requestSender
private IceSocketWrapper sock
private final StunStack stunStack
public NetworkConfigurationDiscoveryProcess(StunStack stunStack, TransportAddress localAddress, TransportAddress serverAddress)
stunStack
- the StunStack to be used by the new instancelocalAddress
- the address where the stack should bind.serverAddress
- the address of the server to interrogate.public void shutDown()
public void start() throws IOException, StunException
IOException
- if we fail to bind.StunException
- if the stun4j stack fails start for some reason.public StunDiscoveryReport determineAddress() throws StunException, IOException
StunException
- ILLEGAL_STATE if the discoverer has not been startedIOException
- if a failure occurs while executing the discovery
algorithm.private StunMessageEvent doTestI(TransportAddress serverAddress) throws IOException, StunException
serverAddress
- the address where to send the bindingRequest.StunException
- if an exception occurs while sending the messgeIOException
- if an error occurs while sending bytes through
the socket.private StunMessageEvent doTestII(TransportAddress serverAddress) throws StunException, IOException
serverAddress
- the address where to send the bindingRequest.StunException
- if an exception occurs while sending the messgeIOException
- if an exception occurs while executing the algorithm.private StunMessageEvent doTestIII(TransportAddress serverAddress) throws StunException, IOException
serverAddress
- the address where to send the bindingRequest.StunException
- if an exception occurs while sending the messgeIOException
- if an exception occurs while sending bytes through
the socket.private void checkStarted() throws StunException
StunException
- ILLEGAL_STATE if the discoverer is not operational.Copyright © 2018. All rights reserved.