Exemple #1
0
        public byte[] Decrypt(byte[] data)
        {
            if (DecryptCountBuf == null)
            {
                DecryptCountBuf = new byte[16];
                DecryptNum      = 0;
            }

            return(Utils.AES_ctr128_encrypt(data, DecryptKey, ref DecryptIV, ref DecryptCountBuf, ref DecryptNum));
        }
Exemple #2
0
        public byte[] Encrypt(byte[] data)
        {
            if (EncryptCountBuf == null)
            {
                EncryptCountBuf = new byte[16];
                EncryptNum      = 0;
            }

            return(Utils.AES_ctr128_encrypt(data, EncryptKey, ref EncryptIV, ref EncryptCountBuf, ref EncryptNum));
        }
Exemple #3
0
        private TLUploadFileBase GetCdnFile(TLUploadFileCdnRedirect redirect, TLFileLocation location, int offset, int limit, out TLRPCError er, out bool isCanceled)
        {
            var manualResetEvent      = new ManualResetEvent(false);
            TLUploadFileBase result   = null;
            TLRPCError       outError = null;
            var outIsCanceled         = false;

            var req = new TLUploadGetCdnFile();

            req.FileToken = redirect.FileToken;
            req.Limit     = limit;
            req.Offset    = offset;

            _mtProtoService.SendRequestAsync <TLUploadCdnFileBase>("upload.getCdnFile", req, redirect.DCId, true, callback =>
            {
                if (callback is TLUploadCdnFile file)
                {
                    var iv      = redirect.EncryptionIV;
                    var counter = offset / 16;
                    iv[15]      = (byte)(counter & 0xFF);
                    iv[14]      = (byte)((counter >> 8) & 0xFF);
                    iv[13]      = (byte)((counter >> 16) & 0xFF);
                    iv[12]      = (byte)((counter >> 24) & 0xFF);

                    var key = CryptographicBuffer.CreateFromByteArray(redirect.EncryptionKey);

                    var ecount_buf = new byte[0];
                    var num        = 0u;
                    var bytes      = Utils.AES_ctr128_encrypt(file.Bytes, key, ref iv, ref ecount_buf, ref num);

                    result = new TLUploadFile {
                        Bytes = bytes
                    };
                    manualResetEvent.Set();

                    _statsService.IncrementReceivedBytesCount(_mtProtoService.NetworkType, _dataType, file.Bytes.Length + 4);
                }
                else if (callback is TLUploadCdnFileReuploadNeeded reupload)
                {
                    result = ReuploadFile(redirect, reupload.RequestToken, location, offset, limit, out outError, out outIsCanceled);
                    while (result == null)
                    {
                        result = ReuploadFile(redirect, reupload.RequestToken, location, offset, limit, out outError, out outIsCanceled);
                        if (outIsCanceled)
                        {
                            break;
                        }
                    }

                    manualResetEvent.Set();
                }
            },
                                                                   error =>
            {
                outError = error;

                if (error.CodeEquals(TLErrorCode.INTERNAL) ||
                    (error.CodeEquals(TLErrorCode.BAD_REQUEST) && (error.TypeEquals(TLErrorType.LOCATION_INVALID) || error.TypeEquals(TLErrorType.VOLUME_LOC_NOT_FOUND))) ||
                    (error.CodeEquals(TLErrorCode.NOT_FOUND) && error.ErrorMessage != null && error.ErrorMessage.ToString().StartsWith("Incorrect dhGen")))
                {
                    outIsCanceled = true;

                    manualResetEvent.Set();
                    return;
                }

                int delay;
                lock (_randomRoot)
                {
                    delay = _random.Next(1000, 3000);
                }

                Execute.BeginOnThreadPool(TimeSpan.FromMilliseconds(delay), () => manualResetEvent.Set());
            });

            manualResetEvent.WaitOne(20 * 1000);
            er         = outError;
            isCanceled = outIsCanceled;

            return(result);
        }
