2525import java .net .Socket ;
2626import java .net .DatagramSocket ;
2727import java .net .SocketTimeoutException ;
28+ import java .lang .StringBuilder ;
29+ import java .nio .charset .StandardCharsets ;
2830
2931import com .wolfssl .WolfSSLException ;
3032import com .wolfssl .WolfSSLJNIException ;
@@ -276,6 +278,7 @@ private native int setTlsHmacInner(long ssl, byte[] inner, long sz,
276278 private native int gotCloseNotify (long ssl );
277279 private native int sslSetAlpnProtos (long ssl , byte [] alpnProtos );
278280 private native byte [] sslGet0AlpnSelected (long ssl );
281+ private native int useALPN (long ssl , String protocols , int options );
279282
280283 /* ------------------- session-specific methods --------------------- */
281284
@@ -2753,28 +2756,69 @@ public boolean sessionTicketsEnabled() throws IllegalStateException {
27532756 }
27542757
27552758 /**
2756- * Set ALPN extension protocol for this session.
2757- * Calls native SSL_set_alpn_protos() at native level. Format starts with
2759+ * Set ALPN extension protocol for this session from encoded byte array .
2760+ * Calls SSL_set_alpn_protos() at native level. Format starts with
27582761 * length, where length does not include length byte itself. Example format:
27592762 *
27602763 * byte[] p = "http/1.1".getBytes();
27612764 *
2765+ * Unless this input format is explicitly needed, useALPN(String[], int)
2766+ * will likely be easier to use.
2767+ *
27622768 * @param alpnProtos ALPN protocols, encoded as byte array vector
2763- * @return WolfSSL.SSL_SUCCESS on success, otherwise negative.
2769+ * @return WolfSSL.SSL_SUCCESS on success, otherwise negative on error .
27642770 */
2765- public int setAlpnProtos (byte [] alpnProtos ) throws IllegalStateException {
2771+ public int useALPN (byte [] alpnProtos ) throws IllegalStateException {
27662772
27672773 if (this .active == false )
27682774 throw new IllegalStateException ("Object has been freed" );
27692775
27702776 return sslSetAlpnProtos (getSessionPtr (), alpnProtos );
27712777 }
27722778
2779+ /**
2780+ * Set ALPN extension protocol for this session from String array.
2781+ * Calls native wolfSSL_useALPN(), where protocols should be a String
2782+ * array of ALPN protocols. At the native JNI level, this is converted to
2783+ * a comma-delimited list of prototocls and passed to native wolfSSL.
2784+ *
2785+ * This method is similar to useALPN(byte[]), but accepts a String array
2786+ * and calls a different native wolfSSL API for ALPN use.
2787+ *
2788+ * @param protocols Array of ALPN protocol Strings
2789+ * @param options Options to control behavior of ALPN failure mode.
2790+ * Possible options include:
2791+ * WolfSSL.WOLFSSL_ALPN_CONTINUE_ON_MISMATCH
2792+ * WolfSSL.WOLFSSL_ALPN_FAILED_ON_MISMATCH
2793+ * @return WolfSSL.SSL_SUCCESS on success, otherwise negative on error.
2794+ *
2795+ */
2796+ public int useALPN (String [] protocols , int options ) {
2797+
2798+ /* all protocols, comma delimited */
2799+ StringBuilder allProtocols = new StringBuilder ();
2800+
2801+ if (this .active == false )
2802+ throw new IllegalStateException ("Object has been freed" );
2803+
2804+ if (protocols == null ) {
2805+ return WolfSSL .BAD_FUNC_ARG ;
2806+ }
2807+
2808+ for (int i = 0 ; i < protocols .length ; i ++) {
2809+ if (i != 0 ) {
2810+ allProtocols .append ("," );
2811+ }
2812+ allProtocols .append (protocols [i ]);
2813+ }
2814+
2815+ return useALPN (getSessionPtr (), allProtocols .toString (), options );
2816+ }
2817+
27732818 /**
27742819 * Get the ALPN protocol selected by the client/server for this session.
27752820 *
2776- * @return byte array representation of selected protocol, starting with
2777- * length byte. Length does not include length byte itself.
2821+ * @return byte array representation of selected protocol.
27782822 * @throws IllegalStateException WolfSSLSession has been freed
27792823 */
27802824 public byte [] getAlpnSelected () throws IllegalStateException {
@@ -2785,6 +2829,31 @@ public byte[] getAlpnSelected() throws IllegalStateException {
27852829 return sslGet0AlpnSelected (getSessionPtr ());
27862830 }
27872831
2832+ /**
2833+ * Get the ALPN protocol selected by the client/server for this session.
2834+ *
2835+ * Same behavior as getAlpnSelected(), but returns a String instead of a
2836+ * byte array.
2837+ *
2838+ * @return String of the selected ALPN protocol
2839+ * @throws IllegalStateException WolfSSLSession has been freed
2840+ */
2841+ public String getAlpnSelectedString () throws IllegalStateException {
2842+
2843+ byte [] alpnSelectedBytes = null ;
2844+
2845+ if (this .active == false )
2846+ throw new IllegalStateException ("Object has been freed" );
2847+
2848+ alpnSelectedBytes = getAlpnSelected ();
2849+
2850+ if (alpnSelectedBytes != null ) {
2851+ return new String (alpnSelectedBytes , StandardCharsets .UTF_8 );
2852+ } else {
2853+ return null ;
2854+ }
2855+ }
2856+
27882857 /**
27892858 * Getter function to tell if shutdown has been sent or received
27902859 * @return WolfSSL.SSL_SENT_SHUTDOWN or WolfSSL.SSL_RECEIVED_SHUTDOWN
0 commit comments