NekoX/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java

653 lines
30 KiB
Java
Raw Normal View History

2013-10-25 17:19:00 +02:00
/*
2019-01-23 18:03:33 +01:00
* This is the source code of Telegram for Android v. 5.x.x.
2013-10-25 17:19:00 +02:00
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
2019-01-23 18:03:33 +01:00
* Copyright Nikolai Kudashov, 2013-2018.
2013-10-25 17:19:00 +02:00
*/
package org.telegram.messenger;
2020-09-30 15:48:47 +02:00
import android.annotation.SuppressLint;
2014-08-23 01:22:33 +02:00
import android.app.Activity;
import android.content.SharedPreferences;
2018-07-30 04:07:02 +02:00
import android.net.Uri;
import android.util.SparseArray;
import android.util.SparseIntArray;
2014-08-23 01:22:33 +02:00
2015-09-24 22:52:02 +02:00
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.NativeByteBuffer;
import org.telegram.tgnet.TLObject;
import org.telegram.tgnet.TLRPC;
2013-10-25 17:19:00 +02:00
import java.io.File;
2020-09-30 15:48:47 +02:00
import java.io.FileDescriptor;
2018-07-30 04:07:02 +02:00
import java.io.RandomAccessFile;
2020-09-30 15:48:47 +02:00
import java.lang.reflect.Method;
2017-03-31 01:58:05 +02:00
import java.util.ArrayList;
2013-10-25 17:19:00 +02:00
public class FileUploadOperation {
2017-03-31 01:58:05 +02:00
private static class UploadCachedResult {
2017-03-31 01:58:05 +02:00
private long bytesOffset;
private byte[] iv;
}
2018-07-30 04:07:02 +02:00
private int currentAccount;
private boolean isLastPart;
private boolean nextPartFirst;
private int operationGuid;
private static final int minUploadChunkSize = 128;
private static final int minUploadChunkSlowNetworkSize = 32;
2017-07-08 18:32:04 +02:00
private static final int initialRequestsCount = 8;
2018-07-30 04:07:02 +02:00
private static final int initialRequestsSlowNetworkCount = 1;
2017-07-08 18:32:04 +02:00
private static final int maxUploadingKBytes = 1024 * 2;
2018-07-30 04:07:02 +02:00
private static final int maxUploadingSlowNetworkKBytes = 32;
2022-06-21 04:51:00 +02:00
2017-07-08 18:32:04 +02:00
private int maxRequestsCount;
private int uploadChunkSize = 64 * 1024;
2018-07-30 04:07:02 +02:00
private boolean slowNetwork;
2017-03-31 01:58:05 +02:00
private ArrayList<byte[]> freeRequestIvs;
private int requestNum;
2013-10-25 17:19:00 +02:00
private String uploadingFilePath;
2017-03-31 01:58:05 +02:00
private int state;
2013-10-27 00:34:39 +02:00
private byte[] readBuffer;
2017-03-31 01:58:05 +02:00
private FileUploadOperationDelegate delegate;
2018-07-30 04:07:02 +02:00
private SparseIntArray requestTokens = new SparseIntArray();
2017-03-31 01:58:05 +02:00
private int currentPartNum;
2013-10-25 17:19:00 +02:00
private long currentFileId;
2017-03-31 01:58:05 +02:00
private long totalFileSize;
private int totalPartsCount;
private long readBytesCount;
private long uploadedBytesCount;
private int saveInfoTimes;
2013-10-25 17:19:00 +02:00
private byte[] key;
private byte[] iv;
private byte[] ivChange;
2017-03-31 01:58:05 +02:00
private boolean isEncrypted;
private int fingerprint;
private boolean isBigFile;
2021-01-28 15:15:51 +01:00
private boolean forceSmallFile;
2014-08-23 01:22:33 +02:00
private String fileKey;
2022-06-21 04:51:00 +02:00
private long estimatedSize;
2017-03-31 01:58:05 +02:00
private int uploadStartTime;
2018-07-30 04:07:02 +02:00
private RandomAccessFile stream;
2017-03-31 01:58:05 +02:00
private boolean started;
private int currentUploadRequetsCount;
private SharedPreferences preferences;
private int currentType;
private int lastSavedPartNum;
2018-07-30 04:07:02 +02:00
private long availableSize;
private boolean uploadFirstPartLater;
private SparseArray<UploadCachedResult> cachedResults = new SparseArray<>();
2021-01-28 15:15:51 +01:00
protected long lastProgressUpdateTime;
2013-10-25 17:19:00 +02:00
public interface FileUploadOperationDelegate {
2015-05-21 23:27:27 +02:00
void didFinishUploadingFile(FileUploadOperation operation, TLRPC.InputFile inputFile, TLRPC.InputEncryptedFile inputEncryptedFile, byte[] key, byte[] iv);
void didFailedUploadingFile(FileUploadOperation operation);
2020-01-23 07:15:40 +01:00
void didChangedUploadProgress(FileUploadOperation operation, long uploadedSize, long totalSize);
2013-10-25 17:19:00 +02:00
}
2022-06-21 04:51:00 +02:00
public FileUploadOperation(int instance, String location, boolean encrypted, long estimated, int type) {
2018-07-30 04:07:02 +02:00
currentAccount = instance;
2013-10-25 17:19:00 +02:00
uploadingFilePath = location;
isEncrypted = encrypted;
estimatedSize = estimated;
2017-03-31 01:58:05 +02:00
currentType = type;
2018-07-30 04:07:02 +02:00
uploadFirstPartLater = estimated != 0 && !isEncrypted;
2013-10-25 17:19:00 +02:00
}
2015-10-29 18:10:07 +01:00
public long getTotalFileSize() {
return totalFileSize;
}
2017-03-31 01:58:05 +02:00
public void setDelegate(FileUploadOperationDelegate fileUploadOperationDelegate) {
delegate = fileUploadOperationDelegate;
}
2013-10-25 17:19:00 +02:00
public void start() {
if (state != 0) {
return;
}
state = 1;
2019-01-23 18:03:33 +01:00
Utilities.stageQueue.postRunnable(() -> {
preferences = ApplicationLoader.applicationContext.getSharedPreferences("uploadinfo", Activity.MODE_PRIVATE);
slowNetwork = ApplicationLoader.isConnectionSlow();
if (BuildVars.LOGS_ENABLED) {
FileLog.d("start upload on slow network = " + slowNetwork);
}
for (int a = 0, count = (slowNetwork ? initialRequestsSlowNetworkCount : initialRequestsCount); a < count; a++) {
startUploadRequest();
}
});
2013-10-25 17:19:00 +02:00
}
2018-07-30 04:07:02 +02:00
protected void onNetworkChanged(final boolean slow) {
if (state != 1) {
return;
}
2019-01-23 18:03:33 +01:00
Utilities.stageQueue.postRunnable(() -> {
if (slowNetwork != slow) {
slowNetwork = slow;
if (BuildVars.LOGS_ENABLED) {
FileLog.d("network changed to slow = " + slowNetwork);
}
for (int a = 0; a < requestTokens.size(); a++) {
ConnectionsManager.getInstance(currentAccount).cancelRequest(requestTokens.valueAt(a), true);
}
requestTokens.clear();
cleanup();
isLastPart = false;
nextPartFirst = false;
requestNum = 0;
currentPartNum = 0;
readBytesCount = 0;
uploadedBytesCount = 0;
saveInfoTimes = 0;
key = null;
iv = null;
ivChange = null;
currentUploadRequetsCount = 0;
lastSavedPartNum = 0;
uploadFirstPartLater = false;
cachedResults.clear();
operationGuid++;
for (int a = 0, count = (slowNetwork ? initialRequestsSlowNetworkCount : initialRequestsCount); a < count; a++) {
startUploadRequest();
2018-07-30 04:07:02 +02:00
}
}
});
}
2013-10-25 17:19:00 +02:00
public void cancel() {
2015-10-29 18:10:07 +01:00
if (state == 3) {
2013-10-25 17:19:00 +02:00
return;
}
state = 2;
2019-01-23 18:03:33 +01:00
Utilities.stageQueue.postRunnable(() -> {
for (int a = 0; a < requestTokens.size(); a++) {
ConnectionsManager.getInstance(currentAccount).cancelRequest(requestTokens.valueAt(a), true);
2017-07-08 18:32:04 +02:00
}
});
2013-10-25 17:19:00 +02:00
delegate.didFailedUploadingFile(this);
2014-08-23 01:22:33 +02:00
cleanup();
}
private void cleanup() {
2017-03-31 01:58:05 +02:00
if (preferences == null) {
preferences = ApplicationLoader.applicationContext.getSharedPreferences("uploadinfo", Activity.MODE_PRIVATE);
}
preferences.edit().remove(fileKey + "_time").
remove(fileKey + "_size").
remove(fileKey + "_uploaded").
remove(fileKey + "_id").
remove(fileKey + "_iv").
remove(fileKey + "_key").
remove(fileKey + "_ivc").commit();
2015-02-27 20:57:58 +01:00
try {
if (stream != null) {
stream.close();
stream = null;
}
} catch (Exception e) {
2017-03-31 01:58:05 +02:00
FileLog.e(e);
2015-02-27 20:57:58 +01:00
}
2013-10-25 17:19:00 +02:00
}
2018-07-30 04:07:02 +02:00
protected void checkNewDataAvailable(final long newAvailableSize, final long finalSize) {
2019-01-23 18:03:33 +01:00
Utilities.stageQueue.postRunnable(() -> {
if (estimatedSize != 0 && finalSize != 0) {
estimatedSize = 0;
totalFileSize = finalSize;
calcTotalPartsCount();
if (!uploadFirstPartLater && started) {
storeFileUploadInfo();
}
}
2019-03-03 21:40:48 +01:00
availableSize = finalSize > 0 ? finalSize : newAvailableSize;
2019-01-23 18:03:33 +01:00
if (currentUploadRequetsCount < maxRequestsCount) {
startUploadRequest();
}
});
}
2017-03-31 01:58:05 +02:00
private void storeFileUploadInfo() {
2014-09-28 15:37:26 +02:00
SharedPreferences.Editor editor = preferences.edit();
editor.putInt(fileKey + "_time", uploadStartTime);
editor.putLong(fileKey + "_size", totalFileSize);
editor.putLong(fileKey + "_id", currentFileId);
editor.remove(fileKey + "_uploaded");
if (isEncrypted) {
editor.putString(fileKey + "_iv", Utilities.bytesToHex(iv));
editor.putString(fileKey + "_ivc", Utilities.bytesToHex(ivChange));
editor.putString(fileKey + "_key", Utilities.bytesToHex(key));
}
editor.commit();
}
2018-07-30 04:07:02 +02:00
private void calcTotalPartsCount() {
if (uploadFirstPartLater) {
if (isBigFile) {
2022-06-21 04:51:00 +02:00
totalPartsCount = 1 + (int) (((totalFileSize - uploadChunkSize) + uploadChunkSize - 1) / uploadChunkSize);
2018-07-30 04:07:02 +02:00
} else {
2022-06-21 04:51:00 +02:00
totalPartsCount = 1 + (int) (((totalFileSize - 1024) + uploadChunkSize - 1) / uploadChunkSize);
2018-07-30 04:07:02 +02:00
}
} else {
2022-06-21 04:51:00 +02:00
totalPartsCount = (int) ((totalFileSize + uploadChunkSize - 1) / uploadChunkSize);
2018-07-30 04:07:02 +02:00
}
}
2021-01-28 15:15:51 +01:00
public void setForceSmallFile() {
forceSmallFile = true;
}
2013-10-25 17:19:00 +02:00
private void startUploadRequest() {
if (state != 1) {
return;
}
2018-07-30 04:07:02 +02:00
final TLObject finalRequest;
final int currentRequestPartNum;
2013-12-20 20:25:49 +01:00
2017-03-31 01:58:05 +02:00
final int currentRequestBytes;
final byte[] currentRequestIv;
2013-10-25 17:19:00 +02:00
try {
2014-10-01 00:36:18 +02:00
started = true;
2013-10-25 17:19:00 +02:00
if (stream == null) {
File cacheFile = new File(uploadingFilePath);
2018-07-30 04:07:02 +02:00
if (AndroidUtilities.isInternalUri(Uri.fromFile(cacheFile))) {
2022-12-06 20:13:44 +01:00
throw new FileLog.IgnoreSentException("trying to upload internal file");
2018-07-30 04:07:02 +02:00
}
stream = new RandomAccessFile(cacheFile, "r");
2020-09-30 15:48:47 +02:00
boolean isInternalFile = false;
try {
@SuppressLint("DiscouragedPrivateApi") Method getInt = FileDescriptor.class.getDeclaredMethod("getInt$");
int fdint = (Integer) getInt.invoke(stream.getFD());
if (AndroidUtilities.isInternalUri(fdint)) {
isInternalFile = true;
}
} catch (Throwable e) {
FileLog.e(e);
}
if (isInternalFile) {
throw new Exception("trying to upload internal file");
}
if (estimatedSize != 0) {
totalFileSize = estimatedSize;
} else {
totalFileSize = cacheFile.length();
}
2021-01-28 15:15:51 +01:00
if (!forceSmallFile && totalFileSize > 10 * 1024 * 1024) {
2013-12-20 20:25:49 +01:00
isBigFile = true;
}
2013-10-27 00:34:39 +02:00
2022-06-21 04:51:00 +02:00
long maxUploadParts = MessagesController.getInstance(currentAccount).uploadMaxFileParts;
if (AccountInstance.getInstance(currentAccount).getUserConfig().isPremium() && totalFileSize > FileLoader.DEFAULT_MAX_FILE_SIZE) {
maxUploadParts = MessagesController.getInstance(currentAccount).uploadMaxFilePartsPremium;
}
uploadChunkSize = (int) Math.max(slowNetwork ? minUploadChunkSlowNetworkSize : minUploadChunkSize, (totalFileSize + 1024L * maxUploadParts - 1) / (1024L * maxUploadParts));
if (1024 % uploadChunkSize != 0) {
int chunkSize = 64;
while (uploadChunkSize > chunkSize) {
chunkSize *= 2;
}
uploadChunkSize = chunkSize;
}
2018-07-30 04:07:02 +02:00
maxRequestsCount = Math.max(1, (slowNetwork ? maxUploadingSlowNetworkKBytes : maxUploadingKBytes) / uploadChunkSize);
2017-07-08 18:32:04 +02:00
if (isEncrypted) {
freeRequestIvs = new ArrayList<>(maxRequestsCount);
for (int a = 0; a < maxRequestsCount; a++) {
freeRequestIvs.add(new byte[32]);
}
}
uploadChunkSize *= 1024;
2018-07-30 04:07:02 +02:00
calcTotalPartsCount();
2013-10-27 00:34:39 +02:00
readBuffer = new byte[uploadChunkSize];
2014-08-23 01:22:33 +02:00
fileKey = Utilities.MD5(uploadingFilePath + (isEncrypted ? "enc" : ""));
2014-08-23 01:22:33 +02:00
long fileSize = preferences.getLong(fileKey + "_size", 0);
2014-09-28 15:37:26 +02:00
uploadStartTime = (int)(System.currentTimeMillis() / 1000);
2014-08-23 01:22:33 +02:00
boolean rewrite = false;
2018-07-30 04:07:02 +02:00
if (!uploadFirstPartLater && !nextPartFirst && estimatedSize == 0 && fileSize == totalFileSize) {
currentFileId = preferences.getLong(fileKey + "_id", 0);
2014-08-23 01:22:33 +02:00
int date = preferences.getInt(fileKey + "_time", 0);
long uploadedSize = preferences.getLong(fileKey + "_uploaded", 0);
if (isEncrypted) {
String ivString = preferences.getString(fileKey + "_iv", null);
String keyString = preferences.getString(fileKey + "_key", null);
if (ivString != null && keyString != null) {
key = Utilities.hexToBytes(keyString);
iv = Utilities.hexToBytes(ivString);
2015-05-21 23:27:27 +02:00
if (key != null && iv != null && key.length == 32 && iv.length == 32) {
ivChange = new byte[32];
System.arraycopy(iv, 0, ivChange, 0, 32);
} else {
rewrite = true;
}
} else {
rewrite = true;
}
}
if (!rewrite && date != 0) {
2014-09-28 15:37:26 +02:00
if (isBigFile && date < uploadStartTime - 60 * 60 * 24) {
2014-08-23 01:22:33 +02:00
date = 0;
2014-09-28 15:37:26 +02:00
} else if (!isBigFile && date < uploadStartTime - 60 * 60 * 1.5f) {
2014-08-23 01:22:33 +02:00
date = 0;
}
if (date != 0) {
if (uploadedSize > 0) {
2017-03-31 01:58:05 +02:00
readBytesCount = uploadedSize;
2014-08-23 01:22:33 +02:00
currentPartNum = (int) (uploadedSize / uploadChunkSize);
if (!isBigFile) {
2017-03-31 01:58:05 +02:00
for (int b = 0; b < readBytesCount / uploadChunkSize; b++) {
int bytesRead = stream.read(readBuffer);
int toAdd = 0;
2017-03-31 01:58:05 +02:00
if (isEncrypted && bytesRead % 16 != 0) {
toAdd += 16 - bytesRead % 16;
}
2017-03-31 01:58:05 +02:00
NativeByteBuffer sendBuffer = new NativeByteBuffer(bytesRead + toAdd);
if (bytesRead != uploadChunkSize || totalPartsCount == currentPartNum + 1) {
isLastPart = true;
}
2017-03-31 01:58:05 +02:00
sendBuffer.writeBytes(readBuffer, 0, bytesRead);
if (isEncrypted) {
for (int a = 0; a < toAdd; a++) {
sendBuffer.writeByte(0);
}
2017-03-31 01:58:05 +02:00
Utilities.aesIgeEncryption(sendBuffer.buffer, key, ivChange, true, true, 0, bytesRead + toAdd);
}
2015-09-24 22:52:02 +02:00
sendBuffer.reuse();
}
} else {
2018-07-30 04:07:02 +02:00
stream.seek(uploadedSize);
if (isEncrypted) {
String ivcString = preferences.getString(fileKey + "_ivc", null);
if (ivcString != null) {
ivChange = Utilities.hexToBytes(ivcString);
2015-05-21 23:27:27 +02:00
if (ivChange == null || ivChange.length != 32) {
rewrite = true;
2017-03-31 01:58:05 +02:00
readBytesCount = 0;
2015-05-21 23:27:27 +02:00
currentPartNum = 0;
}
} else {
rewrite = true;
2017-03-31 01:58:05 +02:00
readBytesCount = 0;
currentPartNum = 0;
}
}
}
2014-08-23 01:22:33 +02:00
} else {
rewrite = true;
}
}
} else {
rewrite = true;
}
} else {
rewrite = true;
}
if (rewrite) {
if (isEncrypted) {
iv = new byte[32];
key = new byte[32];
ivChange = new byte[32];
Utilities.random.nextBytes(iv);
Utilities.random.nextBytes(key);
System.arraycopy(iv, 0, ivChange, 0, 32);
}
currentFileId = Utilities.random.nextLong();
2018-07-30 04:07:02 +02:00
if (!nextPartFirst && !uploadFirstPartLater && estimatedSize == 0) {
2017-03-31 01:58:05 +02:00
storeFileUploadInfo();
}
}
if (isEncrypted) {
try {
java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
byte[] arr = new byte[64];
System.arraycopy(key, 0, arr, 0, 32);
System.arraycopy(iv, 0, arr, 32, 32);
byte[] digest = md.digest(arr);
for (int a = 0; a < 4; a++) {
fingerprint |= ((digest[a] ^ digest[a + 4]) & 0xFF) << (a * 8);
}
} catch (Exception e) {
2017-03-31 01:58:05 +02:00
FileLog.e(e);
}
}
2017-03-31 01:58:05 +02:00
uploadedBytesCount = readBytesCount;
lastSavedPartNum = currentPartNum;
2018-07-30 04:07:02 +02:00
if (uploadFirstPartLater) {
if (isBigFile) {
stream.seek(uploadChunkSize);
readBytesCount = uploadChunkSize;
} else {
stream.seek(1024);
readBytesCount = 1024;
}
currentPartNum = 1;
}
2013-10-25 17:19:00 +02:00
}
2013-12-20 20:25:49 +01:00
if (estimatedSize != 0) {
2018-07-30 04:07:02 +02:00
if (readBytesCount + uploadChunkSize > availableSize) {
return;
}
}
2018-07-30 04:07:02 +02:00
if (nextPartFirst) {
stream.seek(0);
if (isBigFile) {
currentRequestBytes = stream.read(readBuffer);
} else {
currentRequestBytes = stream.read(readBuffer, 0, 1024);
}
currentPartNum = 0;
} else {
currentRequestBytes = stream.read(readBuffer);
}
2017-03-31 01:58:05 +02:00
if (currentRequestBytes == -1) {
return;
}
2013-10-25 17:19:00 +02:00
int toAdd = 0;
2017-03-31 01:58:05 +02:00
if (isEncrypted && currentRequestBytes % 16 != 0) {
toAdd += 16 - currentRequestBytes % 16;
2013-10-25 17:19:00 +02:00
}
2017-03-31 01:58:05 +02:00
NativeByteBuffer sendBuffer = new NativeByteBuffer(currentRequestBytes + toAdd);
2018-07-30 04:07:02 +02:00
if (nextPartFirst || currentRequestBytes != uploadChunkSize || estimatedSize == 0 && totalPartsCount == currentPartNum + 1) {
if (uploadFirstPartLater) {
nextPartFirst = true;
uploadFirstPartLater = false;
} else {
isLastPart = true;
}
2013-10-25 17:19:00 +02:00
}
2017-03-31 01:58:05 +02:00
sendBuffer.writeBytes(readBuffer, 0, currentRequestBytes);
if (isEncrypted) {
for (int a = 0; a < toAdd; a++) {
sendBuffer.writeByte(0);
}
2017-03-31 01:58:05 +02:00
Utilities.aesIgeEncryption(sendBuffer.buffer, key, ivChange, true, true, 0, currentRequestBytes + toAdd);
currentRequestIv = freeRequestIvs.get(0);
System.arraycopy(ivChange, 0, currentRequestIv, 0, 32);
freeRequestIvs.remove(0);
} else {
currentRequestIv = null;
}
2013-12-20 20:25:49 +01:00
if (isBigFile) {
TLRPC.TL_upload_saveBigFilePart req = new TLRPC.TL_upload_saveBigFilePart();
2018-07-30 04:07:02 +02:00
req.file_part = currentRequestPartNum = currentPartNum;
2013-12-20 20:25:49 +01:00
req.file_id = currentFileId;
if (estimatedSize != 0) {
req.file_total_parts = -1;
} else {
req.file_total_parts = totalPartsCount;
}
2013-12-20 20:25:49 +01:00
req.bytes = sendBuffer;
finalRequest = req;
} else {
TLRPC.TL_upload_saveFilePart req = new TLRPC.TL_upload_saveFilePart();
2018-07-30 04:07:02 +02:00
req.file_part = currentRequestPartNum = currentPartNum;
2013-12-20 20:25:49 +01:00
req.file_id = currentFileId;
req.bytes = sendBuffer;
finalRequest = req;
}
2018-07-30 04:07:02 +02:00
if (isLastPart && nextPartFirst) {
nextPartFirst = false;
currentPartNum = totalPartsCount - 1;
stream.seek(totalFileSize);
}
2017-03-31 01:58:05 +02:00
readBytesCount += currentRequestBytes;
2013-10-25 17:19:00 +02:00
} catch (Exception e) {
2017-03-31 01:58:05 +02:00
FileLog.e(e);
2018-07-30 04:07:02 +02:00
state = 4;
2013-10-25 17:19:00 +02:00
delegate.didFailedUploadingFile(this);
2014-08-23 01:22:33 +02:00
cleanup();
2013-10-25 17:19:00 +02:00
return;
}
2018-07-30 04:07:02 +02:00
currentPartNum++;
2017-03-31 01:58:05 +02:00
currentUploadRequetsCount++;
final int requestNumFinal = requestNum++;
2018-07-30 04:07:02 +02:00
final long currentRequestBytesOffset = currentRequestPartNum + currentRequestBytes;
2017-03-31 01:58:05 +02:00
final int requestSize = finalRequest.getObjectSize() + 4;
2018-07-30 04:07:02 +02:00
final int currentOperationGuid = operationGuid;
2017-07-08 18:32:04 +02:00
2018-07-30 04:07:02 +02:00
int connectionType;
if (slowNetwork) {
connectionType = ConnectionsManager.ConnectionTypeUpload;
} else {
connectionType = ConnectionsManager.ConnectionTypeUpload | ((requestNumFinal % 4) << 16);
}
2017-07-08 18:32:04 +02:00
2019-01-23 18:03:33 +01:00
int requestToken = ConnectionsManager.getInstance(currentAccount).sendRequest(finalRequest, (response, error) -> {
if (currentOperationGuid != operationGuid) {
return;
}
int networkType = response != null ? response.networkType : ApplicationLoader.getCurrentNetworkType();
if (currentType == ConnectionsManager.FileTypeAudio) {
StatsController.getInstance(currentAccount).incrementSentBytesCount(networkType, StatsController.TYPE_AUDIOS, requestSize);
} else if (currentType == ConnectionsManager.FileTypeVideo) {
StatsController.getInstance(currentAccount).incrementSentBytesCount(networkType, StatsController.TYPE_VIDEOS, requestSize);
} else if (currentType == ConnectionsManager.FileTypePhoto) {
StatsController.getInstance(currentAccount).incrementSentBytesCount(networkType, StatsController.TYPE_PHOTOS, requestSize);
} else if (currentType == ConnectionsManager.FileTypeFile) {
2023-02-03 20:11:36 +01:00
if (uploadingFilePath != null && (uploadingFilePath.toLowerCase().endsWith("mp3") || uploadingFilePath.toLowerCase().endsWith("m4a"))) {
StatsController.getInstance(currentAccount).incrementSentBytesCount(networkType, StatsController.TYPE_MUSIC, requestSize);
} else {
StatsController.getInstance(currentAccount).incrementSentBytesCount(networkType, StatsController.TYPE_FILES, requestSize);
}
2019-01-23 18:03:33 +01:00
}
if (currentRequestIv != null) {
freeRequestIvs.add(currentRequestIv);
}
requestTokens.delete(requestNumFinal);
if (response instanceof TLRPC.TL_boolTrue) {
if (state != 1) {
2018-07-30 04:07:02 +02:00
return;
}
2019-01-23 18:03:33 +01:00
uploadedBytesCount += currentRequestBytes;
long size;
if (estimatedSize != 0) {
size = Math.max(availableSize, estimatedSize);
} else {
size = totalFileSize;
2017-03-31 01:58:05 +02:00
}
2020-01-23 07:15:40 +01:00
delegate.didChangedUploadProgress(FileUploadOperation.this, uploadedBytesCount, size);
2019-01-23 18:03:33 +01:00
currentUploadRequetsCount--;
if (isLastPart && currentUploadRequetsCount == 0 && state == 1) {
state = 3;
if (key == null) {
TLRPC.InputFile result;
if (isBigFile) {
result = new TLRPC.TL_inputFileBig();
} else {
result = new TLRPC.TL_inputFile();
result.md5_checksum = "";
}
result.parts = currentPartNum;
result.id = currentFileId;
result.name = uploadingFilePath.substring(uploadingFilePath.lastIndexOf("/") + 1);
delegate.didFinishUploadingFile(FileUploadOperation.this, result, null, null, null);
cleanup();
2018-07-30 04:07:02 +02:00
} else {
2019-01-23 18:03:33 +01:00
TLRPC.InputEncryptedFile result;
if (isBigFile) {
result = new TLRPC.TL_inputEncryptedFileBigUploaded();
2017-03-31 01:58:05 +02:00
} else {
2019-01-23 18:03:33 +01:00
result = new TLRPC.TL_inputEncryptedFileUploaded();
result.md5_checksum = "";
2017-03-31 01:58:05 +02:00
}
2019-01-23 18:03:33 +01:00
result.parts = currentPartNum;
result.id = currentFileId;
result.key_fingerprint = fingerprint;
delegate.didFinishUploadingFile(FileUploadOperation.this, null, result, key, iv);
cleanup();
}
if (currentType == ConnectionsManager.FileTypeAudio) {
StatsController.getInstance(currentAccount).incrementSentItemsCount(ApplicationLoader.getCurrentNetworkType(), StatsController.TYPE_AUDIOS, 1);
} else if (currentType == ConnectionsManager.FileTypeVideo) {
StatsController.getInstance(currentAccount).incrementSentItemsCount(ApplicationLoader.getCurrentNetworkType(), StatsController.TYPE_VIDEOS, 1);
} else if (currentType == ConnectionsManager.FileTypePhoto) {
StatsController.getInstance(currentAccount).incrementSentItemsCount(ApplicationLoader.getCurrentNetworkType(), StatsController.TYPE_PHOTOS, 1);
} else if (currentType == ConnectionsManager.FileTypeFile) {
2023-02-03 20:11:36 +01:00
if (uploadingFilePath != null && (uploadingFilePath.toLowerCase().endsWith("mp3") || uploadingFilePath.toLowerCase().endsWith("m4a"))) {
StatsController.getInstance(currentAccount).incrementSentItemsCount(ApplicationLoader.getCurrentNetworkType(), StatsController.TYPE_MUSIC, 1);
} else {
StatsController.getInstance(currentAccount).incrementSentItemsCount(ApplicationLoader.getCurrentNetworkType(), StatsController.TYPE_FILES, 1);
}
2019-01-23 18:03:33 +01:00
}
} else if (currentUploadRequetsCount < maxRequestsCount) {
if (estimatedSize == 0 && !uploadFirstPartLater && !nextPartFirst) {
if (saveInfoTimes >= 4) {
saveInfoTimes = 0;
2017-07-08 18:32:04 +02:00
}
2019-01-23 18:03:33 +01:00
if (currentRequestPartNum == lastSavedPartNum) {
lastSavedPartNum++;
long offsetToSave = currentRequestBytesOffset;
byte[] ivToSave = currentRequestIv;
UploadCachedResult result;
while ((result = cachedResults.get(lastSavedPartNum)) != null) {
offsetToSave = result.bytesOffset;
ivToSave = result.iv;
cachedResults.remove(lastSavedPartNum);
2017-03-31 01:58:05 +02:00
lastSavedPartNum++;
2019-01-23 18:03:33 +01:00
}
if (isBigFile && offsetToSave % (1024 * 1024) == 0 || !isBigFile && saveInfoTimes == 0) {
SharedPreferences.Editor editor = preferences.edit();
editor.putLong(fileKey + "_uploaded", offsetToSave);
if (isEncrypted) {
editor.putString(fileKey + "_ivc", Utilities.bytesToHex(ivToSave));
}
2019-01-23 18:03:33 +01:00
editor.commit();
}
} else {
UploadCachedResult result = new UploadCachedResult();
result.bytesOffset = currentRequestBytesOffset;
if (currentRequestIv != null) {
result.iv = new byte[32];
System.arraycopy(currentRequestIv, 0, result.iv, 0, 32);
2013-10-25 17:19:00 +02:00
}
2019-01-23 18:03:33 +01:00
cachedResults.put(currentRequestPartNum, result);
2013-10-25 17:19:00 +02:00
}
2019-01-23 18:03:33 +01:00
saveInfoTimes++;
2017-03-31 01:58:05 +02:00
}
2019-01-23 18:03:33 +01:00
startUploadRequest();
}
} else {
state = 4;
delegate.didFailedUploadingFile(FileUploadOperation.this);
cleanup();
}
2019-01-23 18:03:33 +01:00
}, null, () -> Utilities.stageQueue.postRunnable(() -> {
if (currentUploadRequetsCount < maxRequestsCount) {
startUploadRequest();
2017-07-08 18:32:04 +02:00
}
2021-01-28 15:15:51 +01:00
}), forceSmallFile ? ConnectionsManager.RequestFlagCanCompress : 0, ConnectionsManager.DEFAULT_DATACENTER_ID, connectionType, true);
2017-03-31 01:58:05 +02:00
requestTokens.put(requestNumFinal, requestToken);
2013-10-25 17:19:00 +02:00
}
}