public class ALPNProtocolNameList extends Extension implements java.lang.Cloneable
ProtocolNameList structure
as used by the application_layer_protocol_negotiation TLS extension
(see RFC 7301).
The application_layer_protocol_negotiation (ALPN) extension allows to negotiate the application layer protocol within the TLS handshake. For doing so the client sends an ALPN extension containing the names of the application layer protocols it supports (in preference order). The server compares the protocol names got from the client with its locally configured list and sends back an ALPN extension containing the first of its protocol names that matches to any of the protocol names received from the client. If the server does not support any of the client protocols it sends back a fatal "NO APPLICATION PROTOCOL" alert.
RFC 7301 defines an ALPN ProtocolNameList as list of
protocol names:
opaque ProtocolName<1..2^8-1>;
struct {
ProtocolName protocol_name_list<2..2^16-1>
} ProtocolNameList;
When creating an ALPNProtocolName
object the encoded and/or not encoded name value have to be specified, e.g.:
String protocolName = ...; byte[] encodedProtocolName = ...; ALPNProtocolName protocolName = new ALPNProtocolName(protocolName, encodedProtocolName);If the encoded name is not specified it is UTF-8 encoding before sent to the peer. If the name is not specified the encoded name is UTF-8 decoded.
On the client side you will use the ALPNProtocolName class
to build an ALPNProtocolNameList to be sent to the server. You can create
ALPNProtocolName objects on your own or use any of the predefined names e.g.:
// create protocol name list for http/1.1 and http/2
ALPNProtocolName[] protocolNames = { ALPNProtocolName.PN_HTTP_11, ALPNProtocolName.PN_H_2 };
ALPNProtocolNameList protocolNameList = new ALPNProtocolNameList(protocolNames);
// add to ExtensionList
ExtensionList extensions = new ExtensionList();
...
extensions.addExtension(protocolNameList);
...
// set extensions for the SSLClientContext configuration:
SSLClientContext clientContext = new SSLClientContext();
...
clientContext.setExtensions(extensions);
...
When having finished the handshake you may get the negotiated protocol name
by asking the SSLSocket for the ProtocolNameList included in the active
extension list (extensions negotiated between client and server) or in
the peer extension list (extensions got from the server). Since the server
is only allowed to send an ALPN extension containing one protocol name
only, the ALPNProtocolNameList got from the active extension list should be
equal to the one got from the peer extension list (if the server has sent
back an ALPN extension):
SSLContext clientContext = ...;
...
// set extensions (including ALPN)
...
String serverName = ...;
int serverPort = ...;
// create SSLSocket, perform handshake, e.g.:
SSLSocket sslSocket = new SSLSocket(serverName, serverPort, clientContext);
sslSocket.startHandshake();
...
// get ALPN extension and protocol name sent by the server:
ExtensionList activeExtensions = socket.getActiveExtensions();
if (activeExtensions != null) {
ALPNProtocolNameList protocolNameList = (ALPNProtocolNameList)activeExtensions.getExtension(ALPNProtocolNameList.TYPE);
if (protocolNameList != null) {
ALPNProtocolName[] protocolNames = protocolNameList.getProtocolNames();
System.out.println("Using ALPN protocol: " + protocolNames[0]);
}
}
If you set the critical
flag of a client-side ALPNProtocolNameList to true (client-side
default), the handshake will be aborted if the server does not respond with a
ALPN extension or has sent an ALPN extension containing none or more than
one protocol names. If the server has sent an "no_application_protocol" fatal
alert, the handshake will be aborted in any case, regardless if the client-side
ALPNProtocolNameList extension is configured as critical or not critical.
On the server side you may use the ALPNProtocolName class
to build an ALPNProtocolNameList to tell the server which protocol names may be
accepted from the client e.g.:
// create protocol name list for http/1.1 and http/2
ALPNProtocolName[] protocolNames = { ALPNProtocolName.PN_HTTP_11, ALPNProtocolName.PN_H_2 };
ALPNProtocolNameList protocolNameList = new ALPNProtocolNameList(protocolNames);
// add to ExtensionList
ExtensionList extensions = new ExtensionList();
...
extensions.addExtension(protocolNameList);
...
// set extensions for the SSLServerContext configuration:
SSLServerContext serverContext = new SSLServerContext();
...
serverContext.setExtensions(extensions);
...
If you set the critical
flag of a server-side application_layer_protocol_negotiation extension to true, the
handshake will be aborted if the client does not send a application_layer_protocol_negotiation
extension within the extended ClientHello message or the client has sent an empty ALPN
extension.
By default ALPN extensions are not critical.
ALPNProtocolName,
Extension,
ExtensionList| Modifier and Type | Field and Description |
|---|---|
static ExtensionType |
TYPE
The type (16) of the application_layer_protocol_negotiation extension.
|
| Constructor and Description |
|---|
ALPNProtocolNameList()
Creates a new ALPNProtocolNameList.
|
ALPNProtocolNameList(ALPNProtocolName protocolName)
Creates an ALPNProtocolNameList for the given protocol name.
|
ALPNProtocolNameList(ALPNProtocolName[] protocolNames)
Creates an ALPNProtocolNameList for the given protocol names.
|
| Modifier and Type | Method and Description |
|---|---|
java.lang.Object |
clone()
Returns a clone of this protocol name list.
|
boolean |
contains(ALPNProtocolName protocolName)
Checks if this protocol name list contains the given protocol name.
|
boolean |
equals(java.lang.Object obj)
Checks if this protocol name list is equal to the given object.
|
ALPNProtocolName[] |
getProtocolNames()
Gets the protocol names included in this protocol name list.
|
int |
hashCode()
Gets a hash code of this protocol name list.
|
void |
setProtocolNames(ALPNProtocolName[] protocolNames)
Sets the protocol names of this protocol name list.
|
int |
size()
Gets the number of protocol names included in this protocol name list.
|
java.lang.String |
toString()
Gets a String representation of this protocol name list.
|
getAllowedProtocolVersions, getExtensionType, getName, getType, setCriticalpublic static final ExtensionType TYPE
public ALPNProtocolNameList()
setProtocolNames or method addProtocolName.public ALPNProtocolNameList(ALPNProtocolName[] protocolNames)
protocolNames - the protocol namesjava.lang.IllegalArgumentException - if the given ALPNProtocolNames array is empty or contains
a null elementpublic ALPNProtocolNameList(ALPNProtocolName protocolName)
Additional protocol names may be added by calling method
.addProtocolName
protocolName - the protocol namejava.lang.IllegalArgumentException - if the given ALPNProtocolName is nullpublic ALPNProtocolName[] getProtocolNames()
public void setProtocolNames(ALPNProtocolName[] protocolNames)
protocolNames - the protocol names to be setjava.lang.IllegalArgumentException - if the given ALPNProtocolNames array is empty or contains
a null elementpublic int size()
public int hashCode()
hashCode in class java.lang.Objectpublic boolean equals(java.lang.Object obj)
Two protocol name list are treated as equal if they contain the same
ALPNProtocolName objects (same number and same order). The critical
value is not checked by this method.
equals in class java.lang.Objecttrue if this ALPNProtocolNameList is equal to the
given object, false if it is not equal
to itpublic boolean contains(ALPNProtocolName protocolName)
true if this protocol name list contains the given
protocol name, false if it does not contain itpublic java.lang.Object clone()