Commit 2e17ea68 authored by jiahua.liu's avatar jiahua.liu

Merge remote-tracking branch 'origin/master'

parents 4d67c2e4 434e6511
...@@ -11,7 +11,6 @@ import net.mamoe.mirai.qqandroid.event.PacketReceivedEvent ...@@ -11,7 +11,6 @@ import net.mamoe.mirai.qqandroid.event.PacketReceivedEvent
import net.mamoe.mirai.qqandroid.network.protocol.packet.KnownPacketFactories import net.mamoe.mirai.qqandroid.network.protocol.packet.KnownPacketFactories
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.LoginPacket import net.mamoe.mirai.qqandroid.network.protocol.packet.login.LoginPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.PacketId
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.RegPushReason import net.mamoe.mirai.qqandroid.network.protocol.packet.login.RegPushReason
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.SvcReqRegisterPacket import net.mamoe.mirai.qqandroid.network.protocol.packet.login.SvcReqRegisterPacket
import net.mamoe.mirai.utils.* import net.mamoe.mirai.utils.*
...@@ -101,12 +100,12 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -101,12 +100,12 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
*/ */
suspend fun parsePacket(input: Input) { suspend fun parsePacket(input: Input) {
try { try {
KnownPacketFactories.parseIncomingPacket(bot, input) { packet: Packet, packetId: PacketId, sequenceId: Int -> KnownPacketFactories.parseIncomingPacket(bot, input) { packet: Packet, commandName: String, sequenceId: Int ->
if (PacketReceivedEvent(packet).broadcast().cancelled) { if (PacketReceivedEvent(packet).broadcast().cancelled) {
return@parseIncomingPacket return@parseIncomingPacket
} }
packetListeners.forEach { listener -> packetListeners.forEach { listener ->
if (listener.filter(packetId, sequenceId) && packetListeners.remove(listener)) { if (listener.filter(commandName, sequenceId) && packetListeners.remove(listener)) {
listener.complete(packet) listener.complete(packet)
} }
} }
...@@ -202,7 +201,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -202,7 +201,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
} }
suspend fun <E : Packet> OutgoingPacket.sendAndExpect(): E { suspend fun <E : Packet> OutgoingPacket.sendAndExpect(): E {
val handler = PacketListener(packetId = packetId, sequenceId = sequenceId) val handler = PacketListener(commandName = commandName, sequenceId = sequenceId)
packetListeners.addLast(handler) packetListeners.addLast(handler)
//println(delegate.readBytes().toUHexString()) //println(delegate.readBytes().toUHexString())
println("Sending length=" + delegate.remaining) println("Sending length=" + delegate.remaining)
...@@ -217,10 +216,10 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -217,10 +216,10 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
@PublishedApi @PublishedApi
internal inner class PacketListener( internal inner class PacketListener(
val packetId: PacketId, val commandName: String,
val sequenceId: Int val sequenceId: Int
) : CompletableDeferred<Packet> by CompletableDeferred(supervisor) { ) : CompletableDeferred<Packet> by CompletableDeferred(supervisor) {
fun filter(packetId: PacketId, sequenceId: Int) = this.packetId == packetId && this.sequenceId == sequenceId fun filter(commandName: String, sequenceId: Int) = this.commandName == commandName && this.sequenceId == sequenceId
} }
override suspend fun awaitDisconnection() = supervisor.join() override suspend fun awaitDisconnection() = supervisor.join()
......
...@@ -6,8 +6,6 @@ import kotlinx.io.core.ByteReadPacket ...@@ -6,8 +6,6 @@ import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.buildPacket import kotlinx.io.core.buildPacket
import kotlinx.io.core.writeFully import kotlinx.io.core.writeFully
import net.mamoe.mirai.qqandroid.network.QQAndroidClient import net.mamoe.mirai.qqandroid.network.QQAndroidClient
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.LoginPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.PacketId
import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.cryptor.DecrypterByteArray import net.mamoe.mirai.utils.cryptor.DecrypterByteArray
import net.mamoe.mirai.utils.cryptor.encryptAndWrite import net.mamoe.mirai.utils.cryptor.encryptAndWrite
...@@ -23,12 +21,12 @@ import net.mamoe.mirai.utils.io.writeQQ ...@@ -23,12 +21,12 @@ import net.mamoe.mirai.utils.io.writeQQ
@UseExperimental(ExperimentalUnsignedTypes::class) @UseExperimental(ExperimentalUnsignedTypes::class)
internal class OutgoingPacket constructor( internal class OutgoingPacket constructor(
name: String?, name: String?,
val packetId: PacketId, val commandName: String,
val sequenceId: Int, val sequenceId: Int,
val delegate: ByteReadPacket val delegate: ByteReadPacket
) { ) {
val name: String by lazy { val name: String by lazy {
name ?: packetId.toString() name ?: commandName.toString()
} }
} }
...@@ -66,13 +64,13 @@ internal val EMPTY_BYTE_ARRAY = ByteArray(0) ...@@ -66,13 +64,13 @@ internal val EMPTY_BYTE_ARRAY = ByteArray(0)
internal inline fun PacketFactory<*>.buildOutgingPacket( internal inline fun PacketFactory<*>.buildOutgingPacket(
client: QQAndroidClient, client: QQAndroidClient,
name: String? = null, name: String? = null,
id: PacketId = this.id, commandName: String = this.commandName,
key: ByteArray, key: ByteArray,
body: BytePacketBuilder.(sequenceId: Int) -> Unit body: BytePacketBuilder.(sequenceId: Int) -> Unit
): OutgoingPacket { ): OutgoingPacket {
val sequenceId: Int = client.nextSsoSequenceId() val sequenceId: Int = client.nextSsoSequenceId()
return OutgoingPacket(name, id, sequenceId, buildPacket { return OutgoingPacket(name, commandName, sequenceId, buildPacket {
writeIntLVPacket(lengthOffset = { it + 4 }) { writeIntLVPacket(lengthOffset = { it + 4 }) {
writeInt(0x0B) writeInt(0x0B)
writeByte(1) writeByte(1)
...@@ -113,13 +111,13 @@ internal inline fun PacketFactory<*>.buildLoginOutgoingPacket( ...@@ -113,13 +111,13 @@ internal inline fun PacketFactory<*>.buildLoginOutgoingPacket(
bodyType: Byte, bodyType: Byte,
extraData: ByteArray = EMPTY_BYTE_ARRAY, extraData: ByteArray = EMPTY_BYTE_ARRAY,
name: String? = null, name: String? = null,
id: PacketId = this.id, commandName: String = this.commandName,
key: ByteArray = KEY_16_ZEROS, key: ByteArray = KEY_16_ZEROS,
body: BytePacketBuilder.(sequenceId: Int) -> Unit body: BytePacketBuilder.(sequenceId: Int) -> Unit
): OutgoingPacket { ): OutgoingPacket {
val sequenceId: Int = client.nextSsoSequenceId() val sequenceId: Int = client.nextSsoSequenceId()
return OutgoingPacket(name, id, sequenceId, buildPacket { return OutgoingPacket(name, commandName, sequenceId, buildPacket {
writeIntLVPacket(lengthOffset = { it + 4 }) { writeIntLVPacket(lengthOffset = { it + 4 }) {
writeInt(0x00_00_00_0A) writeInt(0x00_00_00_0A)
writeByte(bodyType) writeByte(bodyType)
...@@ -168,10 +166,10 @@ private val BRP_STUB = ByteReadPacket(EMPTY_BYTE_ARRAY) ...@@ -168,10 +166,10 @@ private val BRP_STUB = ByteReadPacket(EMPTY_BYTE_ARRAY)
* byte[] body() * byte[] body()
*/ */
@UseExperimental(MiraiInternalAPI::class) @UseExperimental(MiraiInternalAPI::class)
internal inline fun BytePacketBuilder.writeLoginSsoPacket( internal inline fun BytePacketBuilder.writeSsoPacket(
client: QQAndroidClient, client: QQAndroidClient,
subAppId: Long, subAppId: Long,
packetId: PacketId, commandName: String,
extraData: ByteReadPacket = BRP_STUB, extraData: ByteReadPacket = BRP_STUB,
sequenceId: Int, sequenceId: Int,
body: BytePacketBuilder.() -> Unit body: BytePacketBuilder.() -> Unit
...@@ -187,7 +185,7 @@ internal inline fun BytePacketBuilder.writeLoginSsoPacket( ...@@ -187,7 +185,7 @@ internal inline fun BytePacketBuilder.writeLoginSsoPacket(
writeInt((extraData.remaining + 4).toInt()) writeInt((extraData.remaining + 4).toInt())
writePacket(extraData) writePacket(extraData)
} }
packetId.commandName.let { commandName.let {
writeInt(it.length + 4) writeInt(it.length + 4)
writeStringUtf8(it) writeStringUtf8(it)
} }
...@@ -269,7 +267,7 @@ internal inline fun PacketFactory<*>.buildSessionOutgoingPacket( ...@@ -269,7 +267,7 @@ internal inline fun PacketFactory<*>.buildSessionOutgoingPacket(
internal fun BytePacketBuilder.writeOicqRequestPacket( internal fun BytePacketBuilder.writeOicqRequestPacket(
client: QQAndroidClient, client: QQAndroidClient,
encryptMethod: EncryptMethod, encryptMethod: EncryptMethod,
packetId: PacketId, commandId: Int,
bodyBlock: BytePacketBuilder.() -> Unit bodyBlock: BytePacketBuilder.() -> Unit
) { ) {
val body = encryptMethod.makeBody(client, bodyBlock) val body = encryptMethod.makeBody(client, bodyBlock)
...@@ -278,7 +276,7 @@ internal fun BytePacketBuilder.writeOicqRequestPacket( ...@@ -278,7 +276,7 @@ internal fun BytePacketBuilder.writeOicqRequestPacket(
writeByte(0x02) // head writeByte(0x02) // head
writeShort((27 + 2 + body.remaining).toShort()) // orthodox algorithm writeShort((27 + 2 + body.remaining).toShort()) // orthodox algorithm
writeShort(client.protocolVersion) writeShort(client.protocolVersion)
writeShort(packetId.commandId.toShort()) writeShort(commandId.toShort())
writeShort(1) // const?? writeShort(1) // const??
writeQQ(client.uin) writeQQ(client.uin)
writeByte(3) // originally const writeByte(3) // originally const
......
...@@ -6,13 +6,12 @@ import kotlinx.serialization.Serializable ...@@ -6,13 +6,12 @@ import kotlinx.serialization.Serializable
import net.mamoe.mirai.data.Packet import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.qqandroid.QQAndroidBot import net.mamoe.mirai.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.network.protocol.packet.PacketFactory import net.mamoe.mirai.qqandroid.network.protocol.packet.PacketFactory
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.PacketId
import net.mamoe.mirai.utils.currentTimeSeconds import net.mamoe.mirai.utils.currentTimeSeconds
@UseExperimental(ExperimentalUnsignedTypes::class) @UseExperimental(ExperimentalUnsignedTypes::class)
internal object ImagePacket : PacketFactory<ImagePacket.RequestImgUrlResponse>() { internal object ImagePacket : PacketFactory<ImagePacket.RequestImgUrlResponse>() {
init { init {
this._id = PacketId(commandId = 0x0000, commandName = "LongConn.OffPicDown") this._commandName = "LongConn.OffPicDown"
} }
...@@ -21,7 +20,7 @@ internal object ImagePacket : PacketFactory<ImagePacket.RequestImgUrlResponse>() ...@@ -21,7 +20,7 @@ internal object ImagePacket : PacketFactory<ImagePacket.RequestImgUrlResponse>()
} }
fun createCmd0x325Packet(req: ImgReq, networkType: Int = 5): Cmd0x352Packet { private fun createCmd0x325Packet(req: ImgReq, networkType: Int = 5): Cmd0x352Packet {
if (req is UploadImgReq) if (req is UploadImgReq)
return Cmd0x352Packet( return Cmd0x352Packet(
1, 1,
......
...@@ -25,7 +25,7 @@ import net.mamoe.mirai.utils.io.discardExact ...@@ -25,7 +25,7 @@ import net.mamoe.mirai.utils.io.discardExact
@UseExperimental(ExperimentalUnsignedTypes::class) @UseExperimental(ExperimentalUnsignedTypes::class)
internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>() { internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>() {
init { init {
this._id = PacketId(commandId = 0x0810, commandName = "wtlogin.login") this._commandName = "wtlogin.login"
} }
object SubCommand9 { object SubCommand9 {
...@@ -36,8 +36,8 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>() { ...@@ -36,8 +36,8 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>() {
operator fun invoke( operator fun invoke(
client: QQAndroidClient client: QQAndroidClient
): OutgoingPacket = buildLoginOutgoingPacket(client, bodyType = 2) { sequenceId -> ): OutgoingPacket = buildLoginOutgoingPacket(client, bodyType = 2) { sequenceId ->
writeLoginSsoPacket(client, subAppId, id, sequenceId = sequenceId) { writeSsoPacket(client, subAppId, commandName, sequenceId = sequenceId) {
writeOicqRequestPacket(client, EncryptMethodECDH7(client.ecdh), id) { writeOicqRequestPacket(client, EncryptMethodECDH7(client.ecdh), 0x0810) {
writeShort(9) // subCommand writeShort(9) // subCommand
writeShort(17) // count of TLVs, probably ignored by server? writeShort(17) // count of TLVs, probably ignored by server?
//writeShort(LoginType.PASSWORD.value.toShort()) //writeShort(LoginType.PASSWORD.value.toShort())
...@@ -563,21 +563,4 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>() { ...@@ -563,21 +563,4 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>() {
// SEE oicq_request.java at method analysisT17f // SEE oicq_request.java at method analysisT17f
} }
} }
} }
\ No newline at end of file
@Suppress("FunctionName")
internal fun PacketId(commandId: Int, commandName: String) = object : PacketId {
override val commandId: Int get() = commandId
override val commandName: String get() = commandName
}
internal interface PacketId {
val commandId: Int // ushort actually
val commandName: String
}
internal object NullPacketId : PacketId {
override val commandId: Int get() = error("uninitialized")
override val commandName: String get() = error("uninitialized")
}
...@@ -15,7 +15,7 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket ...@@ -15,7 +15,7 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.PacketFactory import net.mamoe.mirai.qqandroid.network.protocol.packet.PacketFactory
import net.mamoe.mirai.qqandroid.network.protocol.packet.buildLoginOutgoingPacket import net.mamoe.mirai.qqandroid.network.protocol.packet.buildLoginOutgoingPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.oidb.oidb0x769.Oidb0x769 import net.mamoe.mirai.qqandroid.network.protocol.packet.oidb.oidb0x769.Oidb0x769
import net.mamoe.mirai.qqandroid.network.protocol.packet.writeLoginSsoPacket import net.mamoe.mirai.qqandroid.network.protocol.packet.writeSsoPacket
import net.mamoe.mirai.qqandroid.utils.NetworkType import net.mamoe.mirai.qqandroid.utils.NetworkType
import net.mamoe.mirai.utils.currentTimeSeconds import net.mamoe.mirai.utils.currentTimeSeconds
import net.mamoe.mirai.utils.io.debugPrint import net.mamoe.mirai.utils.io.debugPrint
...@@ -40,10 +40,10 @@ internal object SvcReqRegisterPacket : PacketFactory<SvcReqRegisterPacket.Respon ...@@ -40,10 +40,10 @@ internal object SvcReqRegisterPacket : PacketFactory<SvcReqRegisterPacket.Respon
internal object Response : Packet internal object Response : Packet
const val subAppId = 537062845L private const val subAppId = 537062845L
init { init {
_id = PacketId(0, "StatSvc.register") _commandName = "StatSvc.register"
} }
operator fun invoke( operator fun invoke(
...@@ -55,8 +55,8 @@ internal object SvcReqRegisterPacket : PacketFactory<SvcReqRegisterPacket.Respon ...@@ -55,8 +55,8 @@ internal object SvcReqRegisterPacket : PacketFactory<SvcReqRegisterPacket.Respon
extraData = client.wLoginSigInfo.d2.data, extraData = client.wLoginSigInfo.d2.data,
key = client.wLoginSigInfo.d2Key key = client.wLoginSigInfo.d2Key
) { sequenceId -> ) { sequenceId ->
writeLoginSsoPacket( writeSsoPacket(
client, subAppId = subAppId, packetId = id, client, subAppId = subAppId, commandName = commandName,
extraData = client.wLoginSigInfo.tgt.toReadPacket(), sequenceId = sequenceId extraData = client.wLoginSigInfo.tgt.toReadPacket(), sequenceId = sequenceId
) { ) {
writeUniRequestPacket { writeUniRequestPacket {
......
...@@ -10,7 +10,7 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.* ...@@ -10,7 +10,7 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.*
internal object TransEmpPacket : PacketFactory<TransEmpPacket.Response>() { internal object TransEmpPacket : PacketFactory<TransEmpPacket.Response>() {
init { init {
_id = PacketId(0x0812, "wtlogin.trans_emp") _commandName = "wtlogin.trans_emp"
} }
private const val appId = 16L private const val appId = 16L
...@@ -20,7 +20,7 @@ internal object TransEmpPacket : PacketFactory<TransEmpPacket.Response>() { ...@@ -20,7 +20,7 @@ internal object TransEmpPacket : PacketFactory<TransEmpPacket.Response>() {
fun SubCommand1( fun SubCommand1(
client: QQAndroidClient client: QQAndroidClient
): OutgoingPacket = buildLoginOutgoingPacket(client, bodyType = 2) { ): OutgoingPacket = buildLoginOutgoingPacket(client, bodyType = 2) {
writeOicqRequestPacket(client, EncryptMethodECDH135(client.ecdh), id) { writeOicqRequestPacket(client, EncryptMethodECDH135(client.ecdh), TODO()) {
// oicq.wlogin_sdk.request.trans_emp_1#packTransEmpBody // oicq.wlogin_sdk.request.trans_emp_1#packTransEmpBody
} }
......
...@@ -41,8 +41,11 @@ fun ktor(id: String, version: String) = "io.ktor:ktor-$id:$version" ...@@ -41,8 +41,11 @@ fun ktor(id: String, version: String) = "io.ktor:ktor-$id:$version"
dependencies { dependencies {
runtimeOnly(files("../mirai-core/build/classes/kotlin/jvm/main")) // IDE bug
runtimeOnly(files("../mirai-core-timpc/build/classes/kotlin/jvm/main")) // IDE bug runtimeOnly(files("../mirai-core-timpc/build/classes/kotlin/jvm/main")) // IDE bug
implementation(project(":mirai-core-timpc")) implementation(project(":mirai-core-timpc"))
runtimeOnly(files("../mirai-core-qqandroid/build/classes/kotlin/jvm/main")) // IDE bug
implementation(project(":mirai-core-qqandroid"))
// runtimeOnly(files("../mirai-core/build/classes/kotlin/jvm/main")) // classpath is not added correctly by IDE // runtimeOnly(files("../mirai-core/build/classes/kotlin/jvm/main")) // classpath is not added correctly by IDE
implementation("org.bouncycastle:bcprov-jdk15on:1.64") implementation("org.bouncycastle:bcprov-jdk15on:1.64")
...@@ -70,4 +73,9 @@ dependencies { ...@@ -70,4 +73,9 @@ dependencies {
implementation(ktor("client-core", ktorVersion)) implementation(ktor("client-core", ktorVersion))
implementation(ktor("network", ktorVersion)) implementation(ktor("network", ktorVersion))
testImplementation(kotlin("test-annotations-common"))
testImplementation(kotlin("test"))
testImplementation(kotlin("test-junit"))
testImplementation(kotlin("script-runtime"))
} }
\ No newline at end of file
package jce.jce;
import java.io.UnsupportedEncodingException;
public class HexUtil {
private static final char[] digits = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
public static final byte[] emptybytes = new byte[0];
public static String byte2HexStr(byte var0) {
char var1 = digits[var0 & 15];
var0 = (byte) (var0 >>> 4);
return new String(new char[]{digits[var0 & 15], var1});
}
public static String bytes2HexStr(byte[] var0) {
if (var0 != null && var0.length != 0) {
char[] var3 = new char[var0.length * 2];
for (int var1 = 0; var1 < var0.length; ++var1) {
byte var2 = var0[var1];
var3[var1 * 2 + 1] = digits[var2 & 15];
var2 = (byte) (var2 >>> 4);
var3[var1 * 2 + 0] = digits[var2 & 15];
}
return new String(var3);
} else {
return null;
}
}
public static byte char2Byte(char var0) {
if (var0 >= '0' && var0 <= '9') {
return (byte) (var0 - 48);
} else if (var0 >= 'a' && var0 <= 'f') {
return (byte) (var0 - 97 + 10);
} else {
return var0 >= 'A' && var0 <= 'F' ? (byte) (var0 - 65 + 10) : 0;
}
}
public static byte hexStr2Byte(String var0) {
byte var2 = 0;
byte var1 = var2;
if (var0 != null) {
var1 = var2;
if (var0.length() == 1) {
var1 = char2Byte(var0.charAt(0));
}
}
return var1;
}
public static byte[] hexStr2Bytes(String var0) {
if (var0 != null && !var0.equals("")) {
byte[] var4 = new byte[var0.length() / 2];
for (int var3 = 0; var3 < var4.length; ++var3) {
char var1 = var0.charAt(var3 * 2);
char var2 = var0.charAt(var3 * 2 + 1);
var4[var3] = (byte) (char2Byte(var1) * 16 + char2Byte(var2));
}
return var4;
} else {
return emptybytes;
}
}
public static void main(String[] var0) {
try {
byte[] var2 = "Hello WebSocket World?".getBytes("gbk");
System.out.println(bytes2HexStr(var2));
} catch (UnsupportedEncodingException var1) {
var1.printStackTrace();
}
}
}
package jce.jce;
public class JceDecodeException extends RuntimeException {
public JceDecodeException(String var1) {
super(var1);
}
}
package jce.jce;
public class JceEncodeException extends RuntimeException {
public JceEncodeException(String var1) {
super(var1);
}
}
package jce.jce;
public class JceInputStream$HeadData {
public int tag;
public byte type;
public void clear() {
this.type = 0;
this.tag = 0;
}
}
This diff is collapsed.
This diff is collapsed.
package jce.jce;
import java.io.Serializable;
public abstract class JceStruct implements Serializable {
public static final byte BYTE = 0;
public static final byte DOUBLE = 5;
public static final byte FLOAT = 4;
public static final byte INT = 2;
public static final int JCE_MAX_STRING_LENGTH = 104857600;
public static final byte LIST = 9;
public static final byte LONG = 3;
public static final byte MAP = 8;
public static final byte SHORT = 1;
public static final byte SIMPLE_LIST = 13;
public static final byte STRING1 = 6;
public static final byte STRING4 = 7;
public static final byte STRUCT_BEGIN = 10;
public static final byte STRUCT_END = 11;
public static final byte ZERO_TAG = 12;
public static String toDisplaySimpleString(JceStruct var0) {
if (var0 == null) {
return null;
} else {
StringBuilder var1 = new StringBuilder();
var0.displaySimple(var1, 0);
return var1.toString();
}
}
public boolean containField(String var1) {
return false;
}
public void display(StringBuilder var1, int var2) {
}
public void displaySimple(StringBuilder var1, int var2) {
}
public Object getFieldByName(String var1) {
return null;
}
public JceStruct newInit() {
return null;
}
public abstract void readFrom(JceInputStream var1);
public void recyle() {
}
public void setFieldByName(String var1, Object var2) {
}
public byte[] toByteArray() {
JceOutputStream var1 = new JceOutputStream();
this.writeTo(var1);
return var1.toByteArray();
}
public byte[] toByteArray(String var1) {
JceOutputStream var2 = new JceOutputStream();
var2.setServerEncoding(var1);
this.writeTo(var2);
return var2.toByteArray();
}
public String toString() {
StringBuilder var1 = new StringBuilder();
this.display(var1, 0);
return var1.toString();
}
public abstract void writeTo(JceOutputStream var1);
}
This diff is collapsed.
package jce.jce;
import java.nio.ByteBuffer;
public interface OnIllegalArgumentException {
void onException(IllegalArgumentException var1, ByteBuffer var2, int var3, int var4);
}
package jceTest
import io.ktor.util.InternalAPI
import jce.jce.JceInputStream
import jce.jce.JceOutputStream
import jce.jce.JceStruct
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.readBytes
import net.mamoe.mirai.qqandroid.network.io.JceInput
import net.mamoe.mirai.qqandroid.network.io.JceOutput
import net.mamoe.mirai.qqandroid.network.io.buildJcePacket
import net.mamoe.mirai.utils.io.toUHexString
import org.junit.Test
private infix fun ByteReadPacket.shouldEqualTo(another: ByteArray) {
this.readBytes().let {
check(it.contentEquals(another)) {
"""actual: ${it.toUHexString()}
|required: ${another.toUHexString()}
""".trimMargin()
}
}
}
@UseExperimental(InternalAPI::class)
private fun qqJce(block: JceOutputStream.() -> Unit): ByteArray {
return JceOutputStream().apply(block).toByteArray()
}
internal class JceOutputTest {
@Test
fun writeByte() {
buildJcePacket {
writeByte(1, 1)
writeByte(-128, 2)
} shouldEqualTo qqJce {
write(1.toByte(), 1)
write((-128).toByte(), 2)
}
}
@Test
fun writeDouble() {
buildJcePacket {
writeDouble(1.0, 1)
writeDouble(-128.0, 2)
} shouldEqualTo qqJce {
write(1.toDouble(), 1)
write((-128).toDouble(), 2)
}
}
@Test
fun writeFloat() {
buildJcePacket {
writeFloat(1.0f, 1)
writeFloat(-128.0f, 2)
} shouldEqualTo qqJce {
write(1.toFloat(), 1)
write((-128).toFloat(), 2)
}
}
@Test
fun writeFully() {
buildJcePacket {
writeFully(byteArrayOf(1, 2), 1)
writeFully(byteArrayOf(1, 2), 2)
} shouldEqualTo qqJce {
write(byteArrayOf(1, 2), 1)
write(byteArrayOf(1, 2), 2)
}
}
@Test
fun testWriteFully() {
buildJcePacket {
writeFully(intArrayOf(1, 2), 1)
writeFully(intArrayOf(1, 2), 2)
} shouldEqualTo qqJce {
write(intArrayOf(1, 2), 1)
write(intArrayOf(1, 2), 2)
}
}
@Test
fun testWriteFully1() {
buildJcePacket {
writeFully(shortArrayOf(1, 2), 1)
writeFully(shortArrayOf(1, 2), 2)
} shouldEqualTo qqJce {
write(shortArrayOf(1, 2), 1)
write(shortArrayOf(1, 2), 2)
}
}
@Test
fun testWriteFully2() {
buildJcePacket {
writeFully(booleanArrayOf(true, false), 1)
writeFully(booleanArrayOf(true, false), 2)
} shouldEqualTo qqJce {
write(booleanArrayOf(true, false), 1)
write(booleanArrayOf(true, false), 2)
}
}
@Test
fun testWriteFully3() {
buildJcePacket {
writeFully(longArrayOf(1, 2), 1)
writeFully(longArrayOf(1, 2), 2)
} shouldEqualTo qqJce {
write(longArrayOf(1, 2), 1)
write(longArrayOf(1, 2), 2)
}
}
@Test
fun testWriteFully4() {
buildJcePacket {
writeFully(floatArrayOf(1f, 2f), 1)
writeFully(floatArrayOf(1f, 2f), 2)
} shouldEqualTo qqJce {
write(floatArrayOf(1f, 2f), 1)
write(floatArrayOf(1f, 2f), 2)
}
}
@Test
fun testWriteFully5() {
buildJcePacket {
writeFully(doubleArrayOf(1.0, 2.0), 1)
writeFully(doubleArrayOf(1.0, 2.0), 2)
} shouldEqualTo qqJce {
write(doubleArrayOf(1.0, 2.0), 1)
write(doubleArrayOf(1.0, 2.0), 2)
}
}
@Test
fun testWriteFully6() {
buildJcePacket {
writeFully(arrayOf("123", "哈哈"), 1)
writeFully(arrayOf("123", "哈哈"), 2)
} shouldEqualTo qqJce {
write(arrayOf("123", "哈哈"), 1)
write(arrayOf("123", "哈哈"), 2)
}
}
@Test
fun writeInt() {
buildJcePacket {
writeInt(1, 1)
writeInt(-128, 2)
} shouldEqualTo qqJce {
write(1, 1)
write(-128, 2)
}
}
@Test
fun writeLong() {
buildJcePacket {
writeLong(1, 1)
writeLong(-128, 2)
} shouldEqualTo qqJce {
write(1L, 1)
write(-128L, 2)
}
}
@Test
fun writeShort() {
buildJcePacket {
writeShort(1, 1)
writeShort(-128, 2)
} shouldEqualTo qqJce {
write(1.toShort(), 1)
write((-128).toShort(), 2)
}
}
@Test
fun writeBoolean() {
buildJcePacket {
writeBoolean(true, 1)
writeBoolean(false, 2)
} shouldEqualTo qqJce {
write(true, 1)
write(false, 2)
}
}
@Test
fun writeString() {
buildJcePacket {
writeString("1", 1)
writeString("哈啊", 2)
} shouldEqualTo qqJce {
write("1", 1)
write("哈啊", 2)
}
}
@Test
fun writeMap() {
buildJcePacket {
writeMap(mapOf("" to ""), 1)
writeMap(mapOf("" to 123), 2)
writeMap(mapOf(123.0 to "Hello"), 3)
} shouldEqualTo qqJce {
write(mapOf("" to ""), 1)
write(mapOf("" to 123), 2)
write(mapOf(123.0 to "Hello"), 3)
}
}
@Test
fun writeCollection() {
buildJcePacket {
writeMap(mapOf("" to ""), 1)
writeMap(mapOf("" to 123), 2)
writeMap(mapOf(123.0 to "Hello"), 3)
} shouldEqualTo qqJce {
write(mapOf("" to ""), 1)
write(mapOf("" to 123), 2)
write(mapOf(123.0 to "Hello"), 3)
}
}
data class TestMiraiStruct(
val message: String
) : net.mamoe.mirai.qqandroid.network.io.JceStruct() {
override fun writeTo(builder: JceOutput) {
builder.writeString(message, 0)
}
companion object : Factory<TestMiraiStruct> {
override fun newInstanceFrom(input: JceInput): TestMiraiStruct {
return TestMiraiStruct(input.readString(0))
}
}
}
class TestQQStruct(
private var message: String
) : JceStruct() {
override fun readFrom(var1: JceInputStream) {
message = var1.read("", 0, true)
}
override fun writeTo(var1: JceOutputStream) {
var1.write(message, 0)
}
}
@Test
fun writeJceStruct() {
buildJcePacket {
writeJceStruct(TestMiraiStruct("Hello"), 0)
writeJceStruct(TestMiraiStruct("嗨"), 1)
} shouldEqualTo qqJce {
write(TestQQStruct("Hello"), 0)
write(TestQQStruct("嗨"), 1)
}
}
@Test
fun writeObject() {
buildJcePacket {
writeObject(0.toByte(), 1)
writeObject(0.toShort(), 2)
writeObject(0, 3)
writeObject(0L, 4)
writeObject(0f, 5)
writeObject(0.0, 6)
writeObject("hello", 7)
writeObject(TestMiraiStruct("Hello"), 8)
} shouldEqualTo qqJce {
write(0.toByte(), 1)
write(0.toShort(), 2)
write(0, 3)
write(0L, 4)
write(0f, 5)
write(0.0, 6)
write("hello", 7)
write(TestQQStruct("Hello"), 8)
}
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment