Skip to content

Commit 178c5b3

Browse files
committed
grpc-native: Add default TLS support
Signed-off-by: Johannes Zottele <[email protected]>
1 parent 565ea07 commit 178c5b3

File tree

7 files changed

+168
-84
lines changed

7 files changed

+168
-84
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package kotlinx.rpc.grpc.test.proto
6+
7+
import hello.HelloRequest
8+
import hello.HelloService
9+
import hello.invoke
10+
import kotlinx.coroutines.test.runTest
11+
import kotlinx.rpc.grpc.GrpcClient
12+
import kotlinx.rpc.withService
13+
import kotlin.test.Test
14+
15+
16+
class GrpcbInTlsTest {
17+
18+
val grpcClient = GrpcClient("grpcb.in", 9001) {
19+
// usePlaintext()
20+
}
21+
22+
@Test
23+
fun testTlsCall() = runTest {
24+
val service = grpcClient.withService<HelloService>()
25+
26+
val request = HelloRequest {
27+
greeting = "Postman"
28+
}
29+
val result = service.SayHello(request)
30+
31+
println(result.reply)
32+
}
33+
34+
35+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
syntax = "proto2";
2+
3+
// grpc://grpcb.in:9000 (without TLS)
4+
// grpc://grpcb.in:9001 (with TLS)
5+
6+
7+
package hello;
8+
9+
service HelloService {
10+
rpc SayHello(HelloRequest) returns (HelloResponse);
11+
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);
12+
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);
13+
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse);
14+
}
15+
16+
message HelloRequest {
17+
optional string greeting = 1;
18+
}
19+
20+
message HelloResponse {
21+
required string reply = 1;
22+
}

grpc/grpc-core/src/nativeMain/kotlin/kotlinx/rpc/grpc/ManagedChannel.native.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ package kotlinx.rpc.grpc
99
import kotlinx.rpc.grpc.internal.GrpcChannel
1010
import kotlinx.rpc.grpc.internal.GrpcChannelCredentials
1111
import kotlinx.rpc.grpc.internal.GrpcInsecureChannelCredentials
12+
import kotlinx.rpc.grpc.internal.GrpcSslChannelCredentials
1213
import kotlinx.rpc.grpc.internal.NativeManagedChannel
1314
import kotlinx.rpc.grpc.internal.internalError
1415

