diff --git a/src/main/c/netty_quic_quiche.c b/src/main/c/netty_quic_quiche.c index e7049b7da..a49e65457 100644 --- a/src/main/c/netty_quic_quiche.c +++ b/src/main/c/netty_quic_quiche.c @@ -208,6 +208,23 @@ static jint netty_quic_quiche_conn_close(JNIEnv* env, jclass clazz, jlong conn, return quiche_conn_close((quiche_conn *) conn, app == JNI_TRUE ? true : false, err, (const uint8_t *) reason, (size_t) reason_len); } +static jbyteArray netty_quic_quiche_conn_application_proto(JNIEnv* env, jclass clazz, jlong conn) { + const uint8_t *app_proto = NULL; + size_t app_proto_len; + + quiche_conn_application_proto((quiche_conn *) conn, &app_proto, &app_proto_len); + if (app_proto == NULL || app_proto_len == 0) { + return NULL; + } + jbyteArray array = (*env)->NewByteArray(env, app_proto_len); + if (array == NULL) { + return NULL; + } + (*env)->SetByteArrayRegion(env,array,0,app_proto_len, (jbyte*) app_proto); + return array; +} + + static jboolean netty_quic_quiche_conn_is_established(JNIEnv* env, jclass clazz, jlong conn) { return quiche_conn_is_established((quiche_conn *) conn) == true ? JNI_TRUE : JNI_FALSE; } @@ -429,6 +446,7 @@ static const JNINativeMethod fixed_method_table[] = { { "quiche_conn_stream_shutdown", "(JJIJ)I", (void *) netty_quic_quiche_conn_stream_shutdown }, { "quiche_conn_stream_capacity", "(JJ)I", (void *) netty_quic_quiche_conn_stream_capacity }, { "quiche_conn_stream_finished", "(JJ)Z", (void *) netty_quic_quiche_conn_stream_finished }, + { "quiche_conn_application_proto", "(J)[B", (void *) netty_quic_quiche_conn_application_proto }, { "quiche_conn_close", "(JZJJI)I", (void *) netty_quic_quiche_conn_close }, { "quiche_conn_is_established", "(J)Z", (void *) netty_quic_quiche_conn_is_established }, { "quiche_conn_is_in_early_data", "(J)Z", (void *) netty_quic_quiche_conn_is_in_early_data }, diff --git a/src/main/java/io/netty/incubator/codec/quic/QuicChannel.java b/src/main/java/io/netty/incubator/codec/quic/QuicChannel.java index 1690d0403..7c52a44c9 100644 --- a/src/main/java/io/netty/incubator/codec/quic/QuicChannel.java +++ b/src/main/java/io/netty/incubator/codec/quic/QuicChannel.java @@ -39,4 +39,9 @@ public interface QuicChannel extends Channel { */ Future createStream(QuicStreamAddress address, ChannelHandler handler, Promise promise); + + /** + * Returns the negotiated ALPN protocol or {@code null} if non has been negotiated. + */ + byte[] applicationProtocol(); } diff --git a/src/main/java/io/netty/incubator/codec/quic/Quiche.java b/src/main/java/io/netty/incubator/codec/quic/Quiche.java index d253d68b6..9de535b00 100644 --- a/src/main/java/io/netty/incubator/codec/quic/Quiche.java +++ b/src/main/java/io/netty/incubator/codec/quic/Quiche.java @@ -266,6 +266,13 @@ static native int quiche_retry(long scidAddr, int scidLen, long dcidAddr, int dc */ static native int quiche_conn_close(long connAddr, boolean app, long err, long reasonAddr, int reasonLen); + /** + * See + * + * quiche_conn_application_proto. + */ + static native byte[] quiche_conn_application_proto(long connAddr); + /** * See * quiche_conn_is_established. diff --git a/src/main/java/io/netty/incubator/codec/quic/QuicheQuicChannel.java b/src/main/java/io/netty/incubator/codec/quic/QuicheQuicChannel.java index ab0e029ba..77e4121ee 100644 --- a/src/main/java/io/netty/incubator/codec/quic/QuicheQuicChannel.java +++ b/src/main/java/io/netty/incubator/codec/quic/QuicheQuicChannel.java @@ -195,6 +195,14 @@ public void run() { return promise; } + @Override + public byte[] applicationProtocol() { + if (isConnDestroyed()) { + return null; + } + return Quiche.quiche_conn_application_proto(connAddr); + } + @Override public String toString() { String traceId = this.traceId;