@@ -7,11 +7,7 @@ package aws.sdk.kotlin.crt.http
77import aws.sdk.kotlin.crt.*
88import aws.sdk.kotlin.crt.io.Buffer
99import aws.sdk.kotlin.crt.io.ByteCursorBuffer
10- import aws.sdk.kotlin.crt.util.asAwsByteCursor
11- import aws.sdk.kotlin.crt.util.initFromCursor
12- import aws.sdk.kotlin.crt.util.toKString
13- import aws.sdk.kotlin.crt.util.use
14- import aws.sdk.kotlin.crt.util.withAwsByteCursor
10+ import aws.sdk.kotlin.crt.util.*
1511import kotlinx.atomicfu.atomic
1612import kotlinx.cinterop.*
1713import libcrt.*
@@ -87,105 +83,100 @@ private class HttpStreamContext(
8783 val nativeReq : CPointer <cnames.structs.aws_http_message>,
8884)
8985
86+ private fun callbackError (): Int = aws_raise_error(AWS_ERROR_HTTP_CALLBACK_FAILURE .toInt())
87+
9088private fun onResponseHeaders (
9189 nativeStream : CPointer <cnames.structs.aws_http_stream>? ,
9290 blockType : aws_http_header_block,
9391 headerArray : CPointer <aws_http_header>? ,
9492 numHeaders : size_t,
9593 userdata : COpaquePointer ? ,
96- ): Int {
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)
94+ ): Int =
95+ userdata?.withDereferenced<HttpStreamContext , _ > { ctx ->
96+ ctx.stream?.let { stream ->
97+ val hdrCnt = numHeaders.toInt()
98+ val headers: List <HttpHeader >? = if (hdrCnt > 0 && headerArray != null ) {
99+ val kheaders = mutableListOf<HttpHeader >()
100+ for (i in 0 until hdrCnt) {
101+ val nativeHdr = headerArray[i]
102+ val hdr = HttpHeader (nativeHdr.name.toKString(), nativeHdr.value.toKString())
103+ kheaders.add(hdr)
104+ }
105+ kheaders
106+ } else {
107+ null
109108 }
110- kheaders
111- } else {
112- null
113- }
114109
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())
110+ try {
111+ ctx.handler.onResponseHeaders(stream, stream.responseStatusCode, blockType.value.toInt(), headers)
112+ AWS_OP_SUCCESS
113+ } catch (ex: Exception ) {
114+ log(LogLevel .Error , " onResponseHeaders: $ex " )
115+ null
116+ }
120117 }
121-
122- return AWS_OP_SUCCESS
123- }
124- }
118+ } ? : callbackError()
125119
126120private fun onResponseHeaderBlockDone (
127121 nativeStream : CPointer <cnames.structs.aws_http_stream>? ,
128122 blockType : aws_http_header_block,
129123 userdata : COpaquePointer ? ,
130- ): Int {
131- val ctx = userdata?.asStableRef<HttpStreamContext >()?.get() ? : return AWS_OP_ERR
132- val stream = ctx.stream ? : return AWS_OP_ERR
133-
134- try {
135- ctx.handler.onResponseHeadersDone(stream, blockType.value.toInt())
136- } catch (ex: Exception ) {
137- log(LogLevel .Error , " onResponseHeaderBlockDone: $ex " )
138- return aws_raise_error(AWS_ERROR_HTTP_CALLBACK_FAILURE .toInt())
139- }
140-
141- return AWS_OP_SUCCESS
142- }
124+ ): Int =
125+ userdata?.withDereferenced<HttpStreamContext , _ > { ctx ->
126+ ctx.stream?.let { stream ->
127+ try {
128+ ctx.handler.onResponseHeadersDone(stream, blockType.value.toInt())
129+ AWS_OP_SUCCESS
130+ } catch (ex: Exception ) {
131+ log(LogLevel .Error , " onResponseHeaderBlockDone: $ex " )
132+ null
133+ }
134+ }
135+ } ? : callbackError()
143136
144137private fun onIncomingBody (
145138 nativeStream : CPointer <cnames.structs.aws_http_stream>? ,
146139 data : CPointer <aws_byte_cursor>? ,
147140 userdata : COpaquePointer ? ,
148- ): Int {
149- val ctx = userdata?.asStableRef<HttpStreamContext >()?.get() ? : return AWS_OP_ERR
150- val stream = ctx.stream ? : return AWS_OP_ERR
151-
152- try {
153- val body = if (data != null ) ByteCursorBuffer (data) else Buffer .Empty
154- val windowIncrement = ctx.handler.onResponseBody(stream, body)
155- if (windowIncrement < 0 ) {
156- return aws_raise_error(AWS_ERROR_HTTP_CALLBACK_FAILURE .toInt())
157- }
158-
159- if (windowIncrement > 0 ) {
160- aws_http_stream_update_window(nativeStream, windowIncrement.convert())
141+ ): Int =
142+ userdata?.withDereferenced<HttpStreamContext , _ > { ctx ->
143+ ctx.stream?.let { stream ->
144+ try {
145+ val body = if (data != null ) ByteCursorBuffer (data) else Buffer .Empty
146+ val windowIncrement = ctx.handler.onResponseBody(stream, body)
147+
148+ if (windowIncrement < 0 ) {
149+ null
150+ } else {
151+ if (windowIncrement > 0 ) {
152+ aws_http_stream_update_window(nativeStream, windowIncrement.convert())
153+ }
154+ AWS_OP_SUCCESS
155+ }
156+ } catch (ex: Exception ) {
157+ log(LogLevel .Error , " onIncomingBody: $ex " )
158+ null
159+ }
161160 }
162- } catch (ex: Exception ) {
163- log(LogLevel .Error , " onIncomingBody: $ex " )
164- return aws_raise_error(AWS_ERROR_HTTP_CALLBACK_FAILURE .toInt())
165- }
166-
167- return AWS_OP_SUCCESS
168- }
161+ } ? : callbackError()
169162
170163private fun onStreamComplete (
171164 nativeStream : CPointer <cnames.structs.aws_http_stream>? ,
172165 errorCode : Int ,
173166 userdata : COpaquePointer ? ,
174167) {
175- val stableRef = userdata?.asStableRef<HttpStreamContext >() ? : return
176- val ctx = stableRef.get()
177- val stream = ctx.stream ? : return
178-
179- try {
180- ctx.handler.onResponseComplete(stream, errorCode)
181- } catch (ex: Exception ) {
182- log(LogLevel .Error , " onStreamComplete: $ex " )
183- // close connection if callback throws an exception
184- aws_http_connection_close(aws_http_stream_get_connection(nativeStream))
185- } finally {
186- // cleanup stream resources
187- stableRef.dispose()
188- aws_http_message_destroy(ctx.nativeReq)
168+ userdata?.withDereferenced<HttpStreamContext >(dispose = true ) { ctx ->
169+ try {
170+ val stream = ctx.stream ? : return
171+ ctx.handler.onResponseComplete(stream, errorCode)
172+ } catch (ex: Exception ) {
173+ log(LogLevel .Error , " onStreamComplete: $ex " )
174+ // close connection if callback throws an exception
175+ aws_http_connection_close(aws_http_stream_get_connection(nativeStream))
176+ } finally {
177+ // cleanup request object
178+ aws_http_message_release(ctx.nativeReq)
179+ }
189180 }
190181}
191182
0 commit comments