Implement several missing UnsupportedOperationException

master
Lonami Exo 2018-07-25 21:03:59 +02:00
parent 757f684c6b
commit bc0414a436
8 changed files with 102 additions and 47 deletions

View File

@ -1,6 +1,7 @@
package io.github.lonamiwebs.overgram.crypto; package io.github.lonamiwebs.overgram.crypto;
import io.github.lonamiwebs.overgram.network.MTProtoPlainSender; 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.Abstract;
import io.github.lonamiwebs.overgram.tl.Functions; import io.github.lonamiwebs.overgram.tl.Functions;
import io.github.lonamiwebs.overgram.tl.Types; import io.github.lonamiwebs.overgram.tl.Types;
@ -14,7 +15,8 @@ import java.nio.ByteBuffer;
public class Authenticator { 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 BigInteger nonce = new BigInteger(Utils.randomBytes(16));
final Types.ResPQ resPq = sender.send( final Types.ResPQ resPq = sender.send(
new Functions.ReqPqMulti().nonce(nonce)); new Functions.ReqPqMulti().nonce(nonce));
@ -55,6 +57,7 @@ public class Authenticator {
throw new SecurityException("Step 2 could not find a known RSA key"); 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( final Abstract.ServerDHParams abstractDhParams = sender.send(
new Functions.ReqDHParams() new Functions.ReqDHParams()
.nonce(resPq.nonce()) .nonce(resPq.nonce())
@ -149,6 +152,7 @@ public class Authenticator {
throw new SecurityException("Step 3 DH gen data have invalid nonce hash"); throw new SecurityException("Step 3 DH gen data have invalid nonce hash");
} }
return authKey; // TODO And time offset state.authKey = authKey;
state.setTimeOffset(timeOffset);
} }
} }

View File

