Skip to content

Commit

Permalink
Fix publication issues (#3774)
Browse files Browse the repository at this point in the history
  • Loading branch information
e5l committed Oct 4, 2023
1 parent 51e7e5f commit f081070
Show file tree
Hide file tree
Showing 16 changed files with 79 additions and 43 deletions.
4 changes: 1 addition & 3 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@ org.gradle.jvmargs=-Xmx6g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# kotlin
kotlin.native.ignoreDisabledTargets=true
kotlin.mpp.stability.nowarn=true
kotlin.mpp.enableCompatibilityMetadataVariant=true
kotlin.mpp.enableCInteropCommonization=true
kotlin.internal.mpp.hierarchicalStructureByDefault=true
kotlin.incremental.js.ir=false
kotlin.incremental.js.klib=false
kotlin.incremental.multiplatform=true
Expand All @@ -34,7 +32,7 @@ kotlin.native.binary.memoryModel=experimental

kotlin_version=1.8.22
coroutines_version=1.7.1
atomicfu_version=0.22.2
atomicfu_version=0.22.0
slf4j_version=1.7.36
junit_version=4.13.2
logback_version=1.2.11
Expand Down
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[versions]
kotlin-version = "1.8.22"
kotlinx-html-version = "0.9.1"
coroutines-version = "1.7.2"
coroutines-version = "1.7.3"
atomicfu-version = "0.22.0"
serialization-version = "1.5.1"
validator-version = "0.8.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import platform.windows.*
import platform.windows.HINTERNET
import platform.winhttp.*

@OptIn(ExperimentalForeignApi::class)
internal enum class WinHttpCallbackStatus(val value: UInt) {
SecureFailure(WINHTTP_CALLBACK_STATUS_SECURE_FAILURE.convert<UInt>()),
HeadersAvailable(WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE.convert<UInt>()),
Expand All @@ -20,6 +21,7 @@ internal enum class WinHttpCallbackStatus(val value: UInt) {
CloseComplete(WINHTTP_CALLBACK_STATUS_CLOSE_COMPLETE.convert<UInt>())
}

@OptIn(ExperimentalForeignApi::class)
internal fun winHttpCallback(
@Suppress("UNUSED_PARAMETER")
hInternet: HINTERNET?,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ import kotlinx.cinterop.*
import platform.windows.*
import platform.winhttp.*

@OptIn(ExperimentalForeignApi::class)
internal typealias WinHttpStatusHandler = (statusInfo: LPVOID?, statusInfoLength: DWORD) -> Unit

internal class WinHttpConnect(private val hConnect: COpaquePointer) : Closeable {
internal class WinHttpConnect @OptIn(ExperimentalForeignApi::class) constructor(private val hConnect: COpaquePointer) : Closeable {

private val closed = atomic(false)

@OptIn(ExperimentalForeignApi::class)
val handlers = mutableMapOf<UInt, WinHttpStatusHandler>()

val isClosed: Boolean
Expand All @@ -28,6 +30,7 @@ internal class WinHttpConnect(private val hConnect: COpaquePointer) : Closeable
* @param url is request URL.
* @param chunkedMode is request body chunking mode.
*/
@OptIn(ExperimentalForeignApi::class)
fun openRequest(
method: HttpMethod,
url: Url,
Expand All @@ -52,10 +55,12 @@ internal class WinHttpConnect(private val hConnect: COpaquePointer) : Closeable
)
}

@OptIn(ExperimentalForeignApi::class)
fun on(status: WinHttpCallbackStatus, handler: WinHttpStatusHandler) {
handlers[status.value] = handler
}

@OptIn(ExperimentalForeignApi::class)
override fun close() {
if (!closed.compareAndSet(expect = false, update = true)) return

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import kotlinx.coroutines.*
import platform.winhttp.*
import kotlin.coroutines.*

@OptIn(ExperimentalForeignApi::class)
internal suspend inline fun <T> Closeable.closeableCoroutine(
state: WinHttpConnect,
errorMessage: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@ import kotlinx.cinterop.*
import platform.windows.*
import platform.winhttp.*

@OptIn(ExperimentalForeignApi::class)
private val winHttpModuleHandle by lazy {
GetModuleHandleW("winhttp.dll")
}
@OptIn(ExperimentalForeignApi::class)
private val languageId = makeLanguageId(LANG_NEUTRAL.convert(), SUBLANG_DEFAULT.convert())

@OptIn(ExperimentalForeignApi::class)
private val ERROR_INSUFFICIENT_BUFFER: UInt = platform.windows.ERROR_INSUFFICIENT_BUFFER.convert()

/**
Expand Down Expand Up @@ -42,6 +45,7 @@ internal fun getWinHttpException(message: String, errorCode: UInt): Exception {
/**
* Creates an error message from WinAPI error code.
*/
@OptIn(ExperimentalForeignApi::class)
internal fun getErrorMessage(errorCode: UInt): String {
return formatMessage(errorCode, winHttpModuleHandle)
?: formatMessage(errorCode)
Expand All @@ -54,6 +58,7 @@ internal fun getErrorMessage(errorCode: UInt): String {
* @param errorCode is error code.
* @param moduleHandle is DLL handle to look for message.
*/
@OptIn(ExperimentalForeignApi::class)
private fun formatMessage(errorCode: UInt, moduleHandle: HMODULE? = null): String? = memScoped {
val formatSourceFlag = if (moduleHandle != null) {
FORMAT_MESSAGE_FROM_HMODULE
Expand Down Expand Up @@ -96,7 +101,7 @@ private fun formatMessage(errorCode: UInt, moduleHandle: HMODULE? = null): Strin
errorCode,
languageId,
bufferPtr.reinterpret(),
0,
0.convert(),
null
)

Expand All @@ -112,6 +117,7 @@ private fun formatMessage(errorCode: UInt, moduleHandle: HMODULE? = null): Strin
}
}

@OptIn(ExperimentalForeignApi::class)
private fun CPointer<UShortVar>.toKStringFromUtf16(size: Int): String {
val nativeBytes = this

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,24 @@ import platform.windows.SECURITY_FLAG_IGNORE_UNKNOWN_CA
import platform.winhttp.*
import kotlin.coroutines.*

internal class WinHttpRequest(
@OptIn(ExperimentalForeignApi::class)
internal class WinHttpRequest @OptIn(ExperimentalForeignApi::class) constructor(
hSession: COpaquePointer,
data: HttpRequestData,
config: WinHttpClientEngineConfig
) : Closeable {
private val connect: WinHttpConnect

@OptIn(ExperimentalForeignApi::class)
private val hRequest: COpaquePointer
private val closed = atomic(false)
private val requestClosed = atomic(false)

@OptIn(ExperimentalForeignApi::class)
private val connectReference: StableRef<WinHttpConnect>

init {
val hConnect = WinHttpConnect(hSession, data.url.host, data.url.port.convert(), 0)
val hConnect = WinHttpConnect(hSession, data.url.host, data.url.port.convert(), 0.convert())
?: throw getWinHttpException("Unable to create connection")
connect = WinHttpConnect(hConnect)
connectReference = StableRef.create(connect)
Expand Down Expand Up @@ -58,7 +63,7 @@ internal class WinHttpRequest(
}

fun upgradeToWebSocket() {
if (WinHttpSetOption(hRequest, WINHTTP_OPTION_UPGRADE_TO_WEB_SOCKET, null, 0) == 0) {
if (WinHttpSetOption(hRequest, WINHTTP_OPTION_UPGRADE_TO_WEB_SOCKET.convert(), null, 0.convert()) == 0) {
throw getWinHttpException("Unable to request WebSocket upgrade")
}
}
Expand Down Expand Up @@ -86,8 +91,8 @@ internal class WinHttpRequest(
headersString,
headersString.length.convert(),
WINHTTP_NO_REQUEST_DATA,
0,
WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH,
0.convert(),
WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH.convert(),
statePtr.convert()
) == 0
) {
Expand Down Expand Up @@ -201,6 +206,7 @@ internal class WinHttpRequest(
*
* @param callContext is call context.
*/
@OptIn(ExperimentalForeignApi::class)
fun createWebSocket(callContext: CoroutineContext): WinHttpWebSocket {
val statePtr = connectReference.asCPointer().rawValue.toLong()
val hWebsocket = WinHttpWebSocketCompleteUpgrade(hRequest, statePtr.convert())
Expand All @@ -214,14 +220,15 @@ internal class WinHttpRequest(
/**
* Disables built-in features which are handled by Ktor client.
*/
@OptIn(ExperimentalForeignApi::class)
private fun configureFeatures() = memScoped {
val options = alloc<DWORDVar> {
value = (WINHTTP_DISABLE_COOKIES or WINHTTP_DISABLE_REDIRECTS).convert()
}

if (WinHttpSetOption(
hRequest,
WINHTTP_OPTION_DISABLE_FEATURE,
WINHTTP_OPTION_DISABLE_FEATURE.convert(),
options.ptr,
sizeOf<DWORDVar>().convert()
) == 0
Expand All @@ -233,6 +240,7 @@ internal class WinHttpRequest(
/**
* Receive status callbacks about all operations.
*/
@OptIn(ExperimentalForeignApi::class)
private fun configureStatusCallback(enable: Boolean) = memScoped {
val notifications = WINHTTP_CALLBACK_FLAG_ALL_COMPLETIONS.convert<UInt>()
val callback = if (enable) {
Expand All @@ -241,7 +249,7 @@ internal class WinHttpRequest(
null
}

val oldStatusCallback = WinHttpSetStatusCallback(hRequest, callback, notifications, 0)
val oldStatusCallback = WinHttpSetStatusCallback(hRequest, callback, notifications, 0.convert())
if (oldStatusCallback?.rawValue?.toLong() == WINHTTP_INVALID_STATUS_CALLBACK) {
val errorCode = GetLastError()
if (errorCode != ERROR_INVALID_HANDLE) {
Expand All @@ -255,6 +263,7 @@ internal class WinHttpRequest(
*
* @param protocolVersion is required protocol version.
*/
@OptIn(ExperimentalForeignApi::class)
private fun enableHttpProtocols(protocolVersion: HttpProtocolVersion) = memScoped {
if (protocolVersion != HttpProtocolVersion.HTTP_2_0) return@memScoped
val flags = alloc<UIntVar> {
Expand All @@ -266,6 +275,7 @@ internal class WinHttpRequest(
/**
* Disables TLS verification for testing purposes.
*/
@OptIn(ExperimentalForeignApi::class)
private fun disableTlsVerification() = memScoped {
val flags = alloc<UIntVar> {
value = (
Expand All @@ -275,7 +285,7 @@ internal class WinHttpRequest(
SECURITY_FLAG_IGNORE_CERT_DATE_INVALID
).convert()
}
if (WinHttpSetOption(hRequest, WINHTTP_OPTION_SECURITY_FLAGS, flags.ptr, UINT_SIZE) == 0) {
if (WinHttpSetOption(hRequest, WINHTTP_OPTION_SECURITY_FLAGS.convert(), flags.ptr, UINT_SIZE) == 0) {
throw getWinHttpException("Unable to disable TLS verification")
}
}
Expand All @@ -291,13 +301,15 @@ internal class WinHttpRequest(
/**
* Gets a string length in bytes.
*/
@OptIn(ExperimentalForeignApi::class)
private fun getLength(dwSize: UIntVar) = (dwSize.value / sizeOf<ShortVar>().convert()).convert<Int>()

/**
* Returns a header value.
*
* @param headerId is header identifier.
*/
@OptIn(ExperimentalForeignApi::class)
private fun getHeader(headerId: Int): String = memScoped {
val dwSize = alloc<UIntVar>()

Expand All @@ -321,6 +333,7 @@ internal class WinHttpRequest(
/**
* Gets a HTTP protocol version from server response.
*/
@OptIn(ExperimentalForeignApi::class)
private fun isHttp2Response() = memScoped {
val flags = alloc<UIntVar>()
val dwSize = alloc<UIntVar> {
Expand All @@ -334,13 +347,15 @@ internal class WinHttpRequest(
false
}

@OptIn(ExperimentalForeignApi::class)
private fun closeRequest() {
if (!requestClosed.compareAndSet(expect = false, update = true)) return

configureStatusCallback(enable = false)
WinHttpCloseHandle(hRequest)
}

@OptIn(ExperimentalForeignApi::class)
override fun close() {
if (!closed.compareAndSet(expect = false, update = true)) return

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ import io.ktor.utils.io.pool.*
import kotlinx.atomicfu.*
import kotlinx.cinterop.*
import kotlinx.coroutines.*
import kotlin.collections.MutableMap
import kotlin.collections.mutableMapOf
import kotlin.collections.set
import kotlin.coroutines.*

Expand Down Expand Up @@ -57,6 +55,7 @@ internal class WinHttpRequestProducer(
}
}

@OptIn(ExperimentalForeignApi::class)
private suspend fun writeChunkedBody(requestBody: ByteReadChannel, readBuffer: ByteArray) {
while (true) {
val readBytes = requestBody.readAvailable(readBuffer).takeIf { it > 0 } ?: break
Expand All @@ -67,6 +66,7 @@ internal class WinHttpRequestProducer(
}
}

@OptIn(ExperimentalForeignApi::class)
private suspend fun writeBodyChunk(readBuffer: ByteArray, length: Int) {
// Write chunk length
val chunkStart = "${length.toString(16)}\r\n".toByteArray()
Expand All @@ -83,6 +83,7 @@ internal class WinHttpRequestProducer(
}
}

@OptIn(ExperimentalForeignApi::class)
private suspend fun writeRegularBody(requestBody: ByteReadChannel, readBuffer: ByteArray) {
while (true) {
val readBytes = requestBody.readAvailable(readBuffer).takeIf { it > 0 } ?: break
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import kotlinx.cinterop.*
import kotlinx.coroutines.*
import kotlin.coroutines.*

@OptIn(DelicateCoroutinesApi::class)
@OptIn(DelicateCoroutinesApi::class, ExperimentalForeignApi::class)
internal fun WinHttpRequest.readBody(callContext: CoroutineContext): ByteReadChannel {
return GlobalScope.writer(callContext) {
val readBuffer = ByteArrayPool.borrow()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,19 @@ import kotlinx.atomicfu.*
import kotlinx.cinterop.*
import platform.winhttp.*

@OptIn(ExperimentalForeignApi::class)
internal class WinHttpSession(private val config: WinHttpClientEngineConfig) : Closeable {

@OptIn(ExperimentalForeignApi::class)
private var hSession: COpaquePointer

private val closed = atomic(false)
private val timeoutConfigured = atomic(false)

init {
hSession = WinHttpOpen(
WINHTTP_NO_USER_AGENT,
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY.convert(),
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS,
WINHTTP_FLAG_ASYNC.convert()
Expand Down Expand Up @@ -67,7 +70,7 @@ internal class WinHttpSession(private val config: WinHttpClientEngineConfig) : C
value = protocol.value.convert()
}
val dwSize = sizeOf<UIntVar>().convert<UInt>()
WinHttpSetOption(hSession, WINHTTP_OPTION_SECURE_PROTOCOLS, options.ptr, dwSize)
WinHttpSetOption(hSession, WINHTTP_OPTION_SECURE_PROTOCOLS.convert(), options.ptr, dwSize)
}

private fun setTimeouts(resolveTimeout: Int, connectTimeout: Int, sendTimeout: Int, receiveTimeout: Int) {
Expand All @@ -86,7 +89,7 @@ internal class WinHttpSession(private val config: WinHttpClientEngineConfig) : C

if (WinHttpSetOption(
hSession,
WINHTTP_OPTION_PROXY,
WINHTTP_OPTION_PROXY.convert(),
proxyInfo.ptr,
sizeOf<WINHTTP_PROXY_INFO>().convert()
) == 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ private object WinHttpWebSocketBuffer {
val Close = WINHTTP_WEB_SOCKET_CLOSE_BUFFER_TYPE
}

internal class WinHttpWebSocket(
@OptIn(ExperimentalForeignApi::class)
internal class WinHttpWebSocket @OptIn(ExperimentalForeignApi::class) constructor(
private val hWebSocket: COpaquePointer,
private val connect: WinHttpConnect,
callContext: CoroutineContext
Expand Down Expand Up @@ -236,7 +237,7 @@ internal class WinHttpWebSocket(
hWebSocket,
status.ptr,
null,
0,
0.convert(),
reasonLengthConsumed.ptr
) != 0u
) {
Expand Down Expand Up @@ -280,7 +281,7 @@ internal class WinHttpWebSocket(
hWebSocket,
WINHTTP_WEB_SOCKET_SUCCESS_CLOSE_STATUS.convert(),
NULL,
0
0.convert()
)
WinHttpCloseHandle(hWebSocket)
connect.close()
Expand Down
Loading

0 comments on commit f081070

Please sign in to comment.