Index: tls.c
==================================================================
--- tls.c
+++ tls.c
@@ -748,10 +748,11 @@
     char *CAdir		        = NULL;
     char *DHparams	        = NULL;
     char *model		        = NULL;
 #ifndef OPENSSL_NO_TLSEXT
     char *servername	        = NULL;	/* hostname for Server Name Indication */
+    Tcl_Obj *alpn		= NULL;
 #endif
     int ssl2 = 0, ssl3 = 0;
     int tls1 = 1, tls1_1 = 1, tls1_2 = 1, tls1_3 = 1;
     int proto = 0;
     int verify = 0, require = 0, request = 1;
@@ -810,10 +811,11 @@
 	OPTBOOL( "-require", require);
 	OPTBOOL( "-request", request);
 	OPTBOOL( "-server", server);
 #ifndef OPENSSL_NO_TLSEXT
         OPTSTR( "-servername", servername);
+	OPTOBJ( "-alpn", alpn);
 #endif
 
 	OPTBOOL( "-ssl2", ssl2);
 	OPTBOOL( "-ssl3", ssl3);
 	OPTBOOL( "-tls1", tls1);
@@ -821,11 +823,11 @@
 	OPTBOOL( "-tls1.2", tls1_2);
 	OPTBOOL( "-tls1.3", tls1_3);
   OPTBYTE("-cert", cert, cert_len);
   OPTBYTE("-key", key, key_len);
 
-	OPTBAD( "option", "-cadir, -cafile, -cert, -certfile, -cipher, -command, -dhparams, -key, -keyfile, -model, -password, -require, -request, -server, -servername, -ssl2, -ssl3, -tls1, -tls1.1, -tls1.2, or tls1.3");
+	OPTBAD( "option", "-alpn, -cadir, -cafile, -cert, -certfile, -cipher, -command, -dhparams, -key, -keyfile, -model, -password, -require, -request, -server, -servername, -ssl2, -ssl3, -tls1, -tls1.1, -tls1.2, or tls1.3");
 
 	return TCL_ERROR;
     }
     if (request)	    verify |= SSL_VERIFY_CLIENT_ONCE | SSL_VERIFY_PEER;
     if (request && require) verify |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
@@ -958,10 +960,51 @@
                 (char *) NULL);
             Tls_Free((char *) statePtr);
             return TCL_ERROR;
         }
     }
+    if (alpn) {
+	/* Convert a Tcl list into a protocol-list in wire-format */
+	unsigned char *protos, *p;
+	unsigned int protoslen = 0;
+	int i, len, cnt;
+	Tcl_Obj **list;
+	if (Tcl_ListObjGetElements(interp, alpn, &cnt, &list) != TCL_OK) {
+	    Tls_Free((char *) statePtr);
+	    return TCL_ERROR;
+	}
+	/* Determine the memory required for the protocol-list */
+	for (i = 0; i < cnt; i++) {
+	    Tcl_GetStringFromObj(list[i], &len);
+	    if (len > 255) {
+		Tcl_AppendResult(interp, "alpn protocol name too long",
+		  (char *) NULL);
+		Tls_Free((char *) statePtr);
+		return TCL_ERROR;
+	    }
+	    protoslen += 1 + len;
+	}
+	/* Build the complete protocol-list */
+	protos = ckalloc(protoslen);
+	/* protocol-lists consist of 8-bit length-prefixed, byte strings */
+	for (i = 0, p = protos; i < cnt; i++) {
+	    char *str = Tcl_GetStringFromObj(list[i], &len);
+	    *p++ = len;
+	    memcpy(p, str, len);
+	    p += len;
+	}
+	/* Note: This functions reverses the return value convention */
+	if (SSL_set_alpn_protos(statePtr->ssl, protos, protoslen)) {
+	    Tcl_AppendResult(interp, "failed to set alpn protocols",
+	      (char *) NULL);
+	    Tls_Free((char *) statePtr);
+	    ckfree(protos);
+	    return TCL_ERROR;
+	}
+	/* SSL_set_alpn_protos makes a copy of the protocol-list */
+	ckfree(protos);
+    }
 #endif
 
     /*
      * SSL Callbacks
      */