@@ -29,17 +30,17 @@ public actual abstract class ManagedChannelBuilder<T : ManagedChannelBuilder<T>>
2930
internal class NativeManagedChannelBuilder(
3031
private val target: String,
3132
) : ManagedChannelBuilder<NativeManagedChannelBuilder>() {
32-
private var credentials: GrpcChannelCredentials? = null
33+
private var credentials: Lazy<GrpcChannelCredentials> = lazy { GrpcSslChannelCredentials() }
3334

3435
override fun usePlaintext(): NativeManagedChannelBuilder {
35-
credentials = GrpcInsecureChannelCredentials()
36+
credentials = lazy { GrpcInsecureChannelCredentials() }
3637
return this
3738
}
3839

3940
fun buildChannel(): NativeManagedChannel {
4041
return NativeManagedChannel(
4142
target,
42-
credentials = credentials ?: error("No credentials set"),
43+
credentials = credentials.value,
4344
)
4445
}
4546

grpc/grpc-core/src/nativeMain/kotlin/kotlinx/rpc/grpc/internal/NativeManagedChannel.kt

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import cnames.structs.grpc_channel_credentials
1111
import kotlinx.atomicfu.atomic
1212
import kotlinx.cinterop.CPointer
1313
import kotlinx.cinterop.ExperimentalForeignApi
14+
import kotlinx.cinterop.memScoped
1415
import kotlinx.coroutines.CompletableDeferred
1516
import kotlinx.coroutines.Job
1617
import kotlinx.coroutines.SupervisorJob
@@ -27,13 +28,14 @@ import libkgrpc.grpc_channel_credentials_release
2728
import libkgrpc.grpc_channel_destroy
2829
import libkgrpc.grpc_insecure_credentials_create
2930
import libkgrpc.grpc_slice_unref
31+
import libkgrpc.grpc_ssl_credentials_create_ex
3032
import kotlin.coroutines.cancellation.CancellationException
3133
import kotlin.experimental.ExperimentalNativeApi
3234
import kotlin.native.ref.createCleaner
3335
import kotlin.time.Duration
3436

3537
/**
36-
* Wrapper for [cnames.structs.grpc_channel_credentials].
38+
* Wrapper for [grpc_channel_credentials].
3739
*/
3840
internal sealed class GrpcChannelCredentials(
3941
internal val raw: CPointer<grpc_channel_credentials>,
@@ -47,8 +49,28 @@ internal sealed class GrpcChannelCredentials(
4749
* Insecure credentials.
4850
*/
4951
internal class GrpcInsecureChannelCredentials() :
50-
GrpcChannelCredentials(grpc_insecure_credentials_create() ?: error("Failed to create channel credentials"))
52+
GrpcChannelCredentials(
53+
grpc_insecure_credentials_create() ?: error("grpc_insecure_credentials_create() returned null")
54+
)
5155

56+
/**
57+
* SSL credentials.
58+
*/
59+
internal class GrpcSslChannelCredentials(
60+
raw: CPointer<grpc_channel_credentials>,
61+
) : GrpcChannelCredentials(raw) {
62+
63+
constructor() : this(
64+
memScoped {
65+
grpc_ssl_credentials_create_ex(
66+
null,
67+
null,
68+
null,
69+
null
70+
) ?: error("grpc_ssl_credentials_create() returned null")
71+
}
72+
)
73+
}
5274

5375
/**
5476
* Native implementation of [ManagedChannel].

protobuf/protobuf-core/src/commonMain/kotlin/kotlinx/rpc/protobuf/internal/ProtobufException.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public class ProtobufDecodingException : ProtobufException {
1313
public constructor(message: String, cause: Throwable? = null) : super(message, cause)
1414

1515
public companion object Companion {
16-
internal fun missingRequiredField(messageName: String, fieldName: String) =
16+
public fun missingRequiredField(messageName: String, fieldName: String): ProtobufDecodingException =
1717
ProtobufDecodingException("Message '$messageName' is missing a required field: $fieldName")
1818

1919
internal fun negativeSize() = ProtobufDecodingException(

tests/compiler-plugin-tests/src/test-gen/kotlinx/rpc/codegen/test/runners/BoxTestGenerated.java

Lines changed: 38 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,51 +7,53 @@
77
package kotlinx.rpc.codegen.test.runners;
88

99
import com.intellij.testFramework.TestDataPath;
10-
import org.jetbrains.kotlin.test.util.KtTestUtil;
1110
import org.jetbrains.kotlin.test.TargetBackend;
1211
import org.jetbrains.kotlin.test.TestMetadata;
12+
import org.jetbrains.kotlin.test.util.KtTestUtil;
1313
import org.junit.jupiter.api.Test;
1414

1515
import java.io.File;
1616
import java.util.regex.Pattern;
1717

18-
/** This class is generated by {@link kotlinx.rpc.codegen.test.GenerateTestsKt}. DO NOT MODIFY MANUALLY */
18+
/**
19+
* This class is generated by {@link kotlinx.rpc.codegen.test.GenerateTestsKt}. DO NOT MODIFY MANUALLY
20+
*/
1921
@SuppressWarnings("all")
2022
@TestMetadata("src/testData/box")
2123
@TestDataPath("$PROJECT_ROOT")
2224
public class BoxTestGenerated extends AbstractBoxTest {
23-
@Test
24-
public void testAllFilesPresentInBox() {
25-
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("src/testData/box"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
26-
}
27-
28-
@Test
29-
@TestMetadata("customParameterTypes.kt")
30-
public void testCustomParameterTypes() {
31-
runTest("src/testData/box/customParameterTypes.kt");
32-
}
33-
34-
@Test
35-
@TestMetadata("flowParameter.kt")
36-
public void testFlowParameter() {
37-
runTest("src/testData/box/flowParameter.kt");
38-
}
39-
40-
@Test
41-
@TestMetadata("grpc.kt")
42-
public void testGrpc() {
43-
runTest("src/testData/box/grpc.kt");
44-
}
45-
46-
@Test
47-
@TestMetadata("multiModule.kt")
48-
public void testMultiModule() {
49-
runTest("src/testData/box/multiModule.kt");
50-
}
51-
52-
@Test
53-
@TestMetadata("simple.kt")
54-
public void testSimple() {
55-
runTest("src/testData/box/simple.kt");
56-
}
25+
@Test
26+
public void testAllFilesPresentInBox() {
27+
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("src/testData/box"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
28+
}
29+
30+
@Test
31+
@TestMetadata("customParameterTypes.kt")
32+
public void testCustomParameterTypes() {
33+
runTest("src/testData/box/customParameterTypes.kt");
34+
}
35+
36+
@Test
37+
@TestMetadata("flowParameter.kt")
38+
public void testFlowParameter() {
39+
runTest("src/testData/box/flowParameter.kt");
40+
}
41+
42+
@Test
43+
@TestMetadata("grpc.kt")
44+
public void testGrpc() {
45+
runTest("src/testData/box/grpc.kt");
46+
}
47+
48+
@Test
49+
@TestMetadata("multiModule.kt")
50+
public void testMultiModule() {
51+
runTest("src/testData/box/multiModule.kt");
52+
}
53+
54+
@Test
55+
@TestMetadata("simple.kt")
56+
public void testSimple() {
57+
runTest("src/testData/box/simple.kt");
58+
}
5759
}

tests/compiler-plugin-tests/src/test-gen/kotlinx/rpc/codegen/test/runners/DiagnosticTestGenerated.java

Lines changed: 44 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -7,57 +7,59 @@
77
package kotlinx.rpc.codegen.test.runners;
88

99
import com.intellij.testFramework.TestDataPath;
10-
import org.jetbrains.kotlin.test.util.KtTestUtil;
1110
import org.jetbrains.kotlin.test.TargetBackend;
1211
import org.jetbrains.kotlin.test.TestMetadata;
12+
import org.jetbrains.kotlin.test.util.KtTestUtil;
1313
import org.junit.jupiter.api.Test;
1414

1515
import java.io.File;
1616
import java.util.regex.Pattern;
1717

18-
/** This class is generated by {@link kotlinx.rpc.codegen.test.GenerateTestsKt}. DO NOT MODIFY MANUALLY */
18+
/**
19+
* This class is generated by {@link kotlinx.rpc.codegen.test.GenerateTestsKt}. DO NOT MODIFY MANUALLY
20+
*/
1921
@SuppressWarnings("all")
2022
@TestMetadata("src/testData/diagnostics")
2123
@TestDataPath("$PROJECT_ROOT")
2224
public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
23-
@Test
24-
public void testAllFilesPresentInDiagnostics() {
25-
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("src/testData/diagnostics"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
26-
}
27-
28-
@Test
29-
@TestMetadata("checkedAnnotation.kt")
30-
public void testCheckedAnnotation() {
31-
runTest("src/testData/diagnostics/checkedAnnotation.kt");
32-
}
33-
34-
@Test
35-
@TestMetadata("grpc.kt")
36-
public void testGrpc() {
37-
runTest("src/testData/diagnostics/grpc.kt");
38-
}
39-
40-
@Test
41-
@TestMetadata("rpcChecked.kt")
42-
public void testRpcChecked() {
43-
runTest("src/testData/diagnostics/rpcChecked.kt");
44-
}
45-
46-
@Test
47-
@TestMetadata("rpcService.kt")
48-
public void testRpcService() {
49-
runTest("src/testData/diagnostics/rpcService.kt");
50-
}
51-
52-
@Test
53-
@TestMetadata("strictMode.kt")
54-
public void testStrictMode() {
55-
runTest("src/testData/diagnostics/strictMode.kt");
56-
}
57-
58-
@Test
59-
@TestMetadata("withCodec.kt")
60-
public void testWithCodec() {
61-
runTest("src/testData/diagnostics/withCodec.kt");
62-
}
25+
@Test
26+
public void testAllFilesPresentInDiagnostics() {
27+
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("src/testData/diagnostics"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
28+
}
29+
30+
@Test
31+
@TestMetadata("checkedAnnotation.kt")
32+
public void testCheckedAnnotation() {
33+
runTest("src/testData/diagnostics/checkedAnnotation.kt");
34+
}
35+
36+
@Test
37+
@TestMetadata("grpc.kt")
38+
public void testGrpc() {
39+
runTest("src/testData/diagnostics/grpc.kt");
40+
}
41+
42+
@Test
43+
@TestMetadata("rpcChecked.kt")
44+
public void testRpcChecked() {
45+
runTest("src/testData/diagnostics/rpcChecked.kt");
46+
}
47+
48+
@Test
49+
@TestMetadata("rpcService.kt")
50+
public void testRpcService() {
51+
runTest("src/testData/diagnostics/rpcService.kt");
52+
}
53+
54+
@Test
55+
@TestMetadata("strictMode.kt")
56+
public void testStrictMode() {
57+
runTest("src/testData/diagnostics/strictMode.kt");
58+
}
59+
60+
@Test
61+
@TestMetadata("withCodec.kt")
62+
public void testWithCodec() {
63+
runTest("src/testData/diagnostics/withCodec.kt");
64+
}
6365
}

0 commit comments

Comments
 (0)