/// <summary> /// 将客户端传递的 IP 地址与端口转换为 <see cref="IPEndPoint"/> 类型。 /// </summary> private IPEndPoint ConvertClientAddress(GetPeersInfoInput apiInput) { if (IPAddress.TryParse(apiInput.Ip, out IPAddress ipAddress)) { return(new IPEndPoint(ipAddress, apiInput.Port)); } return(null); }
public AnnounceInputParameters(GetPeersInfoInput apiInput) { Error = new BDictionary(); ClientAddress = ConvertClientAddress(apiInput); InfoHash = ConvertInfoHash(apiInput); Event = ConvertTorrentEvent(apiInput); PeerId = apiInput.Peer_Id; Uploaded = apiInput.Uploaded; Downloaded = apiInput.Downloaded; Left = apiInput.Left; IsEnableCompact = apiInput.Compact == 1; PeerWantCount = apiInput.NumWant ?? 30; }
public async Task GetPeersInfo(GetPeersInfoInput input) { // 如果 BT 客户端没有传递 IP,则通过 Context 获得。 if (string.IsNullOrEmpty(input.Ip)) { input.Ip = _httpContextAccessor.HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString(); } // 本机测试用。 input.Ip = "127.0.0.1"; AnnounceInputParameters inputPara = input; var resultDict = new BDictionary(); // 如果产生了错误,则不执行其他操作,直接返回结果。 if (inputPara.Error.Count == 0) { _bitTorrentManager.UpdatePeer(input.Info_Hash, inputPara); _bitTorrentManager.ClearZombiePeers(input.Info_Hash, TimeSpan.FromMinutes(10)); var peers = _bitTorrentManager.GetPeers(input.Info_Hash); HandlePeersData(resultDict, peers, inputPara); // 构建剩余字段信息 // 客户端等待时间 resultDict.Add(TrackerServerConsts.IntervalKey, new BNumber((int)TimeSpan.FromSeconds(30).TotalSeconds)); // 最小等待间隔 resultDict.Add(TrackerServerConsts.MinIntervalKey, new BNumber((int)TimeSpan.FromSeconds(30).TotalSeconds)); // Tracker 服务器的 Id resultDict.Add(TrackerServerConsts.TrackerIdKey, new BString("Tracker-DEMO")); // 已完成的 Peer 数量 resultDict.Add(TrackerServerConsts.CompleteKey, new BNumber(_bitTorrentManager.GetComplete(input.Info_Hash))); // 非做种状态的 Peer 数量 resultDict.Add(TrackerServerConsts.IncompleteKey, new BNumber(_bitTorrentManager.GetInComplete(input.Info_Hash))); } else { resultDict = inputPara.Error; } // 写入响应结果。 var resultDictBytes = resultDict.EncodeAsBytes(); var response = _httpContextAccessor.HttpContext.Response; response.ContentType = "text/plain"; response.StatusCode = 200; response.ContentLength = resultDictBytes.Length; await response.Body.WriteAsync(resultDictBytes); }
/// <summary> /// 将 info_hash 参数从 URL 编码转换为标准的字符串。 /// </summary> private string ConvertInfoHash(GetPeersInfoInput apiInput) { var infoHashBytes = HttpUtility.UrlDecodeToBytes(apiInput.Info_Hash); if (infoHashBytes == null) { Error.Add(TrackerServerConsts.FailureKey, new BString("info_hash 参数不能为空.")); return(null); } if (infoHashBytes.Length != 20) { Error.Add(TrackerServerConsts.FailureKey, new BString($"info_hash 参数的长度 {{{infoHashBytes.Length}}} 不符合 BT 协议规范.")); } return(BitConverter.ToString(infoHashBytes)); }
/// <summary> /// 将客户端传递的字符串 Event 转换为 <see cref="TorrentEvent"/> 枚举。 /// </summary> private TorrentEvent ConvertTorrentEvent(GetPeersInfoInput apiInput) { switch (apiInput.Event) { case "started": return(TorrentEvent.Started); case "stopped": return(TorrentEvent.Stopped); case "completed": return(TorrentEvent.Completed); default: return(TorrentEvent.None); } }