Implement several missing UnsupportedOperationException
This commit is contained in:
parent
757f684c6b
commit
bc0414a436
|
@ -1,6 +1,7 @@
|
|||
package io.github.lonamiwebs.overgram.crypto;
|
||||
|
||||
import io.github.lonamiwebs.overgram.network.MTProtoPlainSender;
|
||||
import io.github.lonamiwebs.overgram.network.MTProtoState;
|
||||
import io.github.lonamiwebs.overgram.tl.Abstract;
|
||||
import io.github.lonamiwebs.overgram.tl.Functions;
|
||||
import io.github.lonamiwebs.overgram.tl.Types;
|
||||
|
@ -14,7 +15,8 @@ import java.nio.ByteBuffer;
|
|||
|
||||
public class Authenticator {
|
||||
|
||||
public static AuthKey doAuthentication(final MTProtoPlainSender sender) throws IOException, ClassNotFoundException {
|
||||
public static void doAuthentication(final MTProtoPlainSender sender, final MTProtoState state)
|
||||
throws IOException, ClassNotFoundException {
|
||||
final BigInteger nonce = new BigInteger(Utils.randomBytes(16));
|
||||
final Types.ResPQ resPq = sender.send(
|
||||
new Functions.ReqPqMulti().nonce(nonce));
|
||||
|
@ -55,6 +57,7 @@ public class Authenticator {
|
|||
throw new SecurityException("Step 2 could not find a known RSA key");
|
||||
}
|
||||
|
||||
// TODO This step fails half the time, why?
|
||||
final Abstract.ServerDHParams abstractDhParams = sender.send(
|
||||
new Functions.ReqDHParams()
|
||||
.nonce(resPq.nonce())
|
||||
|
@ -149,6 +152,7 @@ public class Authenticator {
|
|||
throw new SecurityException("Step 3 DH gen data have invalid nonce hash");
|
||||
}
|
||||
|
||||
return authKey; // TODO And time offset
|
||||
state.authKey = authKey;
|
||||
state.setTimeOffset(timeOffset);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ public class MTProtoSender {
|
|||
success = false;
|
||||
for (int i = 0; i < retries; ++i) {
|
||||
try {
|
||||
state.authKey = Authenticator.doAuthentication(plain);
|
||||
Authenticator.doAuthentication(plain, state);
|
||||
success = true;
|
||||
break;
|
||||
} catch (SecurityException | IOException | ClassNotFoundException ignored) {
|
||||
|
@ -222,6 +222,7 @@ public class MTProtoSender {
|
|||
}
|
||||
try {
|
||||
processMessage(message);
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
} catch (InterruptedException ignored) {
|
||||
doDisconnect();
|
||||
return;
|
||||
|
@ -229,7 +230,7 @@ public class MTProtoSender {
|
|||
}
|
||||
}
|
||||
|
||||
private void processMessage(final TLMessage message) throws InterruptedException {
|
||||
private void processMessage(final TLMessage message) throws InterruptedException, ClassNotFoundException {
|
||||
pendingAck.add(message.id);
|
||||
if (message.object instanceof RPCResult) {
|
||||
handleRpcResult(message);
|
||||
|
@ -264,33 +265,37 @@ public class MTProtoSender {
|
|||
}
|
||||
}
|
||||
|
||||
private void handleRpcResult(final TLMessage message) {
|
||||
private void handleRpcResult(final TLMessage message) throws ClassNotFoundException {
|
||||
final RPCResult result = (RPCResult) message.object;
|
||||
final TLMessage replyMessage = pendingMessages.remove(result.reqMsgId);
|
||||
|
||||
boolean ok = false;
|
||||
try {
|
||||
if (result.error != null) {
|
||||
replyMessage.future.completeExceptionally(new RPCError(result.error));
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
final BinaryReader reader = new BinaryReader(ByteBuffer.wrap(result.result));
|
||||
try {
|
||||
replyMessage.future.complete(((TLRequest) replyMessage.object).readResult(reader));
|
||||
} catch (ClassNotFoundException e) {
|
||||
replyMessage.future.completeExceptionally(e);
|
||||
}
|
||||
ok = true;
|
||||
} finally {
|
||||
if (!ok) {
|
||||
replyMessage.future.completeExceptionally(new Exception());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void handleContainer(final TLMessage message) throws InterruptedException {
|
||||
public void handleContainer(final TLMessage message) throws InterruptedException, ClassNotFoundException {
|
||||
final MessageContainer result = (MessageContainer) message.object;
|
||||
for (final TLMessage innerMessage : result.messages) {
|
||||
processMessage(innerMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public void handleGzipPacked(final TLMessage message) throws InterruptedException {
|
||||
public void handleGzipPacked(final TLMessage message) throws InterruptedException, ClassNotFoundException {
|
||||
final GzipPacked result = (GzipPacked) message.object;
|
||||
message.object = result.packedObject();
|
||||
final BinaryReader reader = new BinaryReader(ByteBuffer.wrap(result.unpackedData));
|
||||
message.object = reader.readTl();
|
||||
processMessage(message);
|
||||
}
|
||||
|
||||
|
@ -323,9 +328,11 @@ public class MTProtoSender {
|
|||
final TLMessage badMessage = pendingMessages.get(result.badMsgId());
|
||||
|
||||
if (result.errorCode() == 16 || result.errorCode() == 17) {
|
||||
state.updateTimeOffset(message.id);
|
||||
if (badMessage != null) {
|
||||
// resend and update time offset
|
||||
throw new UnsupportedOperationException();
|
||||
pendingMessages.remove(badMessage.id);
|
||||
badMessage.id = state.getNewMsgId();
|
||||
pendingMessages.put(badMessage.id, badMessage);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -114,12 +114,9 @@ public class MTProtoState {
|
|||
throw new SecurityException("Server replied with a wrong session ID");
|
||||
}
|
||||
|
||||
final long remoteMsgId = tlReader.readLong();
|
||||
final int remoteSeq = tlReader.readInt();
|
||||
tlReader.readInt(); // inner message length
|
||||
|
||||
final TLObject object = tlReader.readTl();
|
||||
return new TLMessage(remoteMsgId, remoteSeq, object);
|
||||
final TLMessage message = new TLMessage();
|
||||
message.deserialize(tlReader);
|
||||
return message;
|
||||
}
|
||||
|
||||
public long getNewMsgId() {
|
||||
|
@ -140,6 +137,10 @@ public class MTProtoState {
|
|||
lastMsgId = 0;
|
||||
}
|
||||
|
||||
public void setTimeOffset(final long timeOffset) {
|
||||
this.timeOffset = timeOffset;
|
||||
}
|
||||
|
||||
public int getSeqNo(final boolean contentRelated) {
|
||||
if (contentRelated) {
|
||||
return 1 + 2 * sequence++;
|
||||
|
|
|
@ -51,8 +51,16 @@ public class TcpFull extends Connection {
|
|||
final int length = buffer.getInt();
|
||||
final int seq = buffer.getInt();
|
||||
final byte[] body = client.read(length - 12);
|
||||
final int crc = ByteBuffer.wrap(client.read(4)).getInt();
|
||||
// TODO Check crc
|
||||
final int crc = ByteBuffer.wrap(client.read(4)).order(ByteOrder.LITTLE_ENDIAN).getInt();
|
||||
|
||||
final CRC32 validCrc = new CRC32();
|
||||
buffer.rewind();
|
||||
validCrc.update(buffer.array());
|
||||
validCrc.update(body);
|
||||
if ((int) validCrc.getValue() != crc) {
|
||||
throw new SecurityException("Invalid CRC");
|
||||
}
|
||||
|
||||
return body;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,24 +3,53 @@ package io.github.lonamiwebs.overgram.tl;
|
|||
import io.github.lonamiwebs.overgram.utils.BinaryReader;
|
||||
import io.github.lonamiwebs.overgram.utils.BinaryWriter;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
public class GzipPacked extends TLObject {
|
||||
public static final int CONSTRUCTOR_ID = 812830625;
|
||||
|
||||
public byte[] unpackedData;
|
||||
|
||||
@Override
|
||||
public void serialize(final BinaryWriter writer) {
|
||||
throw new UnsupportedOperationException();
|
||||
try {
|
||||
final ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
final GZIPOutputStream gzip = new GZIPOutputStream(out);
|
||||
gzip.write(unpackedData);
|
||||
gzip.finish();
|
||||
writer.write(out.toByteArray());
|
||||
} catch (IOException ignored) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(final BinaryReader reader) throws ClassNotFoundException {
|
||||
throw new UnsupportedOperationException();
|
||||
try {
|
||||
final GZIPInputStream gzip = new GZIPInputStream(new ByteArrayInputStream(reader.read()));
|
||||
final ByteArrayOutputStream out = new ByteArrayOutputStream(4096);
|
||||
final byte[] buffer = new byte[4096];
|
||||
int read;
|
||||
while ((read = gzip.read(buffer)) != -1) {
|
||||
out.write(buffer, 0, read);
|
||||
}
|
||||
unpackedData = out.toByteArray();
|
||||
} catch (IOException ignored) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
public TLObject packedObject() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public static byte[] unzip(final BinaryReader reader) {
|
||||
throw new UnsupportedOperationException();
|
||||
final GzipPacked gzipPacked = new GzipPacked();
|
||||
try {
|
||||
gzipPacked.deserialize(reader);
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
return gzipPacked.unpackedData;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,11 @@ public class MessageContainer extends TLObject {
|
|||
|
||||
@Override
|
||||
public void serialize(final BinaryWriter writer) {
|
||||
throw new UnsupportedOperationException();
|
||||
writer.write(CONSTRUCTOR_ID);
|
||||
writer.write(messages.size());
|
||||
for (final TLMessage message : messages) {
|
||||
writer.write(message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -21,13 +25,9 @@ public class MessageContainer extends TLObject {
|
|||
messages.clear();
|
||||
final int count = reader.readInt();
|
||||
for (int i = 0; i < count; ++i) {
|
||||
final long msgId = reader.readLong();
|
||||
final int seqNo = reader.readInt();
|
||||
final int length = reader.readInt();
|
||||
final int before = reader.tell();
|
||||
final TLObject object = reader.readTl();
|
||||
reader.set(before + length);
|
||||
messages.add(new TLMessage(msgId, seqNo, object));
|
||||
final TLMessage message = new TLMessage();
|
||||
message.deserialize(reader);
|
||||
messages.add(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,6 @@ package io.github.lonamiwebs.overgram.tl;
|
|||
import io.github.lonamiwebs.overgram.utils.BinaryReader;
|
||||
import io.github.lonamiwebs.overgram.utils.BinaryWriter;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class RPCResult extends TLObject {
|
||||
public static final int CONSTRUCTOR_ID = -212046591;
|
||||
|
||||
|
|
|
@ -12,6 +12,9 @@ public class TLMessage extends TLObject {
|
|||
public int seqNo;
|
||||
public TLObject object;
|
||||
|
||||
public TLMessage() {
|
||||
}
|
||||
|
||||
public TLMessage(final long id, final int seqNo, final TLObject object) {
|
||||
this.id = id;
|
||||
this.seqNo = seqNo;
|
||||
|
@ -20,7 +23,7 @@ public class TLMessage extends TLObject {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void serialize(BinaryWriter writer) {
|
||||
public void serialize(final BinaryWriter writer) {
|
||||
final BinaryWriter tmp = new BinaryWriter();
|
||||
tmp.write(object);
|
||||
writer.write(id);
|
||||
|
@ -30,7 +33,12 @@ public class TLMessage extends TLObject {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(BinaryReader reader) throws ClassNotFoundException {
|
||||
throw new UnsupportedOperationException();
|
||||
public void deserialize(final BinaryReader reader) throws ClassNotFoundException {
|
||||
id = reader.readLong();
|
||||
seqNo = reader.readInt();
|
||||
final int length = reader.readInt();
|
||||
final int before = reader.tell();
|
||||
object = reader.readTl();
|
||||
reader.set(before + length);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue