Complete sending and receiving encrypted functions
This commit is contained in:
parent
a08966d8ec
commit
21eb87781e
|
@ -14,7 +14,7 @@ public class Overgram {
|
||||||
final MTProtoSender sender = new MTProtoSender(new MTProtoState(), new TcpFull());
|
final MTProtoSender sender = new MTProtoSender(new MTProtoState(), new TcpFull());
|
||||||
try {
|
try {
|
||||||
sender.connect("149.154.167.91", 443);
|
sender.connect("149.154.167.91", 443);
|
||||||
final Future result = sender.send(new Functions.help.GetConfig());
|
final Future result = sender.send(new Functions.Ping());
|
||||||
System.out.println(result.get());
|
System.out.println(result.get());
|
||||||
} finally {
|
} finally {
|
||||||
sender.disconnect();
|
sender.disconnect();
|
||||||
|
|
|
@ -169,6 +169,7 @@ public class MTProtoSender {
|
||||||
doDisconnect();
|
doDisconnect();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
pendingAck.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
final TLMessage message;
|
final TLMessage message;
|
||||||
|
@ -186,7 +187,9 @@ public class MTProtoSender {
|
||||||
while (!message.future.isCancelled()) {
|
while (!message.future.isCancelled()) {
|
||||||
try {
|
try {
|
||||||
connection.send(body);
|
connection.send(body);
|
||||||
|
break;
|
||||||
} catch (IOException ignored) {
|
} catch (IOException ignored) {
|
||||||
|
// TODO e.g. on timeout retry (loop; not done yet)
|
||||||
try {
|
try {
|
||||||
Thread.sleep(1000);
|
Thread.sleep(1000);
|
||||||
doReconnect();
|
doReconnect();
|
||||||
|
@ -228,7 +231,7 @@ public class MTProtoSender {
|
||||||
|
|
||||||
private void processMessage(final TLMessage message) throws InterruptedException {
|
private void processMessage(final TLMessage message) throws InterruptedException {
|
||||||
pendingAck.add(message.id);
|
pendingAck.add(message.id);
|
||||||
if (message.object instanceof RpcResult) {
|
if (message.object instanceof RPCResult) {
|
||||||
handleRpcResult(message);
|
handleRpcResult(message);
|
||||||
} else if (message.object instanceof MessageContainer) {
|
} else if (message.object instanceof MessageContainer) {
|
||||||
handleContainer(message);
|
handleContainer(message);
|
||||||
|
@ -262,11 +265,15 @@ public class MTProtoSender {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleRpcResult(final TLMessage message) {
|
private void handleRpcResult(final TLMessage message) {
|
||||||
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);
|
||||||
|
|
||||||
// TODO RPC error
|
if (result.error != null) {
|
||||||
final BinaryReader reader = new BinaryReader(ByteBuffer.wrap(result.result()));
|
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));
|
replyMessage.future.complete(((TLRequest) replyMessage.object).readResult(reader));
|
||||||
} catch (ClassNotFoundException e) {
|
} catch (ClassNotFoundException e) {
|
||||||
|
@ -276,7 +283,7 @@ public class MTProtoSender {
|
||||||
|
|
||||||
public void handleContainer(final TLMessage message) throws InterruptedException {
|
public void handleContainer(final TLMessage message) throws InterruptedException {
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,7 +101,9 @@ public class MTProtoState {
|
||||||
final Pair<byte[], byte[]> keyIv = calcKey(msgKey, false);
|
final Pair<byte[], byte[]> keyIv = calcKey(msgKey, false);
|
||||||
final byte[] plainText = AES.decryptIge(reader.read(), keyIv.getKey(), keyIv.getValue());
|
final byte[] plainText = AES.decryptIge(reader.read(), keyIv.getKey(), keyIv.getValue());
|
||||||
|
|
||||||
final byte[] ourKey = Utils.sha256digest(ByteBuffer.wrap(authKey.key, 96, 32).array(), body);
|
final byte[] ourKey = Arrays.copyOfRange(Utils.sha256digest(
|
||||||
|
Arrays.copyOfRange(authKey.key, 96, 128), plainText), 8, 24);
|
||||||
|
|
||||||
if (!Arrays.equals(msgKey, ourKey)) {
|
if (!Arrays.equals(msgKey, ourKey)) {
|
||||||
throw new SecurityException("Received message key doesn't match with expected one");
|
throw new SecurityException("Received message key doesn't match with expected one");
|
||||||
}
|
}
|
||||||
|
@ -112,11 +114,11 @@ 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 = reader.readLong();
|
final long remoteMsgId = tlReader.readLong();
|
||||||
final int remoteSeq = reader.readInt();
|
final int remoteSeq = tlReader.readInt();
|
||||||
reader.readInt(); // inner message length
|
tlReader.readInt(); // inner message length
|
||||||
|
|
||||||
final TLObject object = reader.readTl();
|
final TLObject object = tlReader.readTl();
|
||||||
return new TLMessage(remoteMsgId, remoteSeq, object);
|
return new TLMessage(remoteMsgId, remoteSeq, object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,16 +7,20 @@ public class GzipPacked extends TLObject {
|
||||||
public static final int CONSTRUCTOR_ID = 812830625;
|
public static final int CONSTRUCTOR_ID = 812830625;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void serialize(BinaryWriter writer) {
|
public void serialize(final BinaryWriter writer) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deserialize(BinaryReader reader) throws ClassNotFoundException {
|
public void deserialize(final BinaryReader reader) throws ClassNotFoundException {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public TLObject packedObject() {
|
public TLObject packedObject() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static byte[] unzip(final BinaryReader reader) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,22 +3,31 @@ 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.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class MessageContainer extends TLObject {
|
public class MessageContainer extends TLObject {
|
||||||
public static final int CONSTRUCTOR_ID = 1945237724;
|
public static final int CONSTRUCTOR_ID = 1945237724;
|
||||||
|
|
||||||
|
final public List<TLMessage> messages = new ArrayList<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void serialize(BinaryWriter writer) {
|
public void serialize(final BinaryWriter writer) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deserialize(BinaryReader reader) throws ClassNotFoundException {
|
public void deserialize(final BinaryReader reader) throws ClassNotFoundException {
|
||||||
throw new UnsupportedOperationException();
|
messages.clear();
|
||||||
}
|
final int count = reader.readInt();
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
public List<TLMessage> messages() {
|
final long msgId = reader.readLong();
|
||||||
throw new UnsupportedOperationException();
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
package io.github.lonamiwebs.overgram.tl;
|
||||||
|
|
||||||
|
import java.rmi.RemoteException;
|
||||||
|
|
||||||
|
public class RPCError extends RemoteException {
|
||||||
|
public final int code;
|
||||||
|
public final String value;
|
||||||
|
|
||||||
|
public RPCError(final Types.RpcError from) {
|
||||||
|
super(String.format("RPC error %d: %s", from.errorCode(), from.errorMessage()));
|
||||||
|
code = from.errorCode();
|
||||||
|
value = from.errorMessage();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
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;
|
||||||
|
|
||||||
|
public long reqMsgId;
|
||||||
|
public Types.RpcError error;
|
||||||
|
public byte[] result;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void serialize(final BinaryWriter writer) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deserialize(final BinaryReader reader) throws ClassNotFoundException {
|
||||||
|
reqMsgId = reader.readLong();
|
||||||
|
final int code = reader.readInt();
|
||||||
|
if (code == Types.RpcError.CONSTRUCTOR_ID) {
|
||||||
|
error = new Types.RpcError();
|
||||||
|
error.deserialize(reader);
|
||||||
|
} else if (code == GzipPacked.CONSTRUCTOR_ID) {
|
||||||
|
result = GzipPacked.unzip(reader);
|
||||||
|
} else {
|
||||||
|
result = reader.read();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,26 +0,0 @@
|
||||||
package io.github.lonamiwebs.overgram.tl;
|
|
||||||
|
|
||||||
import io.github.lonamiwebs.overgram.utils.BinaryReader;
|
|
||||||
import io.github.lonamiwebs.overgram.utils.BinaryWriter;
|
|
||||||
|
|
||||||
public class RpcResult extends TLObject {
|
|
||||||
public static final int CONSTRUCTOR_ID = -212046591;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void serialize(BinaryWriter writer) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void deserialize(BinaryReader reader) throws ClassNotFoundException {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public long reqMsgId() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] result() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +1,6 @@
|
||||||
package io.github.lonamiwebs.overgram.utils;
|
package io.github.lonamiwebs.overgram.utils;
|
||||||
|
|
||||||
import io.github.lonamiwebs.overgram.tl.TLObject;
|
import io.github.lonamiwebs.overgram.tl.*;
|
||||||
import io.github.lonamiwebs.overgram.tl.Types;
|
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
@ -111,7 +110,22 @@ public class BinaryReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
public TLObject readTl() throws ClassNotFoundException {
|
public TLObject readTl() throws ClassNotFoundException {
|
||||||
final TLObject object = Types.getFromId(readInt());
|
final int id = readInt();
|
||||||
|
final TLObject object;
|
||||||
|
switch (id) {
|
||||||
|
case RPCResult.CONSTRUCTOR_ID:
|
||||||
|
object = new RPCResult();
|
||||||
|
break;
|
||||||
|
case GzipPacked.CONSTRUCTOR_ID:
|
||||||
|
object = new GzipPacked();
|
||||||
|
break;
|
||||||
|
case MessageContainer.CONSTRUCTOR_ID:
|
||||||
|
object = new MessageContainer();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
object = Types.getFromId(id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
object.deserialize(this);
|
object.deserialize(this);
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
@ -126,10 +140,18 @@ public class BinaryReader {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int tell() {
|
||||||
|
return buffer.position();
|
||||||
|
}
|
||||||
|
|
||||||
public void seek(final int delta) {
|
public void seek(final int delta) {
|
||||||
buffer.position(buffer.position() + delta);
|
buffer.position(buffer.position() + delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void set(final int position) {
|
||||||
|
buffer.position(position);
|
||||||
|
}
|
||||||
|
|
||||||
public byte[] read(final int size) {
|
public byte[] read(final int size) {
|
||||||
final byte[] result = new byte[size];
|
final byte[] result = new byte[size];
|
||||||
buffer.get(result);
|
buffer.get(result);
|
||||||
|
|
Loading…
Reference in New Issue