@@ -1409,10 +1452,14 @@
     X509 *peer;
     Tcl_Obj *objPtr;
     Tcl_Channel chan;
     char *channelName, *ciphers;
     int mode;
+#ifndef OPENSSL_NO_TLSEXT
+    const unsigned char *proto;
+    unsigned int len;
+#endif
 
     dprintf("Called");
 
     switch (objc) {
 	case 2:
@@ -1423,10 +1470,11 @@
 	    if (!strcmp (Tcl_GetString (objv[1]), "-local")) {
 		channelName = Tcl_GetStringFromObj(objv[2], NULL);
 		break;
 	    }
 	    /* else fall... */
+	    __attribute__((fallthrough));
 	default:
 	    Tcl_WrongNumArgs(interp, 1, objv, "?-local? channel");
 	    return TCL_ERROR;
     }
 
@@ -1466,10 +1514,18 @@
 	Tcl_ListObjAppendElement(interp, objPtr,
 		Tcl_NewStringObj("cipher", -1));
 	Tcl_ListObjAppendElement(interp, objPtr,
 		Tcl_NewStringObj(SSL_get_cipher(statePtr->ssl), -1));
     }
+
+#ifndef OPENSSL_NO_TLSEXT
+    /* Report the selected protocol as a result of the negotiation */
+    SSL_get0_alpn_selected(statePtr->ssl, &proto, &len);
+    Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj("alpn", -1));
+    Tcl_ListObjAppendElement(interp, objPtr,
+      Tcl_NewStringObj((char *)proto, (int)len));
+#endif
 
     Tcl_ListObjAppendElement(interp, objPtr,
 	Tcl_NewStringObj("version", -1));
     Tcl_ListObjAppendElement(interp, objPtr,
 	Tcl_NewStringObj(SSL_get_version(statePtr->ssl), -1));

Index: tls.htm
==================================================================
--- tls.htm
+++ tls.htm
@@ -147,10 +147,13 @@
             server channels.</dd>
         <dt><strong>sbits</strong> <em>n</em></dt>
         <dd>The number of bits used for the session key.</dd>
         <dt><strong>certificate</strong> <em>n</em></dt>
         <dd>The PEM encoded certificate.</dd>
+        <dt><strong>alpn</strong> <em>protocol</em></dt>
+        <dd>The protocol selected after Application-Layer Protocol
+	    Negotiation (ALPN).</dd>
         <dt><strong>version</strong> <em>value</em></dt>
         <dd>The protocol version used for the connection:
 	  SSLv2, SSLv3, TLSv1, TLSv1.1, TLSv1.2, unknown</dd>
     </dl>
 </blockquote>
@@ -163,10 +166,13 @@
         setting session parameters for SSL handshake.</dd>
 </dl>
 
 <blockquote>
     <dl>
+        <dt><strong>-alpn</strong> <em>list</em></dt>
+        <dd>List of protocols to offer during Application-Layer
+	    Protocol Negotiation (ALPN).</dd>
         <dt><strong>-cadir</strong> <em>dir</em></dt>
         <dd>Provide the directory containing the CA certificates.</dd>
         <dt><strong>-cafile </strong><em>filename</em></dt>
         <dd>Provide the CA file.</dd>
         <dt><strong>-certfile</strong> <em>filename</em></dt>

Index: tls.tcl
==================================================================
--- tls.tcl
+++ tls.tcl
@@ -44,10 +44,11 @@
         {* -password iopts 1}
         {* -request iopts 1}
         {* -require iopts 1}
         {* -autoservername discardOpts 1}
         {* -servername iopts 1}
+        {* -alpn iopts 1}
         {* -ssl2 iopts 1}
         {* -ssl3 iopts 1}
         {* -tls1 iopts 1}
         {* -tls1.1 iopts 1}
         {* -tls1.2 iopts 1}

