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, setCritical
public 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 null
public 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.Object
public 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.Object
true
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()