All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.jetty.alpn.ALPN Maven / Gradle / Ivy

There is a newer version: 62
Show newest version
//
//  ========================================================================
//  Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.alpn;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSocket;

/**
 * 

{@link ALPN} provides an API to applications that want to make use of the * Application Layer Protocol Negotiation.

*

The ALPN extension is only available when using the TLS protocol, therefore applications must * ensure that the TLS protocol is used:

*
 * SSLContext context = SSLContext.getInstance("TLSv1");
 * 
*

Refer to the * list * of standard SSLContext protocol names for further information on TLS protocol versions supported.

*

Applications must register instances of either {@link SSLSocket} or {@link SSLEngine} with a * {@link ClientProvider} or with a {@link ServerProvider}, depending whether they are on client or * server side.

*

The ALPN implementation will invoke the provider callbacks to allow applications to interact * with the negotiation of the protocol.

*

Client side typical usage:

*
 * final SSLSocket sslSocket = ...;
 * ALPN.put(sslSocket, new ALPN.ClientProvider()
 * {
 *     @Override
 *     public List<String> protocols()
 *     {
 *         return Arrays.asList("spdy/3", "http/1.1");
 *     }
 *
 *     @Override
 *     public void unsupported()
 *     {
 *         ALPN.remove(sslSocket);
 *     }
 *
 *     @Override
 *     public void selected(String protocol) throws SSLException
 *     {
 *         System.out.println("Selected protocol: " + protocol);
 *         ALPN.remove(sslSocket);
 *     }
 *  });
 * 
*

Server side typical usage:

*
 * final SSLSocket sslSocket = ...;
 * ALPN.put(sslSocket, new ALPN.ServerProvider()
 * {
 *     @Override
 *     public void unsupported()
 *     {
 *         ALPN.remove(sslSocket);
 *     }
 *
 *     @Override
 *     public String select(List<String> protocols) throws SSLException
 *     {
 *         ALPN.remove(sslSocket);
 *         return protocols.get(0);
 *     }
 *  });
 * 
*

Applications must ensure to deregister {@link SSLSocket} or {@link SSLEngine} instances, * because they are kept in a JVM global map. * Deregistration should typically happen when the application detects the end of the protocol * negotiation, and/or when the associated socket connection is closed.

*

In order to help application development, you can set the {@link ALPN#debug} field * to {@code true} to have debug code printed to {@link System#err}.

*/ public class ALPN { /** * Flag that enables printing of debug statements to {@link System#err}. */ public static boolean debug = false; private static Map objects = new ConcurrentHashMap<>(); private ALPN() { } /** * Registers a SSLSocket with a provider. * * @param socket the socket to register with the provider * @param provider the provider to register with the socket * @see #remove(SSLSocket) */ public static void put(SSLSocket socket, Provider provider) { objects.put(socket, provider); } /** * @param socket a socket registered with {@link #put(SSLSocket, Provider)} * @return the provider registered with the given socket */ public static Provider get(SSLSocket socket) { return objects.get(socket); } /** * Unregisters the given SSLSocket. * * @param socket the socket to unregister * @return the provider registered with the socket * @see #put(SSLSocket, Provider) */ public static Provider remove(SSLSocket socket) { return objects.remove(socket); } /** * Registers a SSLEngine with a provider. * * @param engine the engine to register with the provider * @param provider the provider to register with the engine * @see #remove(SSLEngine) */ public static void put(SSLEngine engine, Provider provider) { objects.put(engine, provider); } /** * @param engine an engine registered with {@link #put(SSLEngine, Provider)} * @return the provider registered with the given engine */ public static Provider get(SSLEngine engine) { return objects.get(engine); } /** * Unregisters the given SSLEngine. * * @param engine the engine to unregister * @return the provider registered with the engine * @see #put(SSLEngine, Provider) */ public static Provider remove(SSLEngine engine) { return objects.remove(engine); } /** * Base, empty, interface for providers. */ public interface Provider { } /** * The client-side provider interface that applications must * implement to interact with the negotiation of the protocol. */ public interface ClientProvider extends Provider { /** *

Callback invoked to let the implementation know the list * of protocols that should be added to the ALPN extension in * a ClientHello TLS message.

* * @return the list of protocols supported by the client; * if {@code null} or empty, the ALPN extension is not sent */ public List protocols(); /** * Callback invoked to let the client application know that * the server does not support ALPN. */ public void unsupported(); /** *

Callback invoked to let the client application know * the protocol chosen by the server.

*

The implementation may throw an exception to indicate * that the protocol selected by the server is not acceptable, * causing the connection to be closed with a TLS alert of * type {@code no_application_protocol(120)}.

* * @param protocol the protocol selected by the server. * @throws SSLException if the protocol negotiation failed. */ public void selected(String protocol) throws SSLException; } /** * The server-side provider interface that applications must * implement to interact with the negotiation of the protocol. */ public interface ServerProvider extends Provider { /** * Callback invoked to let the server application know that * the client does not support ALPN. */ public void unsupported(); /** *

Callback invoked to let the server application select * a protocol among the ones sent by the client.

*

The implementation may throw an exception to indicate * that the protocol negotiation is not possible, * causing the connection to be closed with a TLS alert of * type {@code no_application_protocol(120)}.

* * @param protocols the protocols sent by the client. * @return the protocol selected by the server application. * A {@code null} value will indicate the server will not * include the {@code ALPN extension} message in the {@code ServerHello} * message. This means the server appears as though it doesn't support * ALPN and lets the client decide how to handle the situation. * @throws SSLException if the protocol negotiation failed. */ public String select(List protocols) throws SSLException; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy