a21494ade6
Applied patch from https://github.com/DrKLO/Telegram/pull/99 . Thanks. Added German localization. Thanks to all from https://github.com/DrKLO/Telegram/pull/129 Experimental audio (will not go to market yet, we will switch to opus codec) Improved text drawing perfomance (now Telegram can draw even «War and Peace» in one message) Ability to send multiple photos and documents from external apps Contacts fixes Memory usage optimizations in network code (receiving data) Partly switched to native ByteBuffers (decoding received data) Added support of Telegram API Layer 12 Bug fixes
314 lines
10 KiB
Java
314 lines
10 KiB
Java
/*
|
|
* This is the source code of Telegram for Android v. 1.3.2.
|
|
* It is licensed under GNU GPL v. 2 or later.
|
|
* You should have received a copy of the license in this archive (see LICENSE).
|
|
*
|
|
* Copyright Nikolai Kudashov, 2013.
|
|
*/
|
|
|
|
package org.telegram.messenger;
|
|
|
|
import android.content.Context;
|
|
import android.content.SharedPreferences;
|
|
|
|
import org.telegram.ui.ApplicationLoader;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.Comparator;
|
|
import java.util.HashMap;
|
|
|
|
public class Datacenter {
|
|
private static final int DATA_VERSION = 4;
|
|
|
|
public int datacenterId;
|
|
public ArrayList<String> addresses = new ArrayList<String>();
|
|
public HashMap<String, Integer> ports = new HashMap<String, Integer>();
|
|
public int[] defaultPorts = new int[] {-1, 80, -1, 443, -1, 443, -1, 80, -1, 443, -1};
|
|
public boolean authorized;
|
|
public long authSessionId;
|
|
public long authDownloadSessionId;
|
|
public long authUploadSessionId;
|
|
public byte[] authKey;
|
|
public long authKeyId;
|
|
public int lastInitVersion = 0;
|
|
private volatile int currentPortNum = 0;
|
|
private volatile int currentAddressNum = 0;
|
|
|
|
public TcpConnection connection;
|
|
public TcpConnection downloadConnection;
|
|
public TcpConnection uploadConnection;
|
|
|
|
private ArrayList<ServerSalt> authServerSaltSet = new ArrayList<ServerSalt>();
|
|
|
|
public Datacenter() {
|
|
authServerSaltSet = new ArrayList<ServerSalt>();
|
|
}
|
|
|
|
public Datacenter(SerializedData data, int version) {
|
|
if (version == 0) {
|
|
datacenterId = data.readInt32();
|
|
String address = data.readString();
|
|
addresses.add(address);
|
|
int port = data.readInt32();
|
|
ports.put(address, port);
|
|
int len = data.readInt32();
|
|
if (len != 0) {
|
|
authKey = data.readData(len);
|
|
}
|
|
len = data.readInt32();
|
|
if (len != 0) {
|
|
authKeyId = data.readInt64();
|
|
}
|
|
authorized = data.readInt32() != 0;
|
|
len = data.readInt32();
|
|
for (int a = 0; a < len; a++) {
|
|
ServerSalt salt = new ServerSalt();
|
|
salt.validSince = data.readInt32();
|
|
salt.validUntil = data.readInt32();
|
|
salt.value = data.readInt64();
|
|
if (authServerSaltSet == null) {
|
|
authServerSaltSet = new ArrayList<ServerSalt>();
|
|
}
|
|
authServerSaltSet.add(salt);
|
|
}
|
|
} else if (version == 1) {
|
|
int currentVersion = data.readInt32();
|
|
if (currentVersion == 2 || currentVersion == 3 || currentVersion == 4) {
|
|
datacenterId = data.readInt32();
|
|
if (currentVersion >= 3) {
|
|
lastInitVersion = data.readInt32();
|
|
}
|
|
int len = data.readInt32();
|
|
for (int a = 0; a < len; a++) {
|
|
String address = data.readString();
|
|
addresses.add(address);
|
|
ports.put(address, data.readInt32());
|
|
}
|
|
|
|
len = data.readInt32();
|
|
if (len != 0) {
|
|
authKey = data.readData(len);
|
|
}
|
|
if (currentVersion == 4) {
|
|
authKeyId = data.readInt64();
|
|
} else {
|
|
len = data.readInt32();
|
|
if (len != 0) {
|
|
authKeyId = data.readInt64();
|
|
}
|
|
}
|
|
authorized = data.readInt32() != 0;
|
|
len = data.readInt32();
|
|
for (int a = 0; a < len; a++) {
|
|
ServerSalt salt = new ServerSalt();
|
|
salt.validSince = data.readInt32();
|
|
salt.validUntil = data.readInt32();
|
|
salt.value = data.readInt64();
|
|
if (authServerSaltSet == null) {
|
|
authServerSaltSet = new ArrayList<ServerSalt>();
|
|
}
|
|
authServerSaltSet.add(salt);
|
|
}
|
|
}
|
|
} else if (version == 2) {
|
|
|
|
}
|
|
readCurrentAddressAndPortNum();
|
|
}
|
|
|
|
public String getCurrentAddress() {
|
|
if (addresses.isEmpty()) {
|
|
return null;
|
|
}
|
|
if (currentAddressNum >= addresses.size()) {
|
|
currentAddressNum = 0;
|
|
}
|
|
return addresses.get(currentAddressNum);
|
|
}
|
|
|
|
public int getCurrentPort() {
|
|
if (ports.isEmpty()) {
|
|
return 443;
|
|
}
|
|
|
|
if (currentPortNum >= defaultPorts.length) {
|
|
currentPortNum = 0;
|
|
}
|
|
int port = defaultPorts[currentPortNum];
|
|
if (port == -1) {
|
|
String address = getCurrentAddress();
|
|
return ports.get(address);
|
|
}
|
|
return port;
|
|
}
|
|
|
|
public void addAddressAndPort(String address, int port) {
|
|
if (addresses.contains(address)) {
|
|
return;
|
|
}
|
|
addresses.add(address);
|
|
ports.put(address, port);
|
|
}
|
|
|
|
public void nextAddressOrPort() {
|
|
if (currentPortNum + 1 < defaultPorts.length) {
|
|
currentPortNum++;
|
|
} else {
|
|
if (currentAddressNum + 1 < addresses.size()) {
|
|
currentAddressNum++;
|
|
} else {
|
|
currentAddressNum = 0;
|
|
}
|
|
currentPortNum = 0;
|
|
}
|
|
}
|
|
|
|
public void storeCurrentAddressAndPortNum() {
|
|
Utilities.stageQueue.postRunnable(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("dataconfig", Context.MODE_PRIVATE);
|
|
SharedPreferences.Editor editor = preferences.edit();
|
|
editor.putInt("dc" + datacenterId + "port", currentPortNum);
|
|
editor.putInt("dc" + datacenterId + "address", currentAddressNum);
|
|
editor.commit();
|
|
}
|
|
});
|
|
}
|
|
|
|
private void readCurrentAddressAndPortNum() {
|
|
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("dataconfig", Context.MODE_PRIVATE);
|
|
currentPortNum = preferences.getInt("dc" + datacenterId + "port", 0);
|
|
currentAddressNum = preferences.getInt("dc" + datacenterId + "address", 0);
|
|
}
|
|
|
|
public void replaceAddressesAndPorts(ArrayList<String> newAddresses, HashMap<String, Integer> newPorts) {
|
|
addresses = newAddresses;
|
|
ports = newPorts;
|
|
}
|
|
|
|
public void SerializeToStream(SerializedData stream) {
|
|
stream.writeInt32(DATA_VERSION);
|
|
stream.writeInt32(datacenterId);
|
|
stream.writeInt32(lastInitVersion);
|
|
stream.writeInt32(addresses.size());
|
|
for (String address : addresses) {
|
|
stream.writeString(address);
|
|
stream.writeInt32(ports.get(address));
|
|
}
|
|
if (authKey != null) {
|
|
stream.writeInt32(authKey.length);
|
|
stream.writeRaw(authKey);
|
|
} else {
|
|
stream.writeInt32(0);
|
|
}
|
|
stream.writeInt64(authKeyId);
|
|
stream.writeInt32(authorized ? 1 : 0);
|
|
stream.writeInt32(authServerSaltSet.size());
|
|
for (ServerSalt salt : authServerSaltSet) {
|
|
stream.writeInt32(salt.validSince);
|
|
stream.writeInt32(salt.validUntil);
|
|
stream.writeInt64(salt.value);
|
|
}
|
|
}
|
|
|
|
public void clear() {
|
|
authKey = null;
|
|
authKeyId = 0;
|
|
authorized = false;
|
|
authServerSaltSet.clear();
|
|
}
|
|
|
|
public void clearServerSalts() {
|
|
authServerSaltSet.clear();
|
|
}
|
|
|
|
public long selectServerSalt(int date) {
|
|
boolean cleanupNeeded = false;
|
|
|
|
long result = 0;
|
|
int maxRemainingInterval = 0;
|
|
|
|
for (ServerSalt salt : authServerSaltSet) {
|
|
if (salt.validUntil < date || (salt.validSince == 0 && salt.validUntil == Integer.MAX_VALUE)) {
|
|
cleanupNeeded = true;
|
|
} else if (salt.validSince <= date && salt.validUntil > date) {
|
|
if (maxRemainingInterval == 0 || Math.abs(salt.validUntil - date) > maxRemainingInterval) {
|
|
maxRemainingInterval = Math.abs(salt.validUntil - date);
|
|
result = salt.value;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (cleanupNeeded) {
|
|
for (int i = 0; i < authServerSaltSet.size(); i++) {
|
|
ServerSalt salt = authServerSaltSet.get(i);
|
|
if (salt.validUntil < date) {
|
|
authServerSaltSet.remove(i);
|
|
i--;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (result == 0) {
|
|
FileLog.e("tmessages", "Valid salt not found");
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private class SaltComparator implements Comparator<ServerSalt> {
|
|
@Override
|
|
public int compare(ServerSalt o1, ServerSalt o2) {
|
|
if (o1.validSince < o2.validSince) {
|
|
return -1;
|
|
} else if (o1.validSince > o2.validSince) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
public void mergeServerSalts(int date, ArrayList<TLRPC.TL_futureSalt> salts) {
|
|
if (salts == null) {
|
|
return;
|
|
}
|
|
ArrayList<Long> existingSalts = new ArrayList<Long>(authServerSaltSet.size());
|
|
|
|
for (ServerSalt salt : authServerSaltSet) {
|
|
existingSalts.add(salt.value);
|
|
}
|
|
for (TLRPC.TL_futureSalt saltDesc : salts) {
|
|
long salt = saltDesc.salt;
|
|
if (!existingSalts.contains(salt) && saltDesc.valid_until > date) {
|
|
ServerSalt serverSalt = new ServerSalt();
|
|
serverSalt.validSince = saltDesc.valid_since;
|
|
serverSalt.validUntil = saltDesc.valid_until;
|
|
serverSalt.value = salt;
|
|
authServerSaltSet.add(serverSalt);
|
|
}
|
|
}
|
|
Collections.sort(authServerSaltSet, new SaltComparator());
|
|
}
|
|
|
|
public void addServerSalt(ServerSalt serverSalt) {
|
|
for (ServerSalt salt : authServerSaltSet) {
|
|
if (salt.value == serverSalt.value) {
|
|
return;
|
|
}
|
|
}
|
|
authServerSaltSet.add(serverSalt);
|
|
Collections.sort(authServerSaltSet, new SaltComparator());
|
|
}
|
|
|
|
boolean containsServerSalt(long value) {
|
|
for (ServerSalt salt : authServerSaltSet) {
|
|
if (salt.value == value) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|