private void RequestNextNeededPiece(PeerId id) { var index = _bitField.FirstFalse(); if (index == -1) return; //throw exception or switch to regular? var m = new LTMetadata(id, LTMetadata.eMessageType.Request, index); id.Enqueue(m); _requestTimeout = DateTime.Now.Add(Timeout); }
protected override async void HandleLtMetadataMessage(PeerId id, LTMetadata message) { base.HandleLtMetadataMessage(id, message); switch (message.MetadataMessageType) { case LTMetadata.eMessageType.Data: if (Stream == null) throw new Exception("Need extention handshake before ut_metadata message."); Stream.Seek(message.Piece*LTMetadata.BlockSize, SeekOrigin.Begin); Stream.Write(message.MetadataPiece, 0, message.MetadataPiece.Length); _bitField[message.Piece] = true; if (_bitField.AllTrue) { Stream.Position = 0; var hash = SHA1Helper.ComputeHash(Stream.ToArray()); if (!Manager.InfoHash.Equals(hash)) { _bitField.SetAll(false); } else { Common.Torrent t; Stream.Position = 0; var dict = new BEncodedDictionary {{"info", BEncodedValue.Decode(Stream)}}; // FIXME: Add the trackers too if (Common.Torrent.TryLoad(dict.Encode(), out t)) { try { var file = await _saveFolder.CreateFileAsync(Manager.InfoHash.ToHex() + ".torrent", CreationCollisionOption.ReplaceExisting); File.WriteAllBytes(file.Path, dict.Encode()); } catch (Exception ex) { Debug.WriteLine("*METADATA EXCEPTION* - Can not write in {0} : {1}", _saveFolder, ex); Manager.Error = new Error(Reason.WriteFailure, ex); Manager.Mode = new ErrorMode(Manager); return; } t.TorrentPath = _saveFolder.Path; Manager.Torrent = t; SwitchToRegular(); } else { _bitField.SetAll(false); } } } //Double test because we can change the bitfield in the other block if (!_bitField.AllTrue) { RequestNextNeededPiece(id); } break; case LTMetadata.eMessageType.Reject: //TODO //Think to what we do in this situation //for moment nothing ;) //reject or flood? break; case LTMetadata.eMessageType.Request: //ever done in base class but needed to avoid default break; default: throw new MessageException(string.Format("Invalid messagetype in LTMetadata: {0}", message.MetadataMessageType)); } }