@@ -7,11 +7,7 @@ package aws.sdk.kotlin.crt.http
7
7
import aws.sdk.kotlin.crt.*
8
8
import aws.sdk.kotlin.crt.io.Buffer
9
9
import 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.*
15
11
import kotlinx.atomicfu.atomic
16
12
import kotlinx.cinterop.*
17
13
import libcrt.*
@@ -87,105 +83,100 @@ private class HttpStreamContext(
87
83
val nativeReq : CPointer <cnames.structs.aws_http_message>,
88
84
)
89
85
86
+ private fun callbackError (): Int = aws_raise_error(AWS_ERROR_HTTP_CALLBACK_FAILURE .toInt())
87
+
90
88
private fun onResponseHeaders (
91
89
nativeStream : CPointer <cnames.structs.aws_http_stream>? ,
92
90
blockType : aws_http_header_block,
93
91
headerArray : CPointer <aws_http_header>? ,
94
92
numHeaders : size_t,
95
93
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
109
108
}
110
- kheaders
111
- } else {
112
- null
113
- }
114
109
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
+ }
120
117
}
121
-
122
- return AWS_OP_SUCCESS
123
- }
124
- }
118
+ } ? : callbackError()
125
119
126
120
private fun onResponseHeaderBlockDone (
127
121
nativeStream : CPointer <cnames.structs.aws_http_stream>? ,
128
122
blockType : aws_http_header_block,
129
123
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()
143
136
144
137
private fun onIncomingBody (
145
138
nativeStream : CPointer <cnames.structs.aws_http_stream>? ,
146
139
data : CPointer <aws_byte_cursor>? ,
147
140
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
+ }
161
160
}
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()
169
162
170
163
private fun onStreamComplete (
171
164
nativeStream : CPointer <cnames.structs.aws_http_stream>? ,
172
165
errorCode : Int ,
173
166
userdata : COpaquePointer ? ,
174
167
) {
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
+ }
189
180
}
190
181
}
191
182
0 commit comments