Exemple #4
0
        private void OnDownloading(object state)
        {
            DownloadablePart part = null;

            lock (_itemsSyncRoot)
            {
                for (var i = 0; i < _items.Count; i++)
                {
                    var item = _items[i];
                    if (item.IsCancelled)
                    {
                        _items.RemoveAt(i--);
                        try
                        {
                            _eventAggregator.Publish(new DownloadingCanceledEventArgs(item));
                        }
                        catch (Exception e)
                        {
                            TLUtils.WriteException(e);
                        }
                    }
                }

                foreach (var item in _items)
                {
                    part = item.Parts.FirstOrDefault(x => x.Status == PartStatus.Ready);
                    if (part != null)
                    {
                        part.Status = PartStatus.Processing;
                        break;
                    }
                }
            }

            if (part == null)
            {
                var currentWorker = (Worker)state;
                currentWorker.Stop();
                return;
            }

            TLRPCError error;
            bool       canceled;

            do
            {
                TLUploadFileBase result;
                if (part.ParentItem.CdnRedirect != null)
                {
                    result = GetCdnFile(part.ParentItem.CdnRedirect, part.ParentItem.Location, part.Offset, part.Limit, out error, out canceled);
                }
                else
                {
                    result = GetFile(part.ParentItem.Location, part.Offset, part.Limit, out error, out canceled);
                }

                if (result is TLUploadFileCdnRedirect redirect)
                {
                    part.ParentItem.CdnRedirect = redirect;
                    part.ParentItem.CdnHashes   = redirect.CdnFileHashes.ToDictionary(x => x.Offset, x => x);
                    continue;
                }
                else
                {
                    part.File = result as TLUploadFile;
                }

                if (canceled)
                {
                    lock (_itemsSyncRoot)
                    {
                        part.ParentItem.IsCancelled = true;
                        part.Status = PartStatus.Processed;
                        _items.Remove(part.ParentItem);
                    }

                    return;
                }
            } while (part.File == null);

            // indicate progress
            // indicate complete
            bool isComplete;
            bool isCanceled;
            var  progress = 0.0;

            lock (_itemsSyncRoot)
            {
                part.Status = PartStatus.Processed;

                var data = part.File.Bytes;
                if (data.Length < part.Limit && (part.Number + 1) != part.ParentItem.Parts.Count)
                {
                    var complete = part.ParentItem.Parts.All(x => x.Status == PartStatus.Processed);
                    if (!complete)
                    {
                        var emptyBufferSize = part.Limit - data.Length;
                        var position        = data.Length;

                        var missingPart = new DownloadablePart(part.ParentItem, position, emptyBufferSize, -part.Number);

                        var currentItemIndex = part.ParentItem.Parts.IndexOf(part);
                        part.ParentItem.Parts.Insert(currentItemIndex + 1, missingPart);
                    }
                }
                else if (data.Length == part.Limit && (part.Number + 1) == part.ParentItem.Parts.Count)
                {
                    var currentItemIndex = part.ParentItem.Parts.IndexOf(part);
                    var missingPart      = new DownloadablePart(part.ParentItem, part.Offset + part.Limit, part.Limit, currentItemIndex + 1);

                    part.ParentItem.Parts.Insert(currentItemIndex + 1, missingPart);
                }

                isCanceled = part.ParentItem.IsCancelled;

                isComplete = part.ParentItem.Parts.All(x => x.Status == PartStatus.Processed);
                if (!isComplete)
                {
                    var downloadedCount = part.ParentItem.Parts.Count(x => x.Status == PartStatus.Processed);
                    var count           = part.ParentItem.Parts.Count;
                    progress = (double)downloadedCount / count;
                }
                else
                {
                    _items.Remove(part.ParentItem);
                }
            }

            if (!isCanceled)
            {
                if (isComplete)
                {
                    byte[] bytes = { };
                    foreach (var p in part.ParentItem.Parts)
                    {
                        var partBytes = p.File.Bytes;

                        var redirect = part.ParentItem.CdnRedirect;
                        if (redirect != null)
                        {
                            var iv      = redirect.EncryptionIV;
                            var counter = p.Offset / 16;
                            iv[15] = (byte)(counter & 0xFF);
                            iv[14] = (byte)((counter >> 8) & 0xFF);
                            iv[13] = (byte)((counter >> 16) & 0xFF);
                            iv[12] = (byte)((counter >> 24) & 0xFF);

                            var key = CryptographicBuffer.CreateFromByteArray(redirect.EncryptionKey);

                            var ecount_buf = new byte[0];
                            var num        = 0u;
                            partBytes             = Utils.AES_ctr128_encrypt(partBytes, key, ref iv, ref ecount_buf, ref num);
                            redirect.EncryptionIV = iv;

                            //TLCdnFileHash hash;
                            //if (!part.ParentItem.CdnHashes.TryGetValue(p.Offset, out hash))
                            //{
                            //    var hashes = GetCdnFileHashes(redirect, part.ParentItem.Location, p.Offset, out TLRPCError er, out bool yolo);
                            //    if (hashes != null)
                            //    {
                            //        foreach (var item in hashes)
                            //        {
                            //            part.ParentItem.CdnHashes[item.Offset] = item;
                            //        }

                            //        part.ParentItem.CdnHashes.TryGetValue(p.Offset, out hash);
                            //    }
                            //}

                            //if (hash != null)
                            //{
                            //    var sha256 = Utils.ComputeSHA256(partBytes);
                            //    if (!sha256.SequenceEqual(hash.Hash))
                            //    {
                            //        lock (_itemsSyncRoot)
                            //        {
                            //            part.ParentItem.IsCancelled = true;
                            //            part.Status = PartStatus.Processed;
                            //            _items.Remove(part.ParentItem);
                            //        }

                            //        Debug.WriteLine("HASH DOESN'T MATCH");
                            //        return;
                            //    }
                            //}
                        }

                        bytes = TLUtils.Combine(bytes, partBytes);
                    }
                    //part.ParentItem.Location.Buffer = bytes;
                    var fileName = String.Format("{0}_{1}_{2}.jpg",
                                                 part.ParentItem.Location.VolumeId,
                                                 part.ParentItem.Location.LocalId,
                                                 part.ParentItem.Location.Secret);

                    FileUtils.WriteTemporaryBites(fileName, bytes);

                    if (part.ParentItem.Callback != null)
                    {
                        part.ParentItem.Progress.Report(1.0);
                        part.ParentItem.Callback.TrySetResult(part.ParentItem);
                    }
                    else
                    {
                        part.ParentItem.Action?.Invoke(part.ParentItem);
                        Execute.BeginOnThreadPool(() => _eventAggregator.Publish(part.ParentItem));
                    }

                    _statsService.IncrementReceivedItemsCount(_protoService.NetworkType, _dataType, 1);
                }
                else
                {
                    if (part.ParentItem.Callback != null)
                    {
                        part.ParentItem.Progress.Report(progress);
                    }
                    else
                    {
                        Execute.BeginOnThreadPool(() => _eventAggregator.Publish(new DownloadProgressChangedEventArgs(part.ParentItem, progress)));
                    }
                }
            }
        }
        protected TLFileBase GetCdnFile(TLFileCdnRedirect redirect, TLInt offset, TLInt limit, out TLCdnFileReuploadNeeded reuploadNeeded, out TLRPCError er, out bool isCanceled, out bool isTokenInvalid)
        {
            var        manualResetEvent = new ManualResetEvent(false);
            TLFileBase result           = null;
            TLCdnFileReuploadNeeded outReuploadNeeded = null;
            TLRPCError outError          = null;
            var        outIsCanceled     = false;
            var        outIsTokenInvalid = false;

            _mtProtoService.GetCdnFileAsync(redirect.DCId, redirect.FileToken, offset, limit,
                                            cdnFileBase =>
            {
                var cdnFile = cdnFileBase as TLCdnFile;
                if (cdnFile != null)
                {
                    var iv      = GetIV(redirect.EncryptionIV.Data, offset);
                    var counter = offset.Value / 16;
                    iv[15]      = (byte)(counter & 0xFF);
                    iv[14]      = (byte)((counter >> 8) & 0xFF);
                    iv[13]      = (byte)((counter >> 16) & 0xFF);
                    iv[12]      = (byte)((counter >> 24) & 0xFF);

                    var key = redirect.EncryptionKey.Data;

                    var ecount_buf = new byte[0];
                    var num        = 0u;
                    var bytes      = Utils.AES_ctr128_encrypt(cdnFile.Bytes.Data, key, ref iv, ref ecount_buf, ref num);

                    result = new TLFile {
                        Bytes = TLString.FromBigEndianData(bytes)
                    };
                }

                var cdnFileReuploadNeeded = cdnFileBase as TLCdnFileReuploadNeeded;
                if (cdnFileReuploadNeeded != null)
                {
                    outReuploadNeeded = cdnFileReuploadNeeded;
                }

                manualResetEvent.Set();
            },
                                            error =>
            {
                outError = error;

                if (error.CodeEquals(ErrorCode.INTERNAL) ||
                    (error.CodeEquals(ErrorCode.BAD_REQUEST) && (error.TypeEquals(ErrorType.LOCATION_INVALID) || error.TypeEquals(ErrorType.VOLUME_LOC_NOT_FOUND))) ||
                    (error.CodeEquals(ErrorCode.NOT_FOUND) && error.Message != null && error.Message.ToString().StartsWith("Incorrect dhGen")))
                {
                    outIsCanceled = true;

                    manualResetEvent.Set();
                    return;
                }
                if (error.CodeEquals(ErrorCode.BAD_REQUEST) && error.TypeEquals(ErrorType.FILE_TOKEN_INVALID))
                {
                    outIsTokenInvalid = true;

                    manualResetEvent.Set();
                    return;
                }

                int delay;
                lock (_randomRoot)
                {
                    delay = _random.Next(1000, 3000);
                }

                Execute.BeginOnThreadPool(TimeSpan.FromMilliseconds(delay), () => manualResetEvent.Set());
            });

            manualResetEvent.WaitOne();
            reuploadNeeded = outReuploadNeeded;
            er             = outError;
            isCanceled     = outIsCanceled;
            isTokenInvalid = outIsTokenInvalid;

            return(result);
        }