Skip to content

Commit e936caf

Browse files
authored
kn: address misc issues (#173)
1 parent d3cfab0 commit e936caf

File tree

14 files changed

+170
-64
lines changed

14 files changed

+170
-64
lines changed

aws-crt-kotlin/native/src/aws/sdk/kotlin/crt/auth/signing/AwsSignerNative.kt

Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import aws.sdk.kotlin.crt.util.asAwsByteCursor
1212
import aws.sdk.kotlin.crt.util.initFromCursor
1313
import aws.sdk.kotlin.crt.util.toAwsString
1414
import aws.sdk.kotlin.crt.util.toKString
15+
import aws.sdk.kotlin.crt.util.use
1516
import kotlinx.cinterop.*
1617
import kotlinx.coroutines.channels.Channel
1718
import kotlinx.coroutines.runBlocking
@@ -31,34 +32,37 @@ public actual object AwsSigner : WithCrt() {
3132
request: HttpRequest,
3233
config: AwsSigningConfig,
3334
): AwsSigningResult = memScoped {
34-
val nativeRequest = request.toNativeRequest().pin()
35-
36-
// Pair of HTTP request and callback channel containing the signature
37-
val userData = nativeRequest to Channel<ByteArray>(1)
38-
val userDataStableRef = StableRef.create(userData)
39-
40-
val signable = checkNotNull(
41-
aws_signable_new_http_request(
42-
allocator = Allocator.Default.allocator,
43-
request = nativeRequest.get(),
44-
),
45-
) { "aws_signable_new_http_request" }
46-
47-
val nativeSigningConfig: CPointer<aws_signing_config_base> = config.toNativeSigningConfig().reinterpret()
48-
49-
awsAssertOpSuccess(
50-
aws_sign_request_aws(
51-
allocator = Allocator.Default.allocator,
52-
signable = signable,
53-
base_config = nativeSigningConfig,
54-
on_complete = staticCFunction(::signCallback),
55-
userdata = userDataStableRef.asCPointer(),
56-
),
57-
) { "sign() aws_sign_request_aws" }
58-
59-
val callbackChannel = userDataStableRef.get().second
60-
val signature = callbackChannel.receive() // wait for async signing to complete....
61-
return AwsSigningResult(nativeRequest.get().toHttpRequest(), signature)
35+
request.toNativeRequest().usePinned { nativeRequest ->
36+
// Pair of HTTP request and callback channel containing the signature
37+
val userData = nativeRequest to Channel<ByteArray>(1)
38+
val userDataStableRef = StableRef.create(userData)
39+
40+
val signable = checkNotNull(
41+
aws_signable_new_http_request(
42+
allocator = Allocator.Default.allocator,
43+
request = nativeRequest.get(),
44+
),
45+
) { "aws_signable_new_http_request" }
46+
47+
val nativeSigningConfig: CPointer<aws_signing_config_base> = config.toNativeSigningConfig().reinterpret()
48+
49+
awsAssertOpSuccess(
50+
aws_sign_request_aws(
51+
allocator = Allocator.Default.allocator,
52+
signable = signable,
53+
base_config = nativeSigningConfig,
54+
on_complete = staticCFunction(::signCallback),
55+
userdata = userDataStableRef.asCPointer(),
56+
),
57+
) { "sign() aws_sign_request_aws" }
58+
59+
val callbackChannel = userDataStableRef.get().second
60+
val signature = callbackChannel.receive() // wait for async signing to complete....
61+
return AwsSigningResult(nativeRequest.get().toHttpRequest(), signature).also {
62+
userDataStableRef.dispose()
63+
callbackChannel.close()
64+
}
65+
}
6266
}
6367

6468
public actual suspend fun signChunk(
@@ -223,9 +227,11 @@ private fun nativeShouldSignHeaderFn(headerName: CPointer<aws_byte_cursor>?, use
223227
return true
224228
}
225229

226-
val kShouldSignHeaderFn = userData.asStableRef<ShouldSignHeaderFunction>().get()
227-
val kHeaderName = headerName.pointed.toKString()
228-
return kShouldSignHeaderFn(kHeaderName)
230+
userData.asStableRef<ShouldSignHeaderFunction>().use {
231+
val kShouldSignHeaderFn = it.get()
232+
val kHeaderName = headerName.pointed.toKString()
233+
return kShouldSignHeaderFn(kHeaderName)
234+
}
229235
}
230236

231237
/**

aws-crt-kotlin/native/src/aws/sdk/kotlin/crt/http/HttpClientConnectionManagerNative.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ public actual class HttpClientConnectionManager actual constructor(
157157
actual override fun close() {
158158
if (closed.compareAndSet(false, true)) {
159159
aws_http_connection_manager_release(manager)
160+
shutdownCompleteStableRef.dispose()
160161
}
161162
}
162163
}

aws-crt-kotlin/native/src/aws/sdk/kotlin/crt/http/HttpClientConnectionNative.kt

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import aws.sdk.kotlin.crt.io.ByteCursorBuffer
1010
import aws.sdk.kotlin.crt.util.asAwsByteCursor
1111
import aws.sdk.kotlin.crt.util.initFromCursor
1212
import aws.sdk.kotlin.crt.util.toKString
13+
import aws.sdk.kotlin.crt.util.use
1314
import aws.sdk.kotlin.crt.util.withAwsByteCursor
1415
import kotlinx.atomicfu.atomic
1516
import kotlinx.cinterop.*
@@ -93,30 +94,33 @@ private fun onResponseHeaders(
9394
numHeaders: size_t,
9495
userdata: COpaquePointer?,
9596
): Int {
96-
val ctx = userdata?.asStableRef<HttpStreamContext>()?.get() ?: return aws_raise_error(AWS_ERROR_HTTP_CALLBACK_FAILURE.toInt())
97-
val stream = ctx.stream ?: return AWS_OP_ERR
97+
val ctxStableRef = userdata?.asStableRef<HttpStreamContext>() ?: return aws_raise_error(AWS_ERROR_HTTP_CALLBACK_FAILURE.toInt())
98+
ctxStableRef.use {
99+
val ctx = it.get()
100+
val stream = ctx.stream ?: return AWS_OP_ERR
101+
102+
val hdrCnt = numHeaders.toInt()
103+
val headers: List<HttpHeader>? = if (hdrCnt > 0 && headerArray != null) {
104+
val kheaders = mutableListOf<HttpHeader>()
105+
for (i in 0 until hdrCnt) {
106+
val nativeHdr = headerArray[i]
107+
val hdr = HttpHeader(nativeHdr.name.toKString(), nativeHdr.value.toKString())
108+
kheaders.add(hdr)
109+
}
110+
kheaders
111+
} else {
112+
null
113+
}
98114

99-
val hdrCnt = numHeaders.toInt()
100-
val headers: List<HttpHeader>? = if (hdrCnt > 0 && headerArray != null) {
101-
val kheaders = mutableListOf<HttpHeader>()
102-
for (i in 0 until hdrCnt) {
103-
val nativeHdr = headerArray[i]
104-
val hdr = HttpHeader(nativeHdr.name.toKString(), nativeHdr.value.toKString())
105-
kheaders.add(hdr)
115+
try {
116+
ctx.handler.onResponseHeaders(stream, stream.responseStatusCode, blockType.value.toInt(), headers)
117+
} catch (ex: Exception) {
118+
log(LogLevel.Error, "onResponseHeaders: $ex")
119+
return aws_raise_error(AWS_ERROR_HTTP_CALLBACK_FAILURE.toInt())
106120
}
107-
kheaders
108-
} else {
109-
null
110-
}
111121

112-
try {
113-
ctx.handler.onResponseHeaders(stream, stream.responseStatusCode, blockType.value.toInt(), headers)
114-
} catch (ex: Exception) {
115-
log(LogLevel.Error, "onResponseHeaders: $ex")
116-
return aws_raise_error(AWS_ERROR_HTTP_CALLBACK_FAILURE.toInt())
122+
return AWS_OP_SUCCESS
117123
}
118-
119-
return AWS_OP_SUCCESS
120124
}
121125

122126
private fun onResponseHeaderBlockDone(

aws-crt-kotlin/native/src/aws/sdk/kotlin/crt/http/HttpStreamNative.kt

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import aws.sdk.kotlin.crt.CrtRuntimeException
99
import aws.sdk.kotlin.crt.NativeHandle
1010
import aws.sdk.kotlin.crt.awsAssertOpSuccess
1111
import aws.sdk.kotlin.crt.util.asAwsByteCursor
12+
import aws.sdk.kotlin.crt.util.use
1213
import kotlinx.atomicfu.atomic
1314
import kotlinx.cinterop.*
1415
import libcrt.*
@@ -66,18 +67,19 @@ internal class HttpStreamNative(
6667
throw CrtRuntimeException("aws_input_stream_new_from_cursor()")
6768
}
6869

69-
val req = StableRef.create(WriteChunkRequest(cont, byteBuf, stream))
70-
val chunkOpts = cValue<aws_http1_chunk_options> {
71-
chunk_data_size = chunkData.size.convert()
72-
chunk_data = stream
73-
on_complete = staticCFunction(::onWriteChunkComplete)
74-
user_data = req.asCPointer()
75-
}
76-
awsAssertOpSuccess(
77-
aws_http1_stream_write_chunk(ptr, chunkOpts),
78-
) {
79-
cleanupWriteChunkCbData(req)
80-
"aws_http1_stream_write_chunk()"
70+
StableRef.create(WriteChunkRequest(cont, byteBuf, stream)).use { req ->
71+
val chunkOpts = cValue<aws_http1_chunk_options> {
72+
chunk_data_size = chunkData.size.convert()
73+
chunk_data = stream
74+
on_complete = staticCFunction(::onWriteChunkComplete)
75+
user_data = req.asCPointer()
76+
}
77+
awsAssertOpSuccess(
78+
aws_http1_stream_write_chunk(ptr, chunkOpts),
79+
) {
80+
cleanupWriteChunkCbData(req)
81+
"aws_http1_stream_write_chunk()"
82+
}
8183
}
8284
}
8385

aws-crt-kotlin/native/src/aws/sdk/kotlin/crt/io/ClientBootstrapNative.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public actual class ClientBootstrap private constructor(
5252

5353
actual override fun close() {
5454
aws_client_bootstrap_release(ptr)
55+
channelStableRef.dispose()
5556

5657
if (manageHr) hr.close()
5758
if (manageElg) elg.close()

aws-crt-kotlin/native/src/aws/sdk/kotlin/crt/io/EventLoopGroupNative.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ public actual class EventLoopGroup actual constructor(maxThreads: Int) :
5858

5959
actual override fun close() {
6060
aws_event_loop_group_release(ptr)
61+
channelStableRef.dispose()
6162
}
6263
}
6364

aws-crt-kotlin/native/src/aws/sdk/kotlin/crt/io/HostResolverNative.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ public actual class HostResolver private constructor(
5555

5656
actual override fun close() {
5757
aws_host_resolver_release(ptr)
58+
channelStableRef.dispose()
5859

5960
if (manageElg) elg.close()
6061
}

aws-crt-kotlin/native/src/aws/sdk/kotlin/crt/io/MutableBufferNative.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,9 @@ private sealed interface InnerBuffer {
9191
init {
9292
pointer.pointed.len = 0.convert()
9393
pointer.pointed.capacity = dest.size.convert()
94-
pointer.pointed.buffer = pinned.addressOf(0).reinterpret()
94+
pointer.pointed.buffer = pinned.takeUnless { dest.isEmpty() }
95+
?.addressOf(0)
96+
?.reinterpret()
9597
}
9698

9799
override fun release() {

aws-crt-kotlin/native/src/aws/sdk/kotlin/crt/util/Interop.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55
package aws.sdk.kotlin.crt.util
66

7+
import kotlinx.cinterop.StableRef
78
import kotlinx.coroutines.channels.Channel
89

910
/**
@@ -15,3 +16,14 @@ internal typealias ShutdownChannel = Channel<Unit>
1516
* Create a new shutdown notification channel
1617
*/
1718
internal fun shutdownChannel(): ShutdownChannel = Channel(Channel.RENDEZVOUS)
19+
20+
/**
21+
* Execute [block] using [StableRef], then dispose it.
22+
*/
23+
internal inline fun <T : Any, R> StableRef<T>.use(block: (StableRef<T>) -> R): R {
24+
try {
25+
return block(this)
26+
} finally {
27+
dispose()
28+
}
29+
}

aws-crt-kotlin/native/src/aws/sdk/kotlin/crt/util/hashing/CrcNative.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ internal class Crc(val checksumFn: AwsChecksumsCrcFunction) : HashFunction {
2424
private var crc = 0U
2525

2626
override fun update(input: ByteArray, offset: Int, length: Int) {
27+
require(offset >= 0) { "offset must not be negative" }
28+
require(length >= 0) { "length must not be negative" }
29+
require(offset + length <= input.size) {
30+
"offset + length must not exceed input size: $offset + $length > ${input.size}"
31+
}
32+
2733
if (input.isEmpty() || length == 0) {
2834
return
2935
}

0 commit comments

Comments
 (0)