@ -67,7 +67,7 @@ public class MTProtoSender {
success = false; success = false;
for (int i = 0; i < retries; ++i) { for (int i = 0; i < retries; ++i) {
try { try {
state.authKey = Authenticator.doAuthentication(plain); Authenticator.doAuthentication(plain, state);
success = true; success = true;
break; break;
} catch (SecurityException | IOException | ClassNotFoundException ignored) { } catch (SecurityException | IOException | ClassNotFoundException ignored) {
@ -222,6 +222,7 @@ public class MTProtoSender {
} }
try { try {
processMessage(message); processMessage(message);
} catch (ClassNotFoundException ignored) {
} catch (InterruptedException ignored) { } catch (InterruptedException ignored) {
doDisconnect(); doDisconnect();
return; 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); pendingAck.add(message.id);
if (message.object instanceof RPCResult) { if (message.object instanceof RPCResult) {
handleRpcResult(message); 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 RPCResult result = (RPCResult) message.object;
final TLMessage replyMessage = pendingMessages.remove(result.reqMsgId); final TLMessage replyMessage = pendingMessages.remove(result.reqMsgId);
if (result.error != null) { boolean ok = false;
replyMessage.future.completeExceptionally(new RPCError(result.error));
return;
}
final BinaryReader reader = new BinaryReader(ByteBuffer.wrap(result.result));
try { try {
replyMessage.future.complete(((TLRequest) replyMessage.object).readResult(reader)); if (result.error != null) {
} catch (ClassNotFoundException e) { replyMessage.future.completeExceptionally(new RPCError(result.error));
replyMessage.future.completeExceptionally(e); } else {
final BinaryReader reader = new BinaryReader(ByteBuffer.wrap(result.result));
replyMessage.future.complete(((TLRequest) replyMessage.object).readResult(reader));
}
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; final MessageContainer result = (MessageContainer) message.object;
for (final TLMessage innerMessage : result.messages) { for (final TLMessage innerMessage : result.messages) {
processMessage(innerMessage); 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; 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); processMessage(message);
} }
@ -323,9 +328,11 @@ public class MTProtoSender {
final TLMessage badMessage = pendingMessages.get(result.badMsgId()); final TLMessage badMessage = pendingMessages.get(result.badMsgId());
if (result.errorCode() == 16 || result.errorCode() == 17) { if (result.errorCode() == 16 || result.errorCode() == 17) {
state.updateTimeOffset(message.id);
if (badMessage != null) { if (badMessage != null) {
// resend and update time offset pendingMessages.remove(badMessage.id);
throw new UnsupportedOperationException(); badMessage.id = state.getNewMsgId();
pendingMessages.put(badMessage.id, badMessage);
} }
return; return;
} }

View File

@ -114,12 +114,9 @@ public class MTProtoState {
throw new SecurityException("Server replied with a wrong session ID"); throw new SecurityException("Server replied with a wrong session ID");
} }
final long remoteMsgId = tlReader.readLong(); final TLMessage message = new TLMessage();
final int remoteSeq = tlReader.readInt(); message.deserialize(tlReader);
tlReader.readInt(); // inner message length return message;
final TLObject object = tlReader.readTl();
return new TLMessage(remoteMsgId, remoteSeq, object);
} }
public long getNewMsgId() { public long getNewMsgId() {
@ -140,6 +137,10 @@ public class MTProtoState {
lastMsgId = 0; lastMsgId = 0;
} }
public void setTimeOffset(final long timeOffset) {
this.timeOffset = timeOffset;
}
public int getSeqNo(final boolean contentRelated) { public int getSeqNo(final boolean contentRelated) {
if (contentRelated) { if (contentRelated) {
return 1 + 2 * sequence++; return 1 + 2 * sequence++;

View File

@ -51,8 +51,16 @@ public class TcpFull extends Connection {
final int length = buffer.getInt(); final int length = buffer.getInt();
final int seq = buffer.getInt(); final int seq = buffer.getInt();
final byte[] body = client.read(length - 12); final byte[] body = client.read(length - 12);
final int crc = ByteBuffer.wrap(client.read(4)).getInt(); final int crc = ByteBuffer.wrap(client.read(4)).order(ByteOrder.LITTLE_ENDIAN).getInt();
// TODO Check crc
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; return body;
} }
} }

View File

@ -3,24 +3,53 @@ package io.github.lonamiwebs.overgram.tl;
import io.github.lonamiwebs.overgram.utils.BinaryReader; import io.github.lonamiwebs.overgram.utils.BinaryReader;
import io.github.lonamiwebs.overgram.utils.BinaryWriter; 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 class GzipPacked extends TLObject {
public static final int CONSTRUCTOR_ID = 812830625; public static final int CONSTRUCTOR_ID = 812830625;
public byte[] unpackedData;
@Override @Override
public void serialize(final BinaryWriter writer) { 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 @Override
public void deserialize(final BinaryReader reader) throws ClassNotFoundException { 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);
public TLObject packedObject() { final byte[] buffer = new byte[4096];
throw new UnsupportedOperationException(); int read;
while ((read = gzip.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
unpackedData = out.toByteArray();
} catch (IOException ignored) {
throw new RuntimeException();
}
} }
public static byte[] unzip(final BinaryReader reader) { 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;
} }
} }

View File

@ -13,7 +13,11 @@ public class MessageContainer extends TLObject {
@Override @Override
public void serialize(final BinaryWriter writer) { 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 @Override
@ -21,13 +25,9 @@ public class MessageContainer extends TLObject {
messages.clear(); messages.clear();
final int count = reader.readInt(); final int count = reader.readInt();
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
final long msgId = reader.readLong(); final TLMessage message = new TLMessage();
final int seqNo = reader.readInt(); message.deserialize(reader);
final int length = reader.readInt(); messages.add(message);
final int before = reader.tell();
final TLObject object = reader.readTl();
reader.set(before + length);
messages.add(new TLMessage(msgId, seqNo, object));
} }
} }
} }

View File

@ -3,8 +3,6 @@ package io.github.lonamiwebs.overgram.tl;
import io.github.lonamiwebs.overgram.utils.BinaryReader; import io.github.lonamiwebs.overgram.utils.BinaryReader;
import io.github.lonamiwebs.overgram.utils.BinaryWriter; import io.github.lonamiwebs.overgram.utils.BinaryWriter;
import java.util.Arrays;
public class RPCResult extends TLObject { public class RPCResult extends TLObject {
public static final int CONSTRUCTOR_ID = -212046591; public static final int CONSTRUCTOR_ID = -212046591;

View File

@ -12,6 +12,9 @@ public class TLMessage extends TLObject {
public int seqNo; public int seqNo;
public TLObject object; public TLObject object;
public TLMessage() {
}
public TLMessage(final long id, final int seqNo, final TLObject object) { public TLMessage(final long id, final int seqNo, final TLObject object) {
this.id = id; this.id = id;
this.seqNo = seqNo; this.seqNo = seqNo;
@ -20,7 +23,7 @@ public class TLMessage extends TLObject {
} }
@Override @Override
public void serialize(BinaryWriter writer) { public void serialize(final BinaryWriter writer) {
final BinaryWriter tmp = new BinaryWriter(); final BinaryWriter tmp = new BinaryWriter();
tmp.write(object); tmp.write(object);
writer.write(id); writer.write(id);
@ -30,7 +33,12 @@ public class TLMessage extends TLObject {
} }
@Override @Override
public void deserialize(BinaryReader reader) throws ClassNotFoundException { public void deserialize(final BinaryReader reader) throws ClassNotFoundException {
throw new UnsupportedOperationException(); id = reader.readLong();
seqNo = reader.readInt();
final int length = reader.readInt();
final int before = reader.tell();
object = reader.readTl();
reader.set(before + length);
} }
} }