1
0
mirror of https://github.com/mamoe/mirai.git synced 2025-04-25 04:50:26 +08:00

Multiplatform HttpClient and fix time formatting

This commit is contained in:
Him188 2022-06-01 01:37:04 +01:00
parent 4fe56409ec
commit 7a3576fe3e
No known key found for this signature in database
GPG Key ID: BA439CDDCF652375
21 changed files with 188 additions and 43 deletions
mirai-core-utils
build.gradle.kts
src
mingwX64Main/kotlin
mingwX64Test/kotlin
nativeMain/kotlin
mirai-core
build.gradle.kts
src
commonMain/kotlin
commonTest/kotlin/event
darwinMain/kotlin
darwinTest/kotlin
jvmBaseMain/kotlin
linuxX64Main/kotlin
linuxX64Test/kotlin
mingwX64Main/kotlin
nativeTest/kotlin/network/framework

View File

@ -76,7 +76,7 @@ kotlin {
}
}
val mingwMain by getting {
val mingwX64Main by getting {
dependencies {
}
}

View File

@ -11,8 +11,13 @@
package net.mamoe.mirai.utils
import kotlinx.atomicfu.locks.ReentrantLock
import kotlinx.atomicfu.locks.withLock
import kotlinx.cinterop.*
import platform.posix.*
import platform.posix.localtime
import platform.posix.strftime
import platform.posix.time
import platform.posix.time_tVar
/**
* 时间戳
@ -27,18 +32,22 @@ public actual fun currentTimeMillis(): Long {
}
}
private val timeLock = ReentrantLock()
@OptIn(UnsafeNumber::class)
public actual fun currentTimeFormatted(format: String?): String {
public actual fun currentTimeFormatted(format: String?): String = timeLock.withLock {
memScoped {
val timeT = alloc<time_tVar>()
time(timeT.ptr)
val tm = localtime(timeT.ptr)
try {
val bb = allocArray<ByteVar>(40)
strftime(bb, 40, "%Y-%M-%d %H:%M:%S", tm);
return bb.toKString()
} finally {
free(tm)
}
// http://www.cplusplus.com/reference/clibrary/ctime/localtime/
// tm returns a static pointer which doesn't need to free
val tm = localtime(timeT.ptr) // localtime is not thread-safe
val bb = allocArray<ByteVar>(40)
strftime(bb, 40, "%Y-%M-%d %H:%M:%S", tm);
bb.toKString()
}
}

View File

@ -57,6 +57,8 @@ kotlin {
implementation(bouncycastle)
implementation(`log4j-api`)
implementation(`netty-all`)
implementation(`ktor-client-okhttp`)
api(`kotlinx-coroutines-core`)
}
}
@ -103,23 +105,25 @@ kotlin {
}
}
val mingwMain by getting {
dependencies {
}
}
configure((LINUX_TARGETS + WIN_TARGETS).map { getByName(it + "Main") }) {
configure(WIN_TARGETS.map { getByName(it + "Main") }) {
dependencies {
implementation(`ktor-client-curl`)
}
}
configure(MAC_TARGETS.map { getByName(it + "Main") }) {
configure(LINUX_TARGETS.map { getByName(it + "Main") }) {
dependencies {
implementation(`ktor-client-curl`)
}
}
val darwinMain by getting {
dependencies {
implementation(`ktor-client-ios`)
}
}
disableCrossCompile()
// val unixMain by getting {
// dependencies {
// implementation(`ktor-client-cio`)

View File

@ -12,6 +12,7 @@
package net.mamoe.mirai.internal
import io.ktor.client.*
import io.ktor.client.engine.*
import io.ktor.client.features.*
import io.ktor.client.request.*
import io.ktor.client.request.forms.*
@ -72,6 +73,8 @@ import kotlin.jvm.JvmName
internal fun getMiraiImpl() = Mirai as MiraiImpl
internal expect fun createDefaultHttpClient(): HttpClient
@Suppress("FunctionName")
internal expect fun _MiraiImpl_static_init()
@ -152,13 +155,7 @@ internal open class MiraiImpl : IMirai, LowLevelApiAccessor {
override var FileCacheStrategy: FileCacheStrategy = net.mamoe.mirai.utils.FileCacheStrategy.PlatformDefault
@Deprecated("Mirai is not going to use ktor. This is deprecated for removal.", level = DeprecationLevel.WARNING)
override var Http: HttpClient = HttpClient() {
install(HttpTimeout) {
this.requestTimeoutMillis = 30_0000
this.connectTimeoutMillis = 30_0000
this.socketTimeoutMillis = 30_0000
}
}
override var Http: HttpClient = createDefaultHttpClient()
override suspend fun acceptNewFriendRequest(event: NewFriendRequestEvent) {
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")

View File

@ -12,14 +12,12 @@ package net.mamoe.mirai.internal.event
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.first
import me.him188.kotlin.jvm.blocking.bridge.JvmBlockingBridge
import net.mamoe.mirai.event.GlobalEventChannel
import net.mamoe.mirai.event.broadcast
import net.mamoe.mirai.internal.test.runBlockingUnit
import kotlin.test.Test
import kotlin.test.assertIs
@JvmBlockingBridge
internal class EventChannelFlowTest : AbstractEventTest() {
@Test

View File

@ -21,7 +21,6 @@ import net.mamoe.mirai.event.events.MessageEvent
import kotlin.coroutines.coroutineContext
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine
import kotlin.test.*
internal class EventChannelTest : AbstractEventTest() {
@ -37,7 +36,7 @@ internal class EventChannelTest : AbstractEventTest() {
@Test
fun singleFilter() {
runBlocking {
val received = suspendCoroutine<Int> { cont ->
val received = suspendCancellableCoroutine { cont ->
globalEventChannel()
.filterIsInstance<TE>()
.filter {
@ -69,7 +68,7 @@ internal class EventChannelTest : AbstractEventTest() {
@Test
fun multipleFilters() {
runBlocking {
val received = suspendCoroutine<Int> { cont ->
val received = suspendCancellableCoroutine { cont ->
globalEventChannel()
.filterIsInstance<TE>()
.filter {
@ -109,7 +108,7 @@ internal class EventChannelTest : AbstractEventTest() {
fun multipleContexts1() {
runBlocking {
withContext(CoroutineName("1")) {
val received = suspendCoroutine<Int> { cont ->
val received = suspendCancellableCoroutine { cont ->
globalEventChannel()
.context(CoroutineName("2"))
.context(CoroutineName("3"))
@ -132,7 +131,7 @@ internal class EventChannelTest : AbstractEventTest() {
fun multipleContexts2() {
runBlocking {
withContext(CoroutineName("1")) {
val received = suspendCoroutine<Int> { cont ->
val received = suspendCancellableCoroutine { cont ->
globalEventChannel()
.context(CoroutineName("2"))
.context(CoroutineName("3"))
@ -156,7 +155,7 @@ internal class EventChannelTest : AbstractEventTest() {
fun multipleContexts3() {
runBlocking {
withContext(CoroutineName("1")) {
val received = suspendCoroutine<Int> { cont ->
val received = suspendCancellableCoroutine { cont ->
globalEventChannel()
.context(CoroutineName("2"))
.subscribeOnce<TE> {
@ -178,7 +177,7 @@ internal class EventChannelTest : AbstractEventTest() {
fun multipleContexts4() {
runBlocking {
withContext(CoroutineName("1")) {
val received = suspendCoroutine<Int> { cont ->
val received = suspendCancellableCoroutine { cont ->
globalEventChannel()
.subscribeOnce<TE> {
assertEquals("1", currentCoroutineContext()[CoroutineName]!!.name)
@ -250,7 +249,8 @@ internal class EventChannelTest : AbstractEventTest() {
fun testExceptionInFilter() {
assertFailsWith<ExceptionInEventChannelFilterException> {
runBlocking {
suspendCoroutine<Int> { cont ->
@Suppress("RemoveExplicitTypeArguments")
suspendCancellableCoroutine<Int> { cont ->
globalEventChannel()
.exceptionHandler {
cont.resumeWithException(it)
@ -278,7 +278,7 @@ internal class EventChannelTest : AbstractEventTest() {
fun testExceptionInSubscribe() {
runBlocking {
assertFailsWith<IllegalStateException> {
suspendCoroutine<Int> { cont ->
suspendCancellableCoroutine<Int> { cont ->
val handler = CoroutineExceptionHandler { _, throwable ->
cont.resumeWithException(throwable)
}

View File

@ -60,10 +60,11 @@ internal class EventTests : AbstractEventTest() {
resetEventListeners()
var listeners = 0
val counter = atomic(0)
val channel = scope.globalEventChannel()
for (p in EventPriority.values()) {
repeat(2333) {
listeners++
scope.globalEventChannel().subscribeAlways<ParentEvent> {
channel.subscribeAlways<ParentEvent> {
counter.getAndIncrement()
}
}

View File

@ -0,0 +1,24 @@
/*
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
package net.mamoe.mirai.internal
import io.ktor.client.*
import io.ktor.client.engine.ios.*
import io.ktor.client.features.*
internal actual fun createDefaultHttpClient(): HttpClient {
return HttpClient(Ios) {
install(HttpTimeout) {
this.requestTimeoutMillis = 30_0000
this.connectTimeoutMillis = 30_0000
this.socketTimeoutMillis = 30_0000
}
}
}

View File

@ -0,0 +1,10 @@
/*
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
package net.mamoe.mirai.internal

View File

@ -11,7 +11,23 @@
package net.mamoe.mirai.internal
import io.ktor.client.*
import io.ktor.client.engine.okhttp.*
import io.ktor.client.features.*
@Suppress("FunctionName")
internal actual fun _MiraiImpl_static_init() {
// nop
}
internal actual fun createDefaultHttpClient(): HttpClient {
return HttpClient(OkHttp) {
install(HttpTimeout) {
this.requestTimeoutMillis = 30_0000
this.connectTimeoutMillis = 30_0000
this.socketTimeoutMillis = 30_0000
}
}
}

View File

@ -0,0 +1,24 @@
/*
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
package net.mamoe.mirai.internal
import io.ktor.client.*
import io.ktor.client.engine.curl.*
import io.ktor.client.features.*
internal actual fun createDefaultHttpClient(): HttpClient {
return HttpClient(Curl) {
install(HttpTimeout) {
this.requestTimeoutMillis = 30_0000
this.connectTimeoutMillis = 30_0000
this.socketTimeoutMillis = 30_0000
}
}
}

View File

@ -0,0 +1,10 @@
/*
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
package net.mamoe.mirai.internal

View File

@ -0,0 +1,10 @@
/*
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
package net.mamoe.mirai.internal

View File

@ -0,0 +1,24 @@
/*
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
package net.mamoe.mirai.internal
import io.ktor.client.*
import io.ktor.client.engine.curl.*
import io.ktor.client.features.*
internal actual fun createDefaultHttpClient(): HttpClient {
return HttpClient(Curl) {
install(HttpTimeout) {
this.requestTimeoutMillis = 30_0000
this.connectTimeoutMillis = 30_0000
this.socketTimeoutMillis = 30_0000
}
}
}

View File

@ -0,0 +1,10 @@
/*
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
package net.mamoe.mirai.internal

View File

@ -19,16 +19,24 @@ import net.mamoe.mirai.internal.network.handler.NetworkHandlerFactory
internal actual abstract class AbstractCommonNHTest actual constructor() :
AbstractRealNetworkHandlerTest<TestCommonNetworkHandler>() {
actual override val network: TestCommonNetworkHandler
get() = TODO("Not yet implemented")
actual override val factory: NetworkHandlerFactory<TestCommonNetworkHandler>
get() = TODO("Not yet implemented")
actual override val network: TestCommonNetworkHandler by lazy {
factory.create(createContext(), createAddress())
}
actual override val factory: NetworkHandlerFactory<TestCommonNetworkHandler> =
NetworkHandlerFactory<TestCommonNetworkHandler> { context, address ->
object : TestCommonNetworkHandler(bot, context, address) {
override suspend fun createConnection(): PlatformConn {
return conn
}
}
}
protected actual fun removeOutgoingPacketEncoder() {
}
actual val conn: PlatformConn
get() = TODO("Not yet implemented")
actual val conn: PlatformConn = PlatformConn()
}