├── .gitattributes
├── .gitignore
├── DHTSpider.sln
├── README.md
├── SimpleClient
├── App.config
├── NLog.config
├── Program.cs
├── Properties
│ └── AssemblyInfo.cs
└── SimpleClient.csproj
├── Spider
├── Cache
│ ├── DefaultCache.cs
│ ├── ICache.cs
│ └── RedisCache.cs
├── Core
│ ├── DHTSpider.cs
│ ├── EasyTokenManager.cs
│ └── UdpSocketListener.cs
├── Helper
│ └── RedisHelper.cs
├── Log
│ └── Logger.cs
├── Properties
│ └── AssemblyInfo.cs
├── Queue
│ ├── DefaultQueue.cs
│ ├── IQueue.cs
│ └── RedisQueue.cs
├── Spider.csproj
├── SpiderConfiguration.cs
├── SpiderSetting.cs
├── Store
│ ├── ElasticSearchStore.cs
│ ├── IStore.cs
│ └── MongoDBStore.cs
└── packages.config
├── Tancoder.Torrent
├── BigInteger.cs
├── ClassDiagram.cd
├── EventArgs
│ ├── NodeAddedEventArgs.cs
│ ├── NodeFoundEventArgs.cs
│ └── StateUpdateEventArgs.cs
├── Exceptions
│ ├── ChangeLog
│ ├── ConnectionException.cs
│ ├── ListenerException.cs
│ ├── MessageException.cs
│ ├── ProtocolException.cs
│ └── TorrentLoadException.cs
├── FindPeersResult.cs
├── GetPeersResult.cs
├── IDhtEngine.cs
├── IMetaDataFilter.cs
├── ISpider.cs
├── InfoHash.cs
├── Listeners
│ ├── DhtListener.cs
│ ├── Listener.cs
│ ├── UdpListener.cs
│ └── WireListener.cs
├── MessageException.cs
├── MessageFactory.cs
├── Messages
│ ├── DhtMessage.cs
│ ├── Errors
│ │ └── ErrorMessage.cs
│ ├── Queries
│ │ ├── AnnouncePeer.cs
│ │ ├── FindNode.cs
│ │ ├── GetPeers.cs
│ │ ├── Ping.cs
│ │ └── QueryMessage.cs
│ ├── Responses
│ │ ├── AnnouncePeerResponse.cs
│ │ ├── FindNodeResponse.cs
│ │ ├── GetPeersResponse.cs
│ │ ├── PingResponse.cs
│ │ └── ResponseMessage.cs
│ ├── Wire
│ │ ├── ExtData.cs
│ │ ├── ExtHandShack.cs
│ │ ├── ExtQueryPiece.cs
│ │ ├── ExtendMessage.cs
│ │ └── HandShack.cs
│ └── WireMessage.cs
├── Metadata.cs
├── MonoTorrent.BEncoding
│ ├── BEncodedDictionary.cs
│ ├── BEncodedList.cs
│ ├── BEncodedNumber.cs
│ ├── BEncodedString.cs
│ ├── BEncodingException.cs
│ ├── ChangeLog
│ ├── IBEncodedValue.cs
│ └── RawReader.cs
├── NoTraceMessage.cs
├── Nodes
│ ├── ITokenManager.cs
│ ├── Node.cs
│ ├── NodeId.cs
│ └── NodeState.cs
├── Properties
│ └── AssemblyInfo.cs
├── Source
│ ├── Check.cs
│ ├── Enums.cs
│ ├── IMessage.cs
│ ├── Message.cs
│ ├── ToolBox.cs
│ ├── TorrentException.cs
│ ├── UriHelper.cs
│ └── VersionInfo.cs
├── Tancoder.Torrent.csproj
├── TransactionId.cs
└── packages.config
└── demo.png
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | [Xx]64/
19 | [Xx]86/
20 | [Bb]uild/
21 | bld/
22 | [Bb]in/
23 | [Oo]bj/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | artifacts/
46 |
47 | *_i.c
48 | *_p.c
49 | *_i.h
50 | *.ilk
51 | *.meta
52 | *.obj
53 | *.pch
54 | *.pdb
55 | *.pgc
56 | *.pgd
57 | *.rsp
58 | *.sbr
59 | *.tlb
60 | *.tli
61 | *.tlh
62 | *.tmp
63 | *.tmp_proj
64 | *.log
65 | *.vspscc
66 | *.vssscc
67 | .builds
68 | *.pidb
69 | *.svclog
70 | *.scc
71 |
72 | # Chutzpah Test files
73 | _Chutzpah*
74 |
75 | # Visual C++ cache files
76 | ipch/
77 | *.aps
78 | *.ncb
79 | *.opendb
80 | *.opensdf
81 | *.sdf
82 | *.cachefile
83 | *.VC.db
84 |
85 | # Visual Studio profiler
86 | *.psess
87 | *.vsp
88 | *.vspx
89 | *.sap
90 |
91 | # TFS 2012 Local Workspace
92 | $tf/
93 |
94 | # Guidance Automation Toolkit
95 | *.gpState
96 |
97 | # ReSharper is a .NET coding add-in
98 | _ReSharper*/
99 | *.[Rr]e[Ss]harper
100 | *.DotSettings.user
101 |
102 | # JustCode is a .NET coding add-in
103 | .JustCode
104 |
105 | # TeamCity is a build add-in
106 | _TeamCity*
107 |
108 | # DotCover is a Code Coverage Tool
109 | *.dotCover
110 |
111 | # NCrunch
112 | _NCrunch_*
113 | .*crunch*.local.xml
114 | nCrunchTemp_*
115 |
116 | # MightyMoose
117 | *.mm.*
118 | AutoTest.Net/
119 |
120 | # Web workbench (sass)
121 | .sass-cache/
122 |
123 | # Installshield output folder
124 | [Ee]xpress/
125 |
126 | # DocProject is a documentation generator add-in
127 | DocProject/buildhelp/
128 | DocProject/Help/*.HxT
129 | DocProject/Help/*.HxC
130 | DocProject/Help/*.hhc
131 | DocProject/Help/*.hhk
132 | DocProject/Help/*.hhp
133 | DocProject/Help/Html2
134 | DocProject/Help/html
135 |
136 | # Click-Once directory
137 | publish/
138 |
139 | # Publish Web Output
140 | *.[Pp]ublish.xml
141 | *.azurePubxml
142 |
143 | # TODO: Un-comment the next line if you do not want to checkin
144 | # your web deploy settings because they may include unencrypted
145 | # passwords
146 | #*.pubxml
147 | *.publishproj
148 |
149 | # NuGet Packages
150 | *.nupkg
151 | # The packages folder can be ignored because of Package Restore
152 | **/packages/*
153 | # except build/, which is used as an MSBuild target.
154 | !**/packages/build/
155 | # Uncomment if necessary however generally it will be regenerated when needed
156 | #!**/packages/repositories.config
157 | # NuGet v3's project.json files produces more ignoreable files
158 | *.nuget.props
159 | *.nuget.targets
160 |
161 | # Microsoft Azure Build Output
162 | csx/
163 | *.build.csdef
164 |
165 | # Microsoft Azure Emulator
166 | ecf/
167 | rcf/
168 |
169 | # Microsoft Azure ApplicationInsights config file
170 | ApplicationInsights.config
171 |
172 | # Windows Store app package directory
173 | AppPackages/
174 | BundleArtifacts/
175 |
176 | # Visual Studio cache files
177 | # files ending in .cache can be ignored
178 | *.[Cc]ache
179 | # but keep track of directories ending in .cache
180 | !*.[Cc]ache/
181 |
182 | # Others
183 | ClientBin/
184 | [Ss]tyle[Cc]op.*
185 | ~$*
186 | *~
187 | *.dbmdl
188 | *.dbproj.schemaview
189 | *.pfx
190 | *.publishsettings
191 | node_modules/
192 | orleans.codegen.cs
193 |
194 | # RIA/Silverlight projects
195 | Generated_Code/
196 |
197 | # Backup & report files from converting an old project file
198 | # to a newer Visual Studio version. Backup files are not needed,
199 | # because we have git ;-)
200 | _UpgradeReport_Files/
201 | Backup*/
202 | UpgradeLog*.XML
203 | UpgradeLog*.htm
204 |
205 | # SQL Server files
206 | *.mdf
207 | *.ldf
208 |
209 | # Business Intelligence projects
210 | *.rdl.data
211 | *.bim.layout
212 | *.bim_*.settings
213 |
214 | # Microsoft Fakes
215 | FakesAssemblies/
216 |
217 | # GhostDoc plugin setting file
218 | *.GhostDoc.xml
219 |
220 | # Node.js Tools for Visual Studio
221 | .ntvs_analysis.dat
222 |
223 | # Visual Studio 6 build log
224 | *.plg
225 |
226 | # Visual Studio 6 workspace options file
227 | *.opt
228 |
229 | # Visual Studio LightSwitch build output
230 | **/*.HTMLClient/GeneratedArtifacts
231 | **/*.DesktopClient/GeneratedArtifacts
232 | **/*.DesktopClient/ModelManifest.xml
233 | **/*.Server/GeneratedArtifacts
234 | **/*.Server/ModelManifest.xml
235 | _Pvt_Extensions
236 |
237 | # LightSwitch generated files
238 | GeneratedArtifacts/
239 | ModelManifest.xml
240 |
241 | # Paket dependency manager
242 | .paket/paket.exe
243 |
244 | # FAKE - F# Make
245 | .fake/
--------------------------------------------------------------------------------
/DHTSpider.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26430.14
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tancoder.Torrent", "Tancoder.Torrent\Tancoder.Torrent.csproj", "{B3FDEA8E-20F3-4BE3-B73A-505B45BA9501}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spider", "Spider\Spider.csproj", "{E0279EF8-1F47-4CB2-983E-736C375D73C5}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleClient", "SimpleClient\SimpleClient.csproj", "{F2A5753C-3AF2-40F2-9BB8-FD4B3A528ECB}"
11 | EndProject
12 | Global
13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 | Debug|Any CPU = Debug|Any CPU
15 | Release|Any CPU = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {B3FDEA8E-20F3-4BE3-B73A-505B45BA9501}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19 | {B3FDEA8E-20F3-4BE3-B73A-505B45BA9501}.Debug|Any CPU.Build.0 = Debug|Any CPU
20 | {B3FDEA8E-20F3-4BE3-B73A-505B45BA9501}.Release|Any CPU.ActiveCfg = Release|Any CPU
21 | {B3FDEA8E-20F3-4BE3-B73A-505B45BA9501}.Release|Any CPU.Build.0 = Release|Any CPU
22 | {E0279EF8-1F47-4CB2-983E-736C375D73C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23 | {E0279EF8-1F47-4CB2-983E-736C375D73C5}.Debug|Any CPU.Build.0 = Debug|Any CPU
24 | {E0279EF8-1F47-4CB2-983E-736C375D73C5}.Release|Any CPU.ActiveCfg = Release|Any CPU
25 | {E0279EF8-1F47-4CB2-983E-736C375D73C5}.Release|Any CPU.Build.0 = Release|Any CPU
26 | {F2A5753C-3AF2-40F2-9BB8-FD4B3A528ECB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {F2A5753C-3AF2-40F2-9BB8-FD4B3A528ECB}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {F2A5753C-3AF2-40F2-9BB8-FD4B3A528ECB}.Release|Any CPU.ActiveCfg = Release|Any CPU
29 | {F2A5753C-3AF2-40F2-9BB8-FD4B3A528ECB}.Release|Any CPU.Build.0 = Release|Any CPU
30 | EndGlobalSection
31 | GlobalSection(SolutionProperties) = preSolution
32 | HideSolutionNode = FALSE
33 | EndGlobalSection
34 | EndGlobal
35 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DHTSpider
2 | >A Very Simple Spider With DHT Crawler, Written by C#.
3 |
4 | * The bittorrent library bases on MonoTorrent.
5 |
6 | ### 介绍
7 |
8 | DHTSpider 是一个由C#编写的 DHT 爬虫, 从全球` DHT ` 网络里"`嗅探`"正在下载的资源, 并把资源`metadata`(种子信息)进行抓取下载.
9 |
10 |
11 | ### 相关
12 |
13 | >Cache
14 |
15 | + 使用 `Memory` > UseDefaultCache ( 默认 )
16 | + 使用 `Redis` > UseRedisCache ( TODO )
17 |
18 | >Queue
19 |
20 | + 使用 `Memory` > UseDefaultQueue ( 默认 )
21 | + 使用 `Redis` > UseRedisQueue ( TODO )
22 |
23 | >Store
24 |
25 | + 使用 `MongoDB` > UseMongoDBStore ( TODO )
26 | + 使用 `ElasticSearch` > UseElasticSearchStore ( TODO )
27 |
28 | >Log > `NLog`
29 |
30 | >Ioc > `Autofac`
31 |
32 | ### 环境
33 |
34 | 1. `.net` 版本 `>=4.5.2`
35 |
36 | 2. 运行的机器需要`独立IP` , 内网机器需要做下`端口映射`
37 |
38 |
39 | ### 使用
40 |
41 | ```c#
42 |
43 | var spider = SpiderConfiguration.Create() //使用默认配置
44 | .UseDefaultCache() //默认使用内存缓存
45 | .UseDefaultQueue() //默认使用内存队列
46 | .Start();
47 |
48 | ```
49 |
50 | ### 配置
51 |
52 | ```c#
53 |
54 | var spider = SpiderConfiguration.Create(new SpiderSetting()
55 | {
56 | LocalPort = 6881, //使用端口
57 | IsSaveTorrent = true, //是否保存torrent
58 | TorrentSavePath = "", //torrent保存路径
59 | MaxSpiderThreadCount = 1, //爬虫线程数
60 | MaxDownLoadThreadCount = 20 //下载线程数
61 | })
62 | .UseRedisCache() //使用redis缓存
63 | .UseRedisQueue() //使用redis队列
64 | .UseMongoDBStore() //使用mongodb存储
65 | .Start();
66 |
67 | ```
68 |
69 |
70 | #### demo
71 | 
72 |
73 |
--------------------------------------------------------------------------------
/SimpleClient/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/SimpleClient/NLog.config:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
12 |
13 |
14 |
18 |
19 |
20 |
25 |
26 |
31 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
51 |
52 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/SimpleClient/Program.cs:
--------------------------------------------------------------------------------
1 | using Spider;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace SimpleClient
9 | {
10 | class Program
11 | {
12 | static void Main(string[] args)
13 | {
14 | SpiderConfiguration.Create(new SpiderSetting()
15 | {
16 | LocalPort = 6881,//使用端口
17 | IsSaveTorrent = true,//是否保存torrent
18 | TorrentSavePath = "",//torrent保存路径
19 | MaxSpiderThreadCount = 1,//爬虫线程数
20 | MaxDownLoadThreadCount = 5//下载线程数
21 | })
22 | .UseDefaultCache() //默认使用内存缓存
23 | .UseDefaultQueue() //默认使用内存队列
24 | .Start();
25 |
26 |
27 | Console.ReadKey();
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/SimpleClient/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的一般信息由以下
6 | // 控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle("SimpleClient")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Microsoft")]
12 | [assembly: AssemblyProduct("SimpleClient")]
13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2017")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // 将 ComVisible 设置为 false 会使此程序集中的类型
18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
19 | //请将此类型的 ComVisible 特性设置为 true。
20 | [assembly: ComVisible(false)]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid("f2a5753c-3af2-40f2-9bb8-fd4b3a528ecb")]
24 |
25 | // 程序集的版本信息由下列四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 生成号
30 | // 修订号
31 | //
32 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
33 | // 方法是按如下所示使用“*”: :
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/SimpleClient/SimpleClient.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {F2A5753C-3AF2-40F2-9BB8-FD4B3A528ECB}
8 | Exe
9 | SimpleClient
10 | SimpleClient
11 | v4.5.2
12 | 512
13 | true
14 |
15 |
16 | AnyCPU
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | AnyCPU
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | Always
52 |
53 |
54 |
55 |
56 | {e0279ef8-1f47-4cb2-983e-736c375d73c5}
57 | Spider
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/Spider/Cache/DefaultCache.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Runtime.Caching;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | namespace Spider.Cache
10 | {
11 | public class DefaultCache : ICache
12 | {
13 | public ConcurrentDictionary _cache = null;
14 | public DefaultCache()
15 | {
16 | _cache = new ConcurrentDictionary();
17 | }
18 |
19 | public object Get(string key)
20 | {
21 | return MemoryCache.Default.Get(key);
22 | //object val = null;
23 | //_cache.TryGetValue(key, out val);
24 | //return val;
25 | }
26 |
27 | public void Set(string key, object val)
28 | {
29 | MemoryCache.Default.Set(key, val, new CacheItemPolicy());
30 | //_cache.TryAdd(key, val);
31 | }
32 |
33 | public bool ContainsKey(string key)
34 | {
35 | return MemoryCache.Default.Contains(key);
36 | //return _cache.ContainsKey(key);
37 | }
38 |
39 | public int Count()
40 | {
41 | return MemoryCache.Default.Count();
42 | //return _cache.Count;
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Spider/Cache/ICache.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Spider.Cache
8 | {
9 | public interface ICache
10 | {
11 | bool ContainsKey(string key);
12 |
13 | object Get(string key);
14 |
15 | void Set(string key, object val);
16 |
17 | int Count();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Spider/Cache/RedisCache.cs:
--------------------------------------------------------------------------------
1 | using Spider.Helper;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace Spider.Cache
9 | {
10 | public class RedisCache : ICache
11 | {
12 | //TODO
13 | public RedisCache()
14 | {
15 | }
16 |
17 | public bool ContainsKey(string key)
18 | {
19 | throw new NotImplementedException();
20 | }
21 |
22 | public int Count()
23 | {
24 | throw new NotImplementedException();
25 | }
26 |
27 | public object Get(string key)
28 | {
29 | throw new NotImplementedException();
30 | }
31 |
32 | public void Set(string key, object val)
33 | {
34 | throw new NotImplementedException();
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Spider/Core/EasyTokenManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using Tancoder.Torrent.BEncoding;
6 | using Tancoder.Torrent.Dht;
7 |
8 | namespace Spider.Core
9 | {
10 | public class EasyTokenManager : ITokenManager
11 | {
12 | public TimeSpan Timeout { get; set; }
13 | private readonly int tokenLength = 10;
14 |
15 | public BEncodedString GenerateToken(Node node)
16 | {
17 | BEncodedString token = getToken(node);
18 | return token;
19 | }
20 |
21 | private BEncodedString getToken(Node node)
22 | {
23 | byte[] buffer = new byte[tokenLength];
24 | Array.Copy(node.Id.Bytes, buffer, tokenLength);
25 | var token = new BEncodedString(buffer);
26 | return token;
27 | }
28 |
29 | public bool VerifyToken(Node node, BEncodedString token)
30 | {
31 | return getToken(node).Equals(token);
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Spider/Core/UdpSocketListener.cs:
--------------------------------------------------------------------------------
1 | using Spider.Log;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Net;
6 | using System.Net.Sockets;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 |
10 | namespace Spider.Core
11 | {
12 | public delegate void MessageReceived(byte[] buffer, IPEndPoint endpoint);
13 |
14 | public class UdpSocketListener
15 | {
16 | private IPEndPoint endpoint;
17 | public IPEndPoint Endpoint
18 | {
19 | get { return endpoint; }
20 | }
21 |
22 | private Socket m_ListenSocket;
23 |
24 | private SocketAsyncEventArgs m_ReceiveSAE;
25 |
26 | public UdpSocketListener(IPEndPoint endpoint)
27 | {
28 | this.endpoint = endpoint;
29 | }
30 |
31 | public void Start()
32 | {
33 | try
34 | {
35 | m_ListenSocket = new Socket(this.endpoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
36 | m_ListenSocket.Ttl = 255;
37 | m_ListenSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
38 | m_ListenSocket.Bind(this.endpoint);
39 |
40 | //Mono 不支持
41 | //if (Platform.SupportSocketIOControlByCodeEnum)
42 | {
43 | uint IOC_IN = 0x80000000;
44 | uint IOC_VENDOR = 0x18000000;
45 | uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
46 |
47 | byte[] optionInValue = { Convert.ToByte(false) };
48 | byte[] optionOutValue = new byte[4];
49 | m_ListenSocket.IOControl((int)SIO_UDP_CONNRESET, optionInValue, optionOutValue);
50 | }
51 |
52 | var eventArgs = new SocketAsyncEventArgs();
53 | m_ReceiveSAE = eventArgs;
54 |
55 | eventArgs.Completed += new EventHandler(eventArgs_Completed);
56 | eventArgs.RemoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
57 |
58 | int receiveBufferSize = 2048;
59 | var buffer = new byte[receiveBufferSize];
60 | eventArgs.SetBuffer(buffer, 0, buffer.Length);
61 |
62 | m_ListenSocket.ReceiveFromAsync(eventArgs);
63 | }
64 | catch (Exception ex)
65 | {
66 | OnError(ex);
67 |
68 | }
69 | }
70 | public event MessageReceived MessageReceived;
71 | private void eventArgs_Completed(object sender, SocketAsyncEventArgs e)
72 | {
73 | if (e.SocketError != SocketError.Success)
74 | {
75 | var errorCode = (int)e.SocketError;
76 |
77 | //The listen socket was closed
78 | //if (errorCode == 995 || errorCode == 10004 || errorCode == 10038)
79 | //return;
80 | //Logger.Fatal($"The listen socket was closed errorCode:{errorCode}");
81 | Logger.Fatal($"errorCode:{errorCode}");
82 | }
83 |
84 | if (e.LastOperation == SocketAsyncOperation.ReceiveFrom)
85 | {
86 | try
87 | {
88 | //获取接收到的数据
89 | byte[] ByteArray = new byte[e.BytesTransferred];
90 | Array.Copy(e.Buffer, 0, ByteArray, 0, ByteArray.Length);
91 | MessageReceived?.Invoke(ByteArray, (IPEndPoint)e.RemoteEndPoint);
92 | }
93 | catch (Exception exc)
94 | {
95 | OnError(exc);
96 | }
97 |
98 | try
99 | {
100 | m_ListenSocket.ReceiveFromAsync(e);
101 | }
102 | catch (Exception exc)
103 | {
104 | OnError(exc);
105 | }
106 | }
107 | }
108 |
109 |
110 | private void OnError(Exception ex)
111 | {
112 | Logger.Fatal(ex.Message + ex.StackTrace);
113 | //throw ex;
114 | }
115 |
116 | public void Stop()
117 | {
118 | if (m_ListenSocket == null)
119 | return;
120 |
121 | lock (this)
122 | {
123 | if (m_ListenSocket == null)
124 | return;
125 |
126 | m_ReceiveSAE.Completed -= new EventHandler(eventArgs_Completed);
127 | m_ReceiveSAE.Dispose();
128 | m_ReceiveSAE = null;
129 |
130 | //if (!Platform.IsMono)
131 | {
132 | try
133 | {
134 | m_ListenSocket.Shutdown(SocketShutdown.Both);
135 | }
136 | catch { }
137 | }
138 |
139 | try
140 | {
141 | m_ListenSocket.Close();
142 | }
143 | catch { }
144 | finally
145 | {
146 | m_ListenSocket = null;
147 | }
148 | }
149 |
150 | }
151 |
152 |
153 | public void Send(byte[] buffer, IPEndPoint endpoint)
154 | {
155 | try
156 | {
157 | if (endpoint.Address != IPAddress.Any)
158 | {
159 | var len = m_ListenSocket.SendTo(buffer, endpoint);
160 | //Logger.Warn($"Send :{len} {buffer.Length} {endpoint}");
161 | }
162 | else
163 | {
164 | Logger.Fatal($"Send Not Work {endpoint.ToString()}");
165 | }
166 | }
167 | catch (Exception ex)
168 | {
169 | OnError(ex);
170 | }
171 | }
172 |
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/Spider/Log/Logger.cs:
--------------------------------------------------------------------------------
1 | using NLog;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 |
7 | namespace Spider.Log
8 | {
9 | public class Logger
10 | {
11 | private static ILogger logger = LogManager.GetCurrentClassLogger();
12 |
13 | public static void Error(string msg)
14 | {
15 | logger.Error(msg);
16 | }
17 |
18 | public static void Info(string msg)
19 | {
20 | logger.Info(msg);
21 | }
22 |
23 | public static void Fatal(string msg)
24 | {
25 | logger.Fatal(msg);
26 | }
27 |
28 | public static void Debug(string msg)
29 | {
30 | logger.Debug(msg);
31 | }
32 |
33 | public static void Trace(string msg)
34 | {
35 | logger.Trace(msg);
36 | }
37 |
38 | public static void Warn(string msg)
39 | {
40 | logger.Warn(msg);
41 | }
42 |
43 |
44 |
45 | public static void ConsoleWrite(string msg, ConsoleColor consoleColor = ConsoleColor.Green)
46 | {
47 | Console.ForegroundColor = consoleColor;
48 | Console.WriteLine("------------------------------------------------------");
49 | Console.WriteLine($"[{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}]{msg}");
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Spider/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的一般信息由以下
6 | // 控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle("Spider")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Microsoft")]
12 | [assembly: AssemblyProduct("Spider")]
13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2017")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // 将 ComVisible 设置为 false 会使此程序集中的类型
18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
19 | //请将此类型的 ComVisible 特性设置为 true。
20 | [assembly: ComVisible(false)]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid("e0279ef8-1f47-4cb2-983e-736c375d73c5")]
24 |
25 | // 程序集的版本信息由下列四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 生成号
30 | // 修订号
31 | //
32 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
33 | //通过使用 "*",如下所示:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Spider/Queue/DefaultQueue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Net;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using Tancoder.Torrent;
9 |
10 | namespace Spider.Queue
11 | {
12 | public class DefaultQueue : IQueue
13 | {
14 | public ConcurrentQueue> _queue = null;
15 | public DefaultQueue()
16 | {
17 | _queue = new ConcurrentQueue>();
18 | }
19 |
20 | public KeyValuePair Dequeue()
21 | {
22 | var item = new KeyValuePair();
23 | _queue.TryDequeue(out item);
24 | return item;
25 | }
26 |
27 | public void Enqueue(KeyValuePair item)
28 | {
29 | _queue.Enqueue(item);
30 | }
31 |
32 | public int Count()
33 | {
34 | return _queue.Count;
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Spider/Queue/IQueue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Net;
5 | using System.Text;
6 | using Tancoder.Torrent;
7 |
8 | namespace Spider.Queue
9 | {
10 | public interface IQueue
11 | {
12 | void Enqueue(KeyValuePair item);
13 |
14 | KeyValuePair Dequeue();
15 |
16 | int Count();
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Spider/Queue/RedisQueue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Net;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using Tancoder.Torrent;
8 |
9 | namespace Spider.Queue
10 | {
11 | public class RedisQueue : IQueue
12 | {
13 | //TODO
14 | public RedisQueue()
15 | {
16 | }
17 | public KeyValuePair Dequeue()
18 | {
19 | throw new NotImplementedException();
20 | }
21 |
22 | public void Enqueue(KeyValuePair item)
23 | {
24 | throw new NotImplementedException();
25 | }
26 |
27 | public int Count()
28 | {
29 | return 0;
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Spider/Spider.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {E0279EF8-1F47-4CB2-983E-736C375D73C5}
8 | Library
9 | Properties
10 | Spider
11 | Spider
12 | v4.5.2
13 | 512
14 |
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 | false
25 |
26 |
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 | false
34 |
35 |
36 |
37 | ..\packages\Autofac.4.6.0\lib\net45\Autofac.dll
38 |
39 |
40 | ..\packages\NLog.4.4.11\lib\net45\NLog.dll
41 |
42 |
43 | ..\packages\StackExchange.Redis.1.2.4\lib\net45\StackExchange.Redis.dll
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | {b3fdea8e-20f3-4be3-b73a-505b45ba9501}
78 | Tancoder.Torrent
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/Spider/SpiderConfiguration.cs:
--------------------------------------------------------------------------------
1 | using Autofac;
2 | using Spider.Cache;
3 | using Spider.Core;
4 | using Spider.Log;
5 | using Spider.Queue;
6 | using Spider.Store;
7 | using System;
8 | using System.Collections.Generic;
9 | using System.IO;
10 | using System.Linq;
11 | using System.Net;
12 | using System.Text;
13 | using System.Threading;
14 | using System.Threading.Tasks;
15 | using Tancoder.Torrent;
16 | using Tancoder.Torrent.BEncoding;
17 | using Tancoder.Torrent.Client;
18 |
19 | namespace Spider
20 | {
21 | public class SpiderConfiguration
22 | {
23 | private readonly ContainerBuilder _builder;
24 | private IContainer _container;
25 |
26 | private static readonly object obj = new object();
27 | private static SpiderConfiguration _instance = null;
28 |
29 | public SpiderSetting _option { get; set; }
30 | public ICache _cache { get; set; }
31 | public IQueue _queue { get; set; }
32 | public IStore _store { get; set; }
33 |
34 | private SpiderConfiguration(SpiderSetting option)
35 | {
36 | _option = option;
37 | _builder = new ContainerBuilder();
38 |
39 | if (_option.IsSaveTorrent)
40 | {
41 | if (string.IsNullOrEmpty(_option.TorrentSavePath) || !Directory.Exists(_option.TorrentSavePath))
42 | {
43 | _option.TorrentSavePath = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "torrent");
44 | Directory.CreateDirectory(_option.TorrentSavePath);
45 | }
46 | }
47 | }
48 |
49 | public static SpiderConfiguration Create(SpiderSetting option = null)
50 | {
51 | if (_instance == null)
52 | {
53 | lock (obj)
54 | {
55 | if (_instance == null)
56 | {
57 | _instance = new SpiderConfiguration(option ?? new SpiderSetting());
58 | }
59 | }
60 | }
61 | return _instance;
62 | }
63 |
64 | public SpiderConfiguration UseDefaultCache()
65 | {
66 | _builder.RegisterType().As().Named("Cache").SingleInstance();
67 | return _instance;
68 | }
69 |
70 | public SpiderConfiguration UseRedisCache()
71 | {
72 | _builder.RegisterType().As().Named("Cache").SingleInstance();
73 | return _instance;
74 | }
75 |
76 | public SpiderConfiguration UseDefaultQueue()
77 | {
78 | _builder.RegisterType().As().Named("Queue").SingleInstance();
79 | return _instance;
80 | }
81 |
82 | public SpiderConfiguration UseRedisQueue()
83 | {
84 | _builder.RegisterType().As().Named("Queue").SingleInstance();
85 | return _instance;
86 | }
87 |
88 | public SpiderConfiguration UseElasticSearchStore()
89 | {
90 | _builder.RegisterType().As().Named("Store").SingleInstance();
91 | return _instance;
92 | }
93 |
94 | public SpiderConfiguration UseMongoDBStore()
95 | {
96 | _builder.RegisterType().As().Named("Store").SingleInstance();
97 | return _instance;
98 | }
99 |
100 | public void Stop()
101 | {
102 | //TODO
103 | }
104 |
105 | public SpiderConfiguration Start()
106 | {
107 | _container = _builder.Build();
108 | if (!_container.IsRegisteredWithName("Cache"))
109 | {
110 | throw new Exception("没有注册Cache");
111 | }
112 | if (!_container.IsRegisteredWithName("Queue"))
113 | {
114 | throw new Exception("没有注册Queue");
115 | }
116 | //if (!_container.IsRegisteredWithName("Store"))
117 | //{
118 | // throw new Exception("没有注册Store");
119 | //}
120 |
121 | _queue = _container.ResolveNamed("Queue");
122 | _cache = _container.ResolveNamed("Cache");
123 | //_store = _container.ResolveNamed("Store");
124 |
125 |
126 | for (var i = 0; i < _option.MaxSpiderThreadCount; i++)
127 | {
128 | var port = _option.LocalPort + i;
129 | Logger.ConsoleWrite($"线程:{i + 1} 端口:{port} 已启动监听...");
130 | Task.Run(() =>
131 | {
132 | var spider = new DHTSpider(new IPEndPoint(IPAddress.Parse("0.0.0.0"), port), _queue);
133 | spider.NewMetadata += DHTSpider_NewMetadata;
134 | spider.Start();
135 | });
136 | Thread.Sleep(1000);
137 | }
138 |
139 | for (var i = 0; i < _option.MaxDownLoadThreadCount; i++)
140 | {
141 | var id = i + 1;
142 | Logger.ConsoleWrite($"线程[{id}]开始下载");
143 | Task.Run(() =>
144 | {
145 | Download(id);
146 | });
147 | Thread.Sleep(100);
148 | }
149 |
150 |
151 | return _instance;
152 | }
153 |
154 |
155 |
156 | private void DHTSpider_NewMetadata(object sender, NewMetadataEventArgs e)
157 | {
158 | var hash = e.Metadata.ToString();
159 | lock (obj)
160 | {
161 | if (!_cache.ContainsKey(hash))
162 | {
163 | _cache.Set(hash, e.Owner);
164 | _queue.Enqueue(new KeyValuePair(e.Metadata, e.Owner));
165 | Logger.ConsoleWrite($"NewMetadata Hash:{e.Metadata} Address:{e.Owner.ToString()}");
166 | }
167 | }
168 |
169 | }
170 |
171 | private void Download(int threadId)
172 | {
173 | while (true)
174 | {
175 | try
176 | {
177 | var info = new KeyValuePair();
178 | lock (this)
179 | {
180 | info = _queue.Dequeue();
181 | }
182 | if (info.Key == null || info.Value == null)
183 | {
184 | Thread.Sleep(1000);
185 | continue;
186 | }
187 | var hash = BitConverter.ToString(info.Key.Hash).Replace("-", "");
188 | using (WireClient client = new WireClient(info.Value))
189 | {
190 | var metadata = client.GetMetaData(info.Key);
191 | if (metadata != null)
192 | {
193 | var name = ((BEncodedString)metadata["name"]).Text;
194 | if (_option.IsSaveTorrent)
195 | {
196 | var filepath = $"{_option.TorrentSavePath}\\{hash}.torrent";
197 | File.WriteAllBytes(filepath, metadata.Encode());
198 | }
199 | Logger.ConsoleWrite($"线程[{threadId}]下载完成 Name:{name} ", ConsoleColor.Yellow);
200 | }
201 |
202 | }
203 |
204 | }
205 | catch (Exception ex)
206 | {
207 | //Logger.Error($"Download {ex.Message}");
208 | }
209 | finally
210 | {
211 | Thread.Sleep(1000);
212 | }
213 | }
214 | }
215 | }
216 | }
217 |
--------------------------------------------------------------------------------
/Spider/SpiderSetting.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace Spider
9 | {
10 | public class SpiderSetting
11 | {
12 | public int LocalPort { get; set; }
13 |
14 | public bool IsSaveTorrent { get; set; }
15 |
16 | public string TorrentSavePath { get; set; }
17 |
18 | public int MaxDownLoadThreadCount { get; set; }
19 |
20 | public int MaxSpiderThreadCount { get; set; }
21 |
22 | public SpiderSetting(int localPort = 6881, bool isSaveTorrent = false, string torrentSavePath = "", int maxDownLoadThreadCount = 10, int maxSpiderThreadCount = 1)
23 | {
24 | LocalPort = localPort;
25 | IsSaveTorrent = isSaveTorrent;
26 | TorrentSavePath = torrentSavePath;
27 | MaxDownLoadThreadCount = maxDownLoadThreadCount;
28 | MaxSpiderThreadCount = maxSpiderThreadCount;
29 | }
30 |
31 |
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Spider/Store/ElasticSearchStore.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Spider.Store
8 | {
9 | public class ElasticSearchStore : IStore
10 | {
11 | //TODO
12 | public bool Insert(object obj)
13 | {
14 | throw new NotImplementedException();
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Spider/Store/IStore.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace Spider.Store
7 | {
8 | public interface IStore
9 | {
10 | bool Insert(object obj);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Spider/Store/MongoDBStore.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Spider.Store
8 | {
9 | public class MongoDBStore : IStore
10 | {
11 | //TODO
12 | public bool Insert(object obj)
13 | {
14 | throw new NotImplementedException();
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Spider/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Tancoder.Torrent/ClassDiagram.cd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAA=
7 | ISpider.cs
8 |
9 |
10 |
11 |
12 |
13 | AAAAAAAAAAAAAAAAAAAAAgQAAAAAAAAAAAAAAAAAAAA=
14 | Metadata.cs
15 |
16 |
17 |
18 |
19 |
20 | AAAAAAAAAAAAAAAAACAAAAAAABCAAAAAAAAAAAAAAAA=
21 | ISpider.cs
22 |
23 |
24 |
25 |
26 |
27 | AAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
28 | IMetaDataFilter.cs
29 |
30 |
31 |
32 |
33 |
34 | AAAAAAAAAAAAAAAAAAAAAAAQAAAAAgAAAAAAAAAAAAA=
35 | ISpider.cs
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/Tancoder.Torrent/EventArgs/NodeAddedEventArgs.cs:
--------------------------------------------------------------------------------
1 | #if !DISABLE_DHT
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Text;
5 |
6 | namespace Tancoder.Torrent.Dht
7 | {
8 | public class NodeAddedEventArgs : EventArgs
9 | {
10 | private Node node;
11 |
12 | public Node Node
13 | {
14 | get { return node; }
15 | }
16 |
17 | public NodeAddedEventArgs(Node node)
18 | {
19 | this.node = node;
20 | }
21 | }
22 | }
23 | #endif
--------------------------------------------------------------------------------
/Tancoder.Torrent/EventArgs/NodeFoundEventArgs.cs:
--------------------------------------------------------------------------------
1 | #if !DISABLE_DHT
2 | // NodeFound.cs.cs
3 | //
4 | // Authors:
5 | // Olivier Dufour
6 | //
7 | // Copyright (C) 2008 Olivier Dufour
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining
10 | // a copy of this software and associated documentation files (the
11 | // "Software"), to deal in the Software without restriction, including
12 | // without limitation the rights to use, copy, modify, merge, publish,
13 | // distribute, sublicense, and/or sell copies of the Software, and to
14 | // permit persons to whom the Software is furnished to do so, subject to
15 | // the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be
18 | // included in all copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 | //
28 | //
29 |
30 | using System;
31 | using System.IO;
32 | using System.Security.Cryptography;
33 | using System.Collections.Generic;
34 |
35 | using Tancoder.Torrent.BEncoding;
36 |
37 | namespace Tancoder.Torrent.Dht
38 | {
39 | public class NodeFoundEventArgs : EventArgs
40 | {
41 | private Node node;
42 |
43 | public NodeFoundEventArgs(Node node)
44 | {
45 | this.node = node;
46 | }
47 |
48 | public Node Node
49 | {
50 | get { return node; }
51 | }
52 | }
53 | }
54 | #endif
--------------------------------------------------------------------------------
/Tancoder.Torrent/EventArgs/StateUpdateEventArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 |
4 | namespace Tancoder.Torrent.Client
5 | {
6 | public class StatsUpdateEventArgs : EventArgs
7 | {
8 | public StatsUpdateEventArgs()
9 | {
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Tancoder.Torrent/Exceptions/ChangeLog:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhangkong828/DHTSpider/49f0055c78ed718bcda77e0466f25c277af9577a/Tancoder.Torrent/Exceptions/ChangeLog
--------------------------------------------------------------------------------
/Tancoder.Torrent/Exceptions/ConnectionException.cs:
--------------------------------------------------------------------------------
1 | //
2 | // ConnectionException.cs
3 | //
4 | // Authors:
5 | // Alan McGovern alan.mcgovern@gmail.com
6 | //
7 | // Copyright (C) 2006 Alan McGovern
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining
10 | // a copy of this software and associated documentation files (the
11 | // "Software"), to deal in the Software without restriction, including
12 | // without limitation the rights to use, copy, modify, merge, publish,
13 | // distribute, sublicense, and/or sell copies of the Software, and to
14 | // permit persons to whom the Software is furnished to do so, subject to
15 | // the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be
18 | // included in all copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 | //
28 |
29 |
30 | using System;
31 | using System.Text;
32 | using Tancoder.Torrent.Common;
33 |
34 | namespace Tancoder.Torrent.Client
35 | {
36 | ///
37 | ///
38 | ///
39 | public class ConnectionException : TorrentException
40 | {
41 | ///
42 | ///
43 | ///
44 | public ConnectionException()
45 | : base()
46 | {
47 | }
48 |
49 |
50 | ///
51 | ///
52 | ///
53 | ///
54 | public ConnectionException(string message)
55 | : base(message)
56 | {
57 | }
58 |
59 |
60 | ///
61 | ///
62 | ///
63 | ///
64 | ///
65 | public ConnectionException(string message, Exception innerException)
66 | : base(message, innerException)
67 | {
68 | }
69 |
70 |
71 | ///
72 | ///
73 | ///
74 | ///
75 | ///
76 | public ConnectionException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
77 | : base(info, context)
78 | {
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/Tancoder.Torrent/Exceptions/ListenerException.cs:
--------------------------------------------------------------------------------
1 | //
2 | // ListenerException.cs
3 | //
4 | // Authors:
5 | // Alan McGovern alan.mcgovern@gmail.com
6 | //
7 | // Copyright (C) 2006 Alan McGovern
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining
10 | // a copy of this software and associated documentation files (the
11 | // "Software"), to deal in the Software without restriction, including
12 | // without limitation the rights to use, copy, modify, merge, publish,
13 | // distribute, sublicense, and/or sell copies of the Software, and to
14 | // permit persons to whom the Software is furnished to do so, subject to
15 | // the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be
18 | // included in all copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 | //
28 |
29 |
30 | using System;
31 | using System.Text;
32 | using Tancoder.Torrent.Common;
33 |
34 | namespace Tancoder.Torrent.Client
35 | {
36 | ///
37 | ///
38 | ///
39 | public class ListenerException : TorrentException
40 | {
41 | ///
42 | ///
43 | ///
44 | public ListenerException()
45 | : base()
46 | {
47 | }
48 |
49 |
50 | ///
51 | ///
52 | ///
53 | ///
54 | public ListenerException(string message)
55 | : base(message)
56 | {
57 | }
58 |
59 |
60 | ///
61 | ///
62 | ///
63 | ///
64 | ///
65 | public ListenerException(string message, Exception innerException)
66 | : base(message, innerException)
67 | {
68 | }
69 |
70 |
71 | ///
72 | ///
73 | ///
74 | ///
75 | ///
76 | public ListenerException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
77 | : base(info, context)
78 | {
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/Tancoder.Torrent/Exceptions/MessageException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using Tancoder.Torrent.Common;
4 |
5 | namespace Tancoder.Torrent.Client
6 | {
7 | public class MessageException : TorrentException
8 | {
9 | public MessageException()
10 | : base()
11 | {
12 | }
13 |
14 |
15 | public MessageException(string message)
16 | : base(message)
17 | {
18 | }
19 |
20 |
21 | public MessageException(string message, Exception innerException)
22 | : base(message, innerException)
23 | {
24 | }
25 |
26 |
27 | public MessageException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
28 | : base(info, context)
29 | {
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Tancoder.Torrent/Exceptions/ProtocolException.cs:
--------------------------------------------------------------------------------
1 | //
2 | // ProtocolException.cs
3 | //
4 | // Authors:
5 | // Alan McGovern alan.mcgovern@gmail.com
6 | //
7 | // Copyright (C) 2006 Alan McGovern
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining
10 | // a copy of this software and associated documentation files (the
11 | // "Software"), to deal in the Software without restriction, including
12 | // without limitation the rights to use, copy, modify, merge, publish,
13 | // distribute, sublicense, and/or sell copies of the Software, and to
14 | // permit persons to whom the Software is furnished to do so, subject to
15 | // the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be
18 | // included in all copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 | //
28 |
29 |
30 | using System;
31 | using System.Text;
32 | using Tancoder.Torrent.Common;
33 |
34 | namespace Tancoder.Torrent.Client
35 | {
36 | public class ProtocolException : TorrentException
37 | {
38 | public ProtocolException()
39 | :base()
40 | {
41 | }
42 |
43 |
44 | public ProtocolException(string message)
45 | : base(message)
46 | {
47 | }
48 |
49 |
50 | public ProtocolException(string message, Exception innerException)
51 | : base(message, innerException)
52 | {
53 | }
54 |
55 |
56 | public ProtocolException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
57 | : base(info, context)
58 | {
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/Tancoder.Torrent/Exceptions/TorrentLoadException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using Tancoder.Torrent.Common;
4 |
5 | namespace Tancoder.Torrent.Client
6 | {
7 | public class TorrentLoadException : TorrentException
8 | {
9 |
10 | public TorrentLoadException()
11 | : base()
12 | {
13 | }
14 |
15 |
16 | public TorrentLoadException(string message)
17 | : base(message)
18 | {
19 | }
20 |
21 |
22 | public TorrentLoadException(string message, Exception innerException)
23 | : base(message, innerException)
24 | {
25 | }
26 |
27 |
28 | public TorrentLoadException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
29 | : base(info, context)
30 | {
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/Tancoder.Torrent/FindPeersResult.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Tancoder.Torrent.Dht;
3 |
4 | namespace Tancoder.Torrent
5 | {
6 | public class FindPeersResult
7 | {
8 | public bool Found { get; set; }
9 | public IList Nodes { get; set; }
10 | }
11 | }
--------------------------------------------------------------------------------
/Tancoder.Torrent/GetPeersResult.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Tancoder.Torrent.BEncoding;
3 | using Tancoder.Torrent.Dht;
4 |
5 | namespace Tancoder.Torrent
6 | {
7 | public class GetPeersResult
8 | {
9 | public bool HasHash { get; set; }
10 | public IList Values { get; set; }
11 | public IList Nodes { get; set; }
12 | }
13 | }
--------------------------------------------------------------------------------
/Tancoder.Torrent/IDhtEngine.cs:
--------------------------------------------------------------------------------
1 | //
2 | // IDhtEngine.cs
3 | //
4 | // Authors:
5 | // Alan McGovern alan.mcgovern@gmail.com
6 | //
7 | // Copyright (C) 2009 Alan McGovern
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining
10 | // a copy of this software and associated documentation files (the
11 | // "Software"), to deal in the Software without restriction, including
12 | // without limitation the rights to use, copy, modify, merge, publish,
13 | // distribute, sublicense, and/or sell copies of the Software, and to
14 | // permit persons to whom the Software is furnished to do so, subject to
15 | // the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be
18 | // included in all copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 | //
28 |
29 |
30 | using System;
31 | using System.Collections.Generic;
32 | using System.Net;
33 | using Tancoder.Torrent.BEncoding;
34 | using Tancoder.Torrent.Dht;
35 | using Tancoder.Torrent.Dht.Messages;
36 |
37 | namespace Tancoder.Torrent
38 | {
39 | public enum ErrorCode : int
40 | {
41 | GenericError = 201,
42 | ServerError = 202,
43 | ProtocolError = 203,// malformed packet, invalid arguments, or bad token
44 | MethodUnknown = 204//Method Unknown
45 | }
46 | public interface IDhtEngine : IDisposable
47 | {
48 | //event EventHandler StateChanged;
49 |
50 | bool Disposed { get; }
51 | NodeId LocalId { get; }
52 | //DhtState State { get; }
53 | ITokenManager TokenManager { get; }
54 |
55 | void Add(BEncodedList nodes);
56 | void Add(IEnumerable enumerable);
57 | void Add(Node node);
58 |
59 | //void Announce(InfoHash infohash, int port);
60 | void GetAnnounced(InfoHash infohash, IPEndPoint endpoint);
61 | void GetPeers(InfoHash infohash);
62 |
63 | GetPeersResult QueryGetPeers(NodeId infohash);
64 | FindPeersResult QueryFindNode(NodeId target);
65 |
66 | //byte[] SaveNodes();
67 | void Send(DhtMessage msg, IPEndPoint endpoint);
68 |
69 | void Start();
70 | NodeId GetNeighborId(NodeId target);
71 | void Stop();
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/Tancoder.Torrent/IMetaDataFilter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace Tancoder.Torrent
7 | {
8 | public interface IMetaDataFilter
9 | {
10 | bool Ignore(InfoHash metadata);
11 | }
12 | }
--------------------------------------------------------------------------------
/Tancoder.Torrent/ISpider.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Net;
5 | using System.Text;
6 | using Tancoder.Torrent.Dht;
7 |
8 | namespace Tancoder.Torrent
9 | {
10 | public interface ISpider
11 | {
12 | event NewMetadataEvent NewMetadata;
13 | IMetaDataFilter Filter { get; set; }
14 |
15 | KeyValuePair Pop();
16 | }
17 |
18 | public class NewMetadataEventArgs : EventArgs
19 | {
20 | public InfoHash Metadata { get; private set; }
21 | public IPEndPoint Owner { get; private set; }
22 |
23 | public NewMetadataEventArgs(InfoHash metadata, IPEndPoint endpoint)
24 | {
25 | Metadata = metadata;
26 | Owner = endpoint;
27 | }
28 | }
29 |
30 | public delegate void NewMetadataEvent(object sender, NewMetadataEventArgs e);
31 | }
--------------------------------------------------------------------------------
/Tancoder.Torrent/InfoHash.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using Tancoder.Torrent.Common;
5 | using System.Web;
6 |
7 | namespace Tancoder.Torrent
8 | {
9 | public class InfoHash : IEquatable
10 | {
11 | static Dictionary base32DecodeTable;
12 |
13 | static InfoHash()
14 | {
15 | base32DecodeTable = new Dictionary();
16 | string table = "abcdefghijklmnopqrstuvwxyz234567";
17 | for (int i = 0; i < table.Length; i++)
18 | base32DecodeTable[table[i]] = (byte)i;
19 | }
20 |
21 | byte[] hash;
22 |
23 | public byte[] Hash
24 | {
25 | get { return hash; }
26 | }
27 |
28 | public InfoHash(byte[] infoHash)
29 | {
30 | Check.InfoHash(infoHash);
31 | if (infoHash.Length != 20)
32 | throw new ArgumentException("Infohash must be exactly 20 bytes long");
33 | hash = (byte[])infoHash.Clone();
34 | }
35 |
36 | public override bool Equals(object obj)
37 | {
38 | return Equals(obj as InfoHash);
39 | }
40 |
41 | public bool Equals(byte[] other)
42 | {
43 | return other == null || other.Length != 20 ? false : Toolbox.ByteMatch(Hash, other);
44 | }
45 |
46 | public bool Equals(InfoHash other)
47 | {
48 | return this == other;
49 | }
50 |
51 | public override int GetHashCode()
52 | {
53 | // Equality is based generally on checking 20 positions, checking 4 should be enough
54 | // for the hashcode as infohashes are randomly distributed.
55 | return Hash[0] | (Hash[1] << 8) | (Hash[2] << 16) | (Hash[3] << 24);
56 | }
57 |
58 | public byte[] ToArray()
59 | {
60 | return (byte[])hash.Clone();
61 | }
62 |
63 | public string ToHex()
64 | {
65 | StringBuilder sb = new StringBuilder(40);
66 | for (int i = 0; i < hash.Length; i++)
67 | {
68 | string hex = hash[i].ToString("X");
69 | if (hex.Length != 2)
70 | sb.Append("0");
71 | sb.Append(hex);
72 | }
73 | return sb.ToString();
74 | }
75 |
76 | public override string ToString()
77 | {
78 | return BitConverter.ToString(hash);
79 | }
80 |
81 | public string UrlEncode()
82 | {
83 | return UriHelper.UrlEncode(Hash);
84 | }
85 |
86 | public static bool operator ==(InfoHash left, InfoHash right)
87 | {
88 | if ((object)left == null)
89 | return (object)right == null;
90 | if ((object)right == null)
91 | return false;
92 | return Toolbox.ByteMatch(left.Hash, right.Hash);
93 | }
94 |
95 | public static bool operator !=(InfoHash left, InfoHash right)
96 | {
97 | return !(left == right);
98 | }
99 |
100 | public static InfoHash FromBase32(string infoHash)
101 | {
102 | Check.InfoHash (infoHash);
103 | if (infoHash.Length != 32)
104 | throw new ArgumentException("Infohash must be a base32 encoded 32 character string");
105 |
106 | infoHash = infoHash.ToLower();
107 | int infohashOffset =0 ;
108 | byte[] hash = new byte[20];
109 | var temp = new byte[8];
110 | for (int i = 0; i < hash.Length; ) {
111 | for (int j=0; j < 8; j++)
112 | if (!base32DecodeTable.TryGetValue(infoHash[infohashOffset++], out temp[j]))
113 | throw new ArgumentException ("infoHash", "Value is not a valid base32 encoded string");
114 |
115 | //8 * 5bits = 40 bits = 5 bytes
116 | hash[i++] = (byte)((temp[0] << 3) | (temp [1]>> 2));
117 | hash[i++] = (byte)((temp[1] << 6) | (temp[2] << 1) | (temp[3] >> 4));
118 | hash[i++] = (byte)((temp[3] << 4) | (temp [4]>> 1));
119 | hash[i++] = (byte)((temp[4] << 7) | (temp[5] << 2) | (temp [6]>> 3));
120 | hash[i++] = (byte)((temp[6] << 5) | temp[7]);
121 | }
122 |
123 | return new InfoHash(hash);
124 | }
125 |
126 | public static InfoHash FromHex(string infoHash)
127 | {
128 | Check.InfoHash (infoHash);
129 | if (infoHash.Length != 40)
130 | throw new ArgumentException("Infohash must be 40 characters long");
131 |
132 | byte[] hash = new byte[20];
133 | for (int i = 0; i < hash.Length; i++)
134 | hash[i] = byte.Parse(infoHash.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber);
135 |
136 | return new InfoHash(hash);
137 | }
138 |
139 | public static InfoHash FromMagnetLink(string magnetLink)
140 | {
141 | Check.MagnetLink(magnetLink);
142 | if (!magnetLink.StartsWith("magnet:?"))
143 | throw new ArgumentException("Invalid magnet link format");
144 | magnetLink = magnetLink.Substring("magnet:?".Length);
145 | int hashStart = magnetLink.IndexOf("xt=urn:btih:");
146 | if (hashStart == -1)
147 | throw new ArgumentException("Magnet link does not contain an infohash");
148 | hashStart += "xt=urn:btih:".Length;
149 |
150 | int hashEnd = magnetLink.IndexOf('&', hashStart);
151 | if (hashEnd == -1)
152 | hashEnd = magnetLink.Length;
153 |
154 | switch (hashEnd - hashStart)
155 | {
156 | case 32:
157 | return FromBase32(magnetLink.Substring(hashStart, 32));
158 | case 40:
159 | return FromHex(magnetLink.Substring(hashStart, 40));
160 | default:
161 | throw new ArgumentException("Infohash must be base32 or hex encoded.");
162 | }
163 | }
164 |
165 | public static InfoHash UrlDecode(string infoHash)
166 | {
167 | Check.InfoHash(infoHash);
168 | return new InfoHash(UriHelper.UrlDecode(infoHash));
169 | }
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/Tancoder.Torrent/Listeners/DhtListener.cs:
--------------------------------------------------------------------------------
1 | #if !DISABLE_DHT
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Text;
5 | using Tancoder.Torrent.Client;
6 | using System.Net;
7 | using Tancoder.Torrent.Common;
8 |
9 | namespace Tancoder.Torrent.Dht.Listeners
10 | {
11 | public delegate void MessageReceived(byte[] buffer, IPEndPoint endpoint);
12 |
13 | public class DhtListener : UdpListener
14 | {
15 | public event MessageReceived MessageReceived;
16 |
17 | public DhtListener(IPEndPoint endpoint)
18 | : base(endpoint)
19 | {
20 |
21 | }
22 |
23 | protected override void OnMessageReceived(byte[] buffer, IPEndPoint endpoint)
24 | {
25 | MessageReceived?.Invoke(buffer, endpoint);
26 | }
27 | }
28 | }
29 | #endif
--------------------------------------------------------------------------------
/Tancoder.Torrent/Listeners/Listener.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Listener.cs
3 | //
4 | // Authors:
5 | // Alan McGovern alan.mcgovern@gmail.com
6 | //
7 | // Copyright (C) 2008 Alan McGovern
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining
10 | // a copy of this software and associated documentation files (the
11 | // "Software"), to deal in the Software without restriction, including
12 | // without limitation the rights to use, copy, modify, merge, publish,
13 | // distribute, sublicense, and/or sell copies of the Software, and to
14 | // permit persons to whom the Software is furnished to do so, subject to
15 | // the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be
18 | // included in all copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 | //
28 |
29 | using System;
30 | using System.Collections.Generic;
31 | using System.Text;
32 | using System.Net.Sockets;
33 | using System.Net;
34 | using Tancoder.Torrent.Common;
35 |
36 | namespace Tancoder.Torrent.Client
37 | {
38 | public abstract class Listener
39 | {
40 | public event EventHandler StatusChanged;
41 |
42 | private IPEndPoint endpoint;
43 | private ListenerStatus status;
44 |
45 | public IPEndPoint Endpoint
46 | {
47 | get { return endpoint; }
48 | }
49 |
50 | public ListenerStatus Status
51 | {
52 | get { return status; }
53 | }
54 |
55 |
56 | protected Listener(IPEndPoint endpoint)
57 | {
58 | this.status = ListenerStatus.NotListening;
59 | this.endpoint = endpoint;
60 | }
61 |
62 | public void ChangeEndpoint(IPEndPoint endpoint)
63 | {
64 | this.endpoint = endpoint;
65 | if (Status == ListenerStatus.Listening)
66 | {
67 | Stop();
68 | Start();
69 | }
70 | }
71 |
72 | protected virtual void RaiseStatusChanged(ListenerStatus status)
73 | {
74 | this.status = status;
75 | if (StatusChanged != null)
76 | Toolbox.RaiseAsyncEvent(StatusChanged, this, EventArgs.Empty);
77 | }
78 |
79 | public abstract void Start();
80 |
81 | public abstract void Stop();
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/Tancoder.Torrent/Listeners/UdpListener.cs:
--------------------------------------------------------------------------------
1 | #if !DISABLE_DHT
2 | //
3 | // UdpListener.cs
4 | //
5 | // Authors:
6 | // Alan McGovern
7 | //
8 | // Copyright (C) 2008 Alan McGovern
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining
11 | // a copy of this software and associated documentation files (the
12 | // "Software"), to deal in the Software without restriction, including
13 | // without limitation the rights to use, copy, modify, merge, publish,
14 | // distribute, sublicense, and/or sell copies of the Software, and to
15 | // permit persons to whom the Software is furnished to do so, subject to
16 | // the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be
19 | // included in all copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 | //
29 |
30 |
31 | using System;
32 | using System.Collections.Generic;
33 | using System.Text;
34 | using System.Net.Sockets;
35 | using System.Net;
36 | using Tancoder.Torrent.BEncoding;
37 | using Tancoder.Torrent.Client;
38 | using Tancoder.Torrent.Common;
39 | using System.Diagnostics;
40 |
41 | namespace Tancoder.Torrent
42 | {
43 | public abstract class UdpListener : Listener
44 | {
45 |
46 | private UdpClient client;
47 |
48 | protected UdpListener(IPEndPoint endpoint)
49 | : base(endpoint)
50 | {
51 |
52 | }
53 |
54 | private void EndReceive(IAsyncResult result)
55 | {
56 | try
57 | {
58 | IPEndPoint e = new IPEndPoint(IPAddress.Any, Endpoint.Port);
59 | byte[] buffer = client.EndReceive(result, ref e);
60 |
61 | OnMessageReceived(buffer, e);
62 | client.BeginReceive(EndReceive, null);
63 | }
64 | //catch (ObjectDisposedException ex)
65 | //{
66 | // // Ignore, we're finished!
67 | // throw new Exception($"UdpListener ObjectDisposedException: {ex}");
68 | //}
69 | catch (SocketException ex)
70 | {
71 | // If the destination computer closes the connection
72 | // we get error code 10054. We need to keep receiving on
73 | // the socket until we clear all the error states
74 | //if (ex.ErrorCode == 10054)
75 | //{
76 | // while (true)
77 | // {
78 | // try
79 | // {
80 | // client.BeginReceive(EndReceive, null);
81 | // return;
82 | // }
83 | // //catch (ObjectDisposedException oe)
84 | // //{
85 | // // throw new Exception($"UdpListener ObjectDisposedException: {oe}");
86 | // //}
87 | // catch (SocketException e)
88 | // {
89 | // throw new Exception($"UdpListener SocketException: {e}");
90 | // //if (e.ErrorCode != 10054)
91 | // // return;
92 | // }
93 | // }
94 | //}
95 | ////else if (ex.ErrorCode == 10052)
96 | ////{
97 |
98 | ////}
99 | //else
100 | //{
101 | // throw new Exception($"UdpListener SocketException: {ex}");
102 | //}
103 | client.BeginReceive(EndReceive, null);
104 | }
105 | catch (Exception ex)
106 | {
107 | throw new Exception($"UdpListener SocketException: {ex}");
108 | }
109 | }
110 |
111 | protected abstract void OnMessageReceived(byte[] buffer, IPEndPoint endpoint);
112 |
113 | public virtual void Send(byte[] buffer, IPEndPoint endpoint)
114 | {
115 | try
116 | {
117 | if (endpoint.Address != IPAddress.Any)
118 | client.Send(buffer, buffer.Length, endpoint);
119 | }
120 | catch (Exception ex)
121 | {
122 | throw new Exception($"UdpListener could not send message: {ex}");
123 | }
124 | }
125 |
126 | public override void Start()
127 | {
128 | try
129 | {
130 | client = new UdpClient(Endpoint);
131 | {
132 | const uint IOC_IN = 0x80000000;
133 | int IOC_VENDOR = 0x18000000;
134 | int SIO_UDP_CONNRESET = (int)(IOC_IN | IOC_VENDOR | 12);
135 | client.Client.IOControl((int)SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, new byte[4]);
136 | }
137 | client.BeginReceive(EndReceive, null);
138 | RaiseStatusChanged(ListenerStatus.Listening);
139 | }
140 | catch (SocketException)
141 | {
142 | RaiseStatusChanged(ListenerStatus.PortNotFree);
143 | }
144 | catch (ObjectDisposedException)
145 | {
146 | // Do Nothing
147 | }
148 | }
149 |
150 | public override void Stop()
151 | {
152 | try
153 | {
154 | client.Close();
155 | }
156 | catch
157 | {
158 | // FIXME: Not needed
159 | }
160 | }
161 | }
162 | }
163 | #endif
--------------------------------------------------------------------------------
/Tancoder.Torrent/MessageException.cs:
--------------------------------------------------------------------------------
1 | #if !DISABLE_DHT
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Text;
5 |
6 | namespace Tancoder.Torrent.Dht
7 | {
8 | public class MessageException : Exception
9 | {
10 | private ErrorCode errorCode;
11 |
12 | public ErrorCode ErrorCode
13 | {
14 | get { return errorCode; }
15 | }
16 |
17 | public MessageException(ErrorCode errorCode, string message) : base(message)
18 | {
19 | this.errorCode = errorCode;
20 | }
21 | }
22 | }
23 | #endif
--------------------------------------------------------------------------------
/Tancoder.Torrent/MessageFactory.cs:
--------------------------------------------------------------------------------
1 | #if !DISABLE_DHT
2 | //
3 | // MessageFactory.cs
4 | //
5 | // Authors:
6 | // Alan McGovern
7 | //
8 | // Copyright (C) 2008 Alan McGovern
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining
11 | // a copy of this software and associated documentation files (the
12 | // "Software"), to deal in the Software without restriction, including
13 | // without limitation the rights to use, copy, modify, merge, publish,
14 | // distribute, sublicense, and/or sell copies of the Software, and to
15 | // permit persons to whom the Software is furnished to do so, subject to
16 | // the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be
19 | // included in all copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 | //
29 |
30 |
31 | using System;
32 | using System.Collections.Generic;
33 | using System.Text;
34 |
35 | using Tancoder.Torrent.BEncoding;
36 |
37 | namespace Tancoder.Torrent.Dht.Messages
38 | {
39 | public delegate DhtMessage Creator(BEncodedDictionary dictionary);
40 | public delegate DhtMessage ResponseCreator(BEncodedDictionary dictionary, QueryMessage message);
41 |
42 | public static class MessageFactory
43 | {
44 | private static readonly string QueryNameKey = "q";
45 | private static BEncodedString MessageTypeKey = "y";
46 | private static BEncodedString TransactionIdKey = "t";
47 |
48 | public static int RegisteredMessages
49 | {
50 | get { return messages.Count; }
51 | }
52 |
53 | static MessageFactory()
54 | {
55 | queryDecoders.Add("announce_peer", delegate(BEncodedDictionary d) { return new AnnouncePeer(d); });
56 | queryDecoders.Add("find_node", delegate(BEncodedDictionary d) { return new FindNode(d); });
57 | queryDecoders.Add("get_peers", delegate(BEncodedDictionary d) { return new GetPeers(d); });
58 | queryDecoders.Add("ping", delegate(BEncodedDictionary d) { return new Ping(d); });
59 | }
60 |
61 | private static Dictionary messages = new Dictionary();
62 | private static Dictionary queryDecoders = new Dictionary();
63 |
64 | public static bool IsRegistered(BEncodedValue transactionId)
65 | {
66 | lock (messages)
67 | {
68 | return messages.ContainsKey(transactionId);
69 | }
70 | }
71 |
72 | public static void RegisterSend(QueryMessage message)
73 | {
74 | lock(messages)
75 | {
76 | messages.Add(message.TransactionId, message);
77 | }
78 | }
79 |
80 | public static bool UnregisterSend(QueryMessage message)
81 | {
82 | lock (messages)
83 | {
84 | return messages.Remove(message.TransactionId);
85 | }
86 | }
87 |
88 | public static DhtMessage DecodeMessage(BEncodedDictionary dictionary)
89 | {
90 | DhtMessage message;
91 | string error;
92 |
93 | if (!TryDecodeMessage(dictionary, out message, out error))
94 | throw new MessageException(ErrorCode.GenericError, error);
95 |
96 | return message;
97 | }
98 |
99 | public static bool TryDecodeMessage(BEncodedDictionary dictionary, out DhtMessage message)
100 | {
101 | string error;
102 | return TryDecodeMessage(dictionary, out message, out error);
103 | }
104 |
105 | public static bool TryDecodeMessage(BEncodedDictionary dictionary, out DhtMessage message, out string error)
106 | {
107 | message = null;
108 | error = null;
109 |
110 | if (dictionary[MessageTypeKey].Equals(QueryMessage.QueryType))
111 | {
112 | if (!queryDecoders.ContainsKey((BEncodedString)dictionary[QueryNameKey]))
113 | {
114 | error = ((BEncodedString)dictionary[QueryNameKey]).Text;
115 | return false;
116 | }
117 | message = queryDecoders[(BEncodedString)dictionary[QueryNameKey]](dictionary);
118 | }
119 | else if (dictionary[MessageTypeKey].Equals(ErrorMessage.ErrorType))
120 | {
121 | message = new ErrorMessage(dictionary);
122 | }
123 | else
124 | {
125 | QueryMessage query;
126 | BEncodedString key = (BEncodedString)dictionary[TransactionIdKey];
127 | if (messages.TryGetValue(key, out query))
128 | {
129 | messages.Remove(key);
130 | try
131 | {
132 | message = query.ResponseCreator(dictionary, query);
133 | }
134 | catch
135 | {
136 | error = "Response dictionary was invalid";
137 | }
138 | }
139 | else
140 | {
141 | error = "Response had bad transaction ID";
142 | }
143 | }
144 |
145 | return error == null && message != null;
146 | }
147 | public static bool TryNoTraceDecodeMessage(BEncodedDictionary dictionary, out DhtMessage message, out string error)
148 | {
149 | message = null;
150 | error = null;
151 |
152 | if (dictionary[MessageTypeKey].Equals(QueryMessage.QueryType))
153 | {
154 | if (!queryDecoders.ContainsKey((BEncodedString)dictionary[QueryNameKey]))
155 | {
156 | error = ((BEncodedString)dictionary[QueryNameKey]).Text;
157 | return false;
158 | }
159 | message = queryDecoders[(BEncodedString)dictionary[QueryNameKey]](dictionary);
160 | }
161 | else if (dictionary[MessageTypeKey].Equals(ErrorMessage.ErrorType))
162 | {
163 | message = new ErrorMessage(dictionary);
164 | }
165 | else
166 | {
167 | QueryMessage query = new NoTraceMessage();
168 | BEncodedString key = (BEncodedString)dictionary[TransactionIdKey];
169 | try
170 | {
171 | message = query.ResponseCreator(dictionary, query);
172 |
173 | //BEncodedValue q;
174 | //if (message == null && dictionary.TryGetValue("q", out q))
175 | //{
176 | // error = q.ToString();
177 | //}
178 | if (message == null && dictionary.ContainsKey("q"))
179 | {
180 | dictionary[MessageTypeKey] = QueryMessage.QueryType;
181 | TryNoTraceDecodeMessage(dictionary, out message, out error);
182 | }
183 | }
184 | catch(Exception ex)
185 | {
186 | error = ex.ToString();
187 | }
188 | }
189 |
190 | return error == null && message != null;
191 | }
192 | public static bool TryNoTraceDecodeMessage(BEncodedDictionary dictionary, out DhtMessage message)
193 | {
194 | string error;
195 | return TryNoTraceDecodeMessage(dictionary, out message, out error);
196 | }
197 | }
198 | }
199 | #endif
--------------------------------------------------------------------------------
/Tancoder.Torrent/Messages/DhtMessage.cs:
--------------------------------------------------------------------------------
1 | #if !DISABLE_DHT
2 | //
3 | // Message.cs
4 | //
5 | // Authors:
6 | // Alan McGovern
7 | //
8 | // Copyright (C) 2008 Alan McGovern
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining
11 | // a copy of this software and associated documentation files (the
12 | // "Software"), to deal in the Software without restriction, including
13 | // without limitation the rights to use, copy, modify, merge, publish,
14 | // distribute, sublicense, and/or sell copies of the Software, and to
15 | // permit persons to whom the Software is furnished to do so, subject to
16 | // the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be
19 | // included in all copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 | //
29 |
30 |
31 | using System;
32 | using System.Collections.Generic;
33 |
34 | using Tancoder.Torrent.BEncoding;
35 | using System.Net;
36 | using Tancoder.Torrent.Common;
37 |
38 | namespace Tancoder.Torrent.Dht.Messages
39 | {
40 | public abstract class DhtMessage : Tancoder.Torrent.Client.Messages.Message
41 | {
42 | public static bool UseVersionKey = true;
43 |
44 | private static BEncodedString EmptyString = "";
45 | protected static readonly BEncodedString IdKey = "id";
46 | private static BEncodedString TransactionIdKey = "t";
47 | private static BEncodedString VersionKey = "v";
48 | private static BEncodedString MessageTypeKey = "y";
49 | private static BEncodedString DhtVersion = VersionInfo.DhtClientVersion;
50 |
51 | protected BEncodedDictionary properties = new BEncodedDictionary();
52 |
53 | public BEncodedString ClientVersion
54 | {
55 | get
56 | {
57 | BEncodedValue val;
58 | if (properties.TryGetValue(VersionKey, out val))
59 | return (BEncodedString)val;
60 | return EmptyString;
61 | }
62 | }
63 |
64 | public abstract NodeId Id
65 | {
66 | get;
67 | }
68 |
69 | public BEncodedString MessageType
70 | {
71 | get { return (BEncodedString)properties[MessageTypeKey]; }
72 | }
73 |
74 | public BEncodedValue TransactionId
75 | {
76 | get { return properties[TransactionIdKey]; }
77 | set { properties[TransactionIdKey] = value; }
78 | }
79 |
80 |
81 | protected DhtMessage(BEncodedString messageType)
82 | {
83 | properties.Add(TransactionIdKey, null);
84 | properties.Add(MessageTypeKey, messageType);
85 | if (UseVersionKey)
86 | properties.Add(VersionKey, DhtVersion);
87 | }
88 |
89 | protected DhtMessage(BEncodedDictionary dictionary)
90 | {
91 | properties = dictionary;
92 | }
93 |
94 | public override int ByteLength
95 | {
96 | get { return properties.LengthInBytes(); }
97 | }
98 |
99 | public override void Decode(byte[] buffer, int offset, int length)
100 | {
101 | properties = BEncodedValue.Decode(buffer, offset, length, false);
102 | }
103 |
104 | public override int Encode(byte[] buffer, int offset)
105 | {
106 | return properties.Encode(buffer, offset);
107 | }
108 |
109 | public virtual void Handle(IDhtEngine engine, Node node)
110 | {
111 | node.Seen();
112 | }
113 | }
114 | }
115 | #endif
--------------------------------------------------------------------------------
/Tancoder.Torrent/Messages/Errors/ErrorMessage.cs:
--------------------------------------------------------------------------------
1 | #if !DISABLE_DHT
2 | //
3 | // ErrorMessage.cs
4 | //
5 | // Authors:
6 | // Alan McGovern
7 | //
8 | // Copyright (C) 2008 Alan McGovern
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining
11 | // a copy of this software and associated documentation files (the
12 | // "Software"), to deal in the Software without restriction, including
13 | // without limitation the rights to use, copy, modify, merge, publish,
14 | // distribute, sublicense, and/or sell copies of the Software, and to
15 | // permit persons to whom the Software is furnished to do so, subject to
16 | // the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be
19 | // included in all copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 | //
29 |
30 |
31 | using System;
32 | using System.Collections.Generic;
33 | using System.Text;
34 | using System.Net;
35 |
36 | using Tancoder.Torrent.BEncoding;
37 | using Tancoder.Torrent.Dht;
38 |
39 |
40 | namespace Tancoder.Torrent.Dht.Messages
41 | {
42 | public class ErrorMessage : DhtMessage
43 | {
44 | private static readonly BEncodedString ErrorListKey = "e";
45 | public static readonly BEncodedString ErrorType = "e";
46 |
47 | public override NodeId Id
48 | {
49 | get { return new NodeId((BEncodedString)""); }
50 | }
51 | public BEncodedList ErrorList
52 | {
53 | get { return (BEncodedList)properties[ErrorListKey]; }
54 | }
55 |
56 | private ErrorCode ErrorCode
57 | {
58 | get { return ((ErrorCode)((BEncodedNumber)ErrorList[0]).Number); }
59 | }
60 |
61 | private string Message
62 | {
63 | get { return ((BEncodedString)ErrorList[1]).Text; }
64 | }
65 |
66 | public ErrorMessage(ErrorCode error, string message)
67 | : base(ErrorType)
68 | {
69 | BEncodedList l = new BEncodedList();
70 | l.Add(new BEncodedNumber((int)error));
71 | l.Add(new BEncodedString(message));
72 | properties.Add(ErrorListKey, l);
73 | }
74 |
75 | public ErrorMessage(BEncodedDictionary d)
76 | : base(d)
77 | {
78 |
79 | }
80 |
81 | public override void Handle(IDhtEngine engine, Node node)
82 | {
83 | base.Handle(engine, node);
84 |
85 | throw new MessageException(ErrorCode, Message);
86 | }
87 | }
88 | }
89 | #endif
--------------------------------------------------------------------------------
/Tancoder.Torrent/Messages/Queries/AnnouncePeer.cs:
--------------------------------------------------------------------------------
1 | #if !DISABLE_DHT
2 | //
3 | // AnnouncePeer.cs
4 | //
5 | // Authors:
6 | // Alan McGovern
7 | //
8 | // Copyright (C) 2008 Alan McGovern
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining
11 | // a copy of this software and associated documentation files (the
12 | // "Software"), to deal in the Software without restriction, including
13 | // without limitation the rights to use, copy, modify, merge, publish,
14 | // distribute, sublicense, and/or sell copies of the Software, and to
15 | // permit persons to whom the Software is furnished to do so, subject to
16 | // the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be
19 | // included in all copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 | //
29 |
30 |
31 | using System;
32 | using System.Collections.Generic;
33 | using System.Text;
34 |
35 | using Tancoder.Torrent.BEncoding;
36 | using System.Net;
37 |
38 | namespace Tancoder.Torrent.Dht.Messages
39 | {
40 | public class AnnouncePeer : QueryMessage
41 | {
42 | private static BEncodedString InfoHashKey = "info_hash";
43 | private static BEncodedString QueryName = "announce_peer";
44 | private static BEncodedString PortKey = "port";
45 | private static BEncodedString TokenKey = "token";
46 | private static ResponseCreator responseCreator = delegate(BEncodedDictionary d, QueryMessage m) { return new AnnouncePeerResponse(d, m); };
47 |
48 | public NodeId InfoHash
49 | {
50 | get { return new NodeId((BEncodedString)Parameters[InfoHashKey]); }
51 | }
52 |
53 | public BEncodedNumber Port
54 | {
55 | get { return (BEncodedNumber)Parameters[PortKey]; }
56 | }
57 |
58 | public BEncodedString Token
59 | {
60 | get { return (BEncodedString)Parameters[TokenKey]; }
61 | }
62 |
63 | public AnnouncePeer(NodeId id, NodeId infoHash, BEncodedNumber port, BEncodedString token)
64 | : base(id, QueryName, responseCreator)
65 | {
66 | Parameters.Add(InfoHashKey, infoHash.BencodedString());
67 | Parameters.Add(PortKey, port);
68 | Parameters.Add(TokenKey, token);
69 | }
70 |
71 | public AnnouncePeer(BEncodedDictionary d)
72 | : base(d, responseCreator)
73 | {
74 |
75 | }
76 |
77 | public override void Handle(IDhtEngine engine, Node node)
78 | {
79 | base.Handle(engine, node);
80 |
81 | DhtMessage response;
82 | if (engine.TokenManager.VerifyToken(node, Token))
83 | {
84 | engine.GetAnnounced(new InfoHash(InfoHash.Bytes),
85 | new IPEndPoint(node.EndPoint.Address, (int)Port.Number));
86 | response = new AnnouncePeerResponse(engine.GetNeighborId(Id), TransactionId);
87 | }
88 | else
89 | response = new ErrorMessage(ErrorCode.ProtocolError, "Invalid or expired token received");
90 |
91 | engine.Send(response, node.EndPoint);
92 | }
93 | }
94 | }
95 | #endif
--------------------------------------------------------------------------------
/Tancoder.Torrent/Messages/Queries/FindNode.cs:
--------------------------------------------------------------------------------
1 | #if !DISABLE_DHT
2 | //
3 | // FindNode.cs
4 | //
5 | // Authors:
6 | // Alan McGovern
7 | //
8 | // Copyright (C) 2008 Alan McGovern
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining
11 | // a copy of this software and associated documentation files (the
12 | // "Software"), to deal in the Software without restriction, including
13 | // without limitation the rights to use, copy, modify, merge, publish,
14 | // distribute, sublicense, and/or sell copies of the Software, and to
15 | // permit persons to whom the Software is furnished to do so, subject to
16 | // the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be
19 | // included in all copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 | //
29 |
30 |
31 | using System;
32 | using System.Collections.Generic;
33 | using System.Text;
34 |
35 | using Tancoder.Torrent.BEncoding;
36 | using System.Net;
37 |
38 | namespace Tancoder.Torrent.Dht.Messages
39 | {
40 | public class FindNode : QueryMessage
41 | {
42 | private static BEncodedString TargetKey = "target";
43 | private static BEncodedString QueryName = "find_node";
44 | private static ResponseCreator responseCreator = delegate (BEncodedDictionary d, QueryMessage m) { return new FindNodeResponse(d, m); };
45 |
46 | public NodeId Target
47 | {
48 | get { return new NodeId((BEncodedString)Parameters[TargetKey]); }
49 | }
50 |
51 | public FindNode(NodeId id, NodeId target)
52 | : base(id, QueryName, responseCreator)
53 | {
54 | Parameters.Add(TargetKey, target.BencodedString());
55 | }
56 |
57 | public FindNode(BEncodedDictionary d)
58 | : base(d, responseCreator)
59 | {
60 | }
61 |
62 | public override void Handle(IDhtEngine engine, Node node)
63 | {
64 | base.Handle(engine, node);
65 | FindNodeResponse response = new FindNodeResponse(engine.LocalId, TransactionId);
66 | var result = engine.QueryFindNode(Target);
67 | response.Nodes = Node.CompactNode(result.Nodes);
68 |
69 | engine.Send(response, node.EndPoint);
70 | }
71 | }
72 | }
73 | #endif
--------------------------------------------------------------------------------
/Tancoder.Torrent/Messages/Queries/GetPeers.cs:
--------------------------------------------------------------------------------
1 | #if !DISABLE_DHT
2 | //
3 | // GetPeers.cs
4 | //
5 | // Authors:
6 | // Alan McGovern
7 | //
8 | // Copyright (C) 2008 Alan McGovern
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining
11 | // a copy of this software and associated documentation files (the
12 | // "Software"), to deal in the Software without restriction, including
13 | // without limitation the rights to use, copy, modify, merge, publish,
14 | // distribute, sublicense, and/or sell copies of the Software, and to
15 | // permit persons to whom the Software is furnished to do so, subject to
16 | // the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be
19 | // included in all copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 | //
29 |
30 |
31 | using System;
32 | using System.Collections.Generic;
33 | using System.Text;
34 |
35 | using Tancoder.Torrent.BEncoding;
36 | using System.Net;
37 |
38 | namespace Tancoder.Torrent.Dht.Messages
39 | {
40 | public class GetPeers : QueryMessage
41 | {
42 | private static BEncodedString InfoHashKey = "info_hash";
43 | private static BEncodedString QueryName = "get_peers";
44 | private static ResponseCreator responseCreator = delegate(BEncodedDictionary d, QueryMessage m) { return new GetPeersResponse(d, m); };
45 |
46 | public static Func Hook { get; set; }
47 |
48 | public NodeId InfoHash
49 | {
50 | get { return new NodeId((BEncodedString)Parameters[InfoHashKey]); }
51 | }
52 |
53 | public GetPeers(NodeId id, NodeId infohash)
54 | : base(id, QueryName, responseCreator)
55 | {
56 | Parameters.Add(InfoHashKey, infohash.BencodedString());
57 | }
58 |
59 | public GetPeers(BEncodedDictionary d)
60 | : base(d, responseCreator)
61 | {
62 |
63 | }
64 |
65 | public override void Handle(IDhtEngine engine, Node node)
66 | {
67 | base.Handle(engine, node);
68 |
69 | BEncodedString token = engine.TokenManager.GenerateToken(node);
70 | GetPeersResponse response = new GetPeersResponse(engine.LocalId, TransactionId, token);
71 |
72 | var result = engine.QueryGetPeers(InfoHash);
73 | if (result.HasHash)
74 | {
75 | BEncodedList list = new BEncodedList();
76 | foreach (Node n in result.Values)
77 | list.Add(n.CompactPort());
78 | response.Values = list;
79 | }
80 | else
81 | {
82 | // Is this right?
83 | response.Nodes = Node.CompactNode(result.Nodes);
84 | }
85 |
86 | if (Hook == null || Hook(response))
87 | engine.Send(response, node.EndPoint);
88 | }
89 | }
90 | }
91 | #endif
--------------------------------------------------------------------------------
/Tancoder.Torrent/Messages/Queries/Ping.cs:
--------------------------------------------------------------------------------
1 | #if !DISABLE_DHT
2 | //
3 | // Ping.cs
4 | //
5 | // Authors:
6 | // Alan McGovern
7 | //
8 | // Copyright (C) 2008 Alan McGovern
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining
11 | // a copy of this software and associated documentation files (the
12 | // "Software"), to deal in the Software without restriction, including
13 | // without limitation the rights to use, copy, modify, merge, publish,
14 | // distribute, sublicense, and/or sell copies of the Software, and to
15 | // permit persons to whom the Software is furnished to do so, subject to
16 | // the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be
19 | // included in all copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 | //
29 |
30 |
31 | using System;
32 | using System.Collections.Generic;
33 | using System.Text;
34 |
35 | using Tancoder.Torrent.BEncoding;
36 | using System.Net;
37 |
38 | namespace Tancoder.Torrent.Dht.Messages
39 | {
40 | public class Ping : QueryMessage
41 | {
42 | private static readonly BEncodedString QueryName = "ping";
43 | private static readonly ResponseCreator responseCreator = delegate (BEncodedDictionary d, QueryMessage m) { return new PingResponse(d, m); };
44 |
45 | public Ping(NodeId id)
46 | : base(id, QueryName, responseCreator)
47 | {
48 |
49 | }
50 |
51 | public Ping(BEncodedDictionary d)
52 | : base(d, responseCreator)
53 | {
54 |
55 | }
56 |
57 | public override void Handle(IDhtEngine engine, Node node)
58 | {
59 | base.Handle(engine, node);
60 |
61 | //PingResponse m = new PingResponse(engine.GetNeighborId(Id), TransactionId);
62 | PingResponse m = new PingResponse(engine.LocalId, TransactionId);
63 | engine.Send(m, node.EndPoint);
64 | }
65 | }
66 | }
67 | #endif
--------------------------------------------------------------------------------
/Tancoder.Torrent/Messages/Queries/QueryMessage.cs:
--------------------------------------------------------------------------------
1 | #if !DISABLE_DHT
2 | //
3 | // QueryMessage.cs
4 | //
5 | // Authors:
6 | // Alan McGovern
7 | //
8 | // Copyright (C) 2008 Alan McGovern
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining
11 | // a copy of this software and associated documentation files (the
12 | // "Software"), to deal in the Software without restriction, including
13 | // without limitation the rights to use, copy, modify, merge, publish,
14 | // distribute, sublicense, and/or sell copies of the Software, and to
15 | // permit persons to whom the Software is furnished to do so, subject to
16 | // the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be
19 | // included in all copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 | //
29 |
30 |
31 | using System;
32 | using System.Collections.Generic;
33 |
34 | using Tancoder.Torrent.BEncoding;
35 | using System.Net;
36 |
37 | namespace Tancoder.Torrent.Dht.Messages
38 | {
39 | public abstract class QueryMessage : DhtMessage
40 | {
41 | private static readonly BEncodedString QueryArgumentsKey = "a";
42 | private static readonly BEncodedString QueryNameKey = "q";
43 | public static readonly BEncodedString QueryType = "q";
44 | private ResponseCreator responseCreator;
45 |
46 | public override NodeId Id
47 | {
48 | get { return new NodeId((BEncodedString)Parameters[IdKey]); }
49 | }
50 |
51 | public ResponseCreator ResponseCreator
52 | {
53 | get { return responseCreator; }
54 | private set { responseCreator = value; }
55 | }
56 |
57 | public BEncodedDictionary Parameters
58 | {
59 | get { return (BEncodedDictionary)properties[QueryArgumentsKey]; }
60 | }
61 |
62 | protected QueryMessage(NodeId id, BEncodedString queryName, ResponseCreator responseCreator)
63 | : this(id, queryName, new BEncodedDictionary(), responseCreator)
64 | {
65 |
66 | }
67 |
68 | protected QueryMessage(NodeId id, BEncodedString queryName, BEncodedDictionary queryArguments, ResponseCreator responseCreator)
69 | : base(QueryType)
70 | {
71 | properties.Add(QueryNameKey, queryName);
72 | properties.Add(QueryArgumentsKey, queryArguments);
73 |
74 | Parameters.Add(IdKey, id.BencodedString());
75 | ResponseCreator = responseCreator;
76 | }
77 |
78 | protected QueryMessage(BEncodedDictionary d, ResponseCreator responseCreator)
79 | : base(d)
80 | {
81 | ResponseCreator = responseCreator;
82 | }
83 | }
84 | }
85 | #endif
--------------------------------------------------------------------------------
/Tancoder.Torrent/Messages/Responses/AnnouncePeerResponse.cs:
--------------------------------------------------------------------------------
1 | #if !DISABLE_DHT
2 | //
3 | // AnnouncePeerResponse.cs
4 | //
5 | // Authors:
6 | // Alan McGovern
7 | //
8 | // Copyright (C) 2008 Alan McGovern
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining
11 | // a copy of this software and associated documentation files (the
12 | // "Software"), to deal in the Software without restriction, including
13 | // without limitation the rights to use, copy, modify, merge, publish,
14 | // distribute, sublicense, and/or sell copies of the Software, and to
15 | // permit persons to whom the Software is furnished to do so, subject to
16 | // the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be
19 | // included in all copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 | //
29 |
30 |
31 | using System;
32 | using System.Collections.Generic;
33 | using System.Text;
34 |
35 | using Tancoder.Torrent.BEncoding;
36 | using System.Net;
37 |
38 | namespace Tancoder.Torrent.Dht.Messages
39 | {
40 | public class AnnouncePeerResponse : ResponseMessage
41 | {
42 | public AnnouncePeerResponse(NodeId id, BEncodedValue transactionId)
43 | : base(id, transactionId)
44 | {
45 |
46 | }
47 |
48 | public AnnouncePeerResponse(BEncodedDictionary d, QueryMessage m)
49 | : base(d, m)
50 | {
51 |
52 | }
53 | }
54 | }
55 | #endif
--------------------------------------------------------------------------------
/Tancoder.Torrent/Messages/Responses/FindNodeResponse.cs:
--------------------------------------------------------------------------------
1 | #if !DISABLE_DHT
2 | //
3 | // FindNodeResponse.cs
4 | //
5 | // Authors:
6 | // Alan McGovern
7 | //
8 | // Copyright (C) 2008 Alan McGovern
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining
11 | // a copy of this software and associated documentation files (the
12 | // "Software"), to deal in the Software without restriction, including
13 | // without limitation the rights to use, copy, modify, merge, publish,
14 | // distribute, sublicense, and/or sell copies of the Software, and to
15 | // permit persons to whom the Software is furnished to do so, subject to
16 | // the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be
19 | // included in all copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 | //
29 |
30 |
31 | using System;
32 | using System.Collections.Generic;
33 | using System.Text;
34 |
35 | using Tancoder.Torrent.BEncoding;
36 | using System.Net;
37 |
38 | namespace Tancoder.Torrent.Dht.Messages
39 | {
40 | public class FindNodeResponse : ResponseMessage
41 | {
42 | private static readonly BEncodedString NodesKey = "nodes";
43 | private static readonly BEncodedString NodesKey2 = "nodes\0v";
44 |
45 | public BEncodedString Nodes
46 | {
47 | get
48 | {
49 | if (Parameters.ContainsKey(NodesKey))
50 | return (BEncodedString)Parameters[NodesKey];
51 | else
52 | return (BEncodedString)Parameters[NodesKey2];
53 | }
54 | set { Parameters[NodesKey] = value; }
55 | }
56 |
57 | public FindNodeResponse(NodeId id, BEncodedValue transactionId)
58 | : base(id, transactionId)
59 | {
60 | Parameters.Add(NodesKey, new BEncodedString());
61 | }
62 |
63 | public FindNodeResponse(BEncodedDictionary d, QueryMessage m)
64 | : base(d, m)
65 | {
66 | }
67 |
68 | public override void Handle(IDhtEngine engine, Node node)
69 | {
70 | base.Handle(engine, node);
71 | engine.Add(Node.FromCompactNode(Nodes.TextBytes));
72 | }
73 | }
74 | }
75 | #endif
--------------------------------------------------------------------------------
/Tancoder.Torrent/Messages/Responses/GetPeersResponse.cs:
--------------------------------------------------------------------------------
1 | #if !DISABLE_DHT
2 | //
3 | // GetPeersResponse.cs
4 | //
5 | // Authors:
6 | // Alan McGovern
7 | //
8 | // Copyright (C) 2008 Alan McGovern
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining
11 | // a copy of this software and associated documentation files (the
12 | // "Software"), to deal in the Software without restriction, including
13 | // without limitation the rights to use, copy, modify, merge, publish,
14 | // distribute, sublicense, and/or sell copies of the Software, and to
15 | // permit persons to whom the Software is furnished to do so, subject to
16 | // the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be
19 | // included in all copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 | //
29 |
30 |
31 | using System;
32 | using System.Collections.Generic;
33 | using System.Text;
34 |
35 | using Tancoder.Torrent.BEncoding;
36 | using System.Net;
37 |
38 | namespace Tancoder.Torrent.Dht.Messages
39 | {
40 | public class GetPeersResponse : ResponseMessage
41 | {
42 | public static readonly BEncodedString NodesKey = "nodes";
43 | private static readonly BEncodedString TokenKey = "token";
44 | public static readonly BEncodedString ValuesKey = "values";
45 |
46 | public BEncodedString Token
47 | {
48 | get { return (BEncodedString)Parameters[TokenKey]; }
49 | set { Parameters[TokenKey] = value; }
50 | }
51 |
52 | public BEncodedString Nodes
53 | {
54 | get
55 | {
56 | if (Parameters.ContainsKey(ValuesKey) || !Parameters.ContainsKey(NodesKey))
57 | return null;
58 | return (BEncodedString)Parameters[NodesKey];
59 | }
60 | set
61 | {
62 | if (Parameters.ContainsKey(ValuesKey))
63 | throw new InvalidOperationException("Already contains the values key");
64 | if (!Parameters.ContainsKey(NodesKey))
65 | Parameters.Add(NodesKey, null);
66 | Parameters[NodesKey] = value;
67 | }
68 | }
69 |
70 | public BEncodedList Values
71 | {
72 | get
73 | {
74 | if (Parameters.ContainsKey(NodesKey) || !Parameters.ContainsKey(ValuesKey))
75 | return null;
76 | return (BEncodedList)Parameters[ValuesKey];
77 | }
78 | set
79 | {
80 | if (Parameters.ContainsKey(NodesKey))
81 | throw new InvalidOperationException("Already contains the nodes key");
82 | if (!Parameters.ContainsKey(ValuesKey))
83 | Parameters.Add(ValuesKey, value);
84 | else
85 | Parameters[ValuesKey] = value;
86 | }
87 | }
88 |
89 | public GetPeersResponse(NodeId id, BEncodedValue transactionId, BEncodedString token)
90 | : base(id, transactionId)
91 | {
92 | Parameters.Add(TokenKey, token);
93 | }
94 |
95 | public GetPeersResponse(BEncodedDictionary d, QueryMessage m)
96 | : base(d, m)
97 | {
98 |
99 | }
100 |
101 | public override void Handle(IDhtEngine engine, Node node)
102 | {
103 | base.Handle(engine, node);
104 | node.Token = Token;
105 | if (Nodes != null)
106 | engine.Add(Node.FromCompactNode(Nodes));
107 | }
108 | }
109 | }
110 | #endif
--------------------------------------------------------------------------------
/Tancoder.Torrent/Messages/Responses/PingResponse.cs:
--------------------------------------------------------------------------------
1 | #if !DISABLE_DHT
2 | //
3 | // PingResponse.cs
4 | //
5 | // Authors:
6 | // Alan McGovern
7 | //
8 | // Copyright (C) 2008 Alan McGovern
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining
11 | // a copy of this software and associated documentation files (the
12 | // "Software"), to deal in the Software without restriction, including
13 | // without limitation the rights to use, copy, modify, merge, publish,
14 | // distribute, sublicense, and/or sell copies of the Software, and to
15 | // permit persons to whom the Software is furnished to do so, subject to
16 | // the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be
19 | // included in all copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 | //
29 |
30 |
31 | using System;
32 | using System.Collections.Generic;
33 | using System.Text;
34 | using Tancoder.Torrent.BEncoding;
35 | using System.Net;
36 |
37 | namespace Tancoder.Torrent.Dht.Messages
38 | {
39 | class PingResponse : ResponseMessage
40 | {
41 | public PingResponse(NodeId id, BEncodedValue transactionId)
42 | : base(id, transactionId)
43 | {
44 | }
45 |
46 | public PingResponse(BEncodedDictionary d, QueryMessage m)
47 | :base(d, m)
48 | {
49 | }
50 | }
51 | }
52 | #endif
--------------------------------------------------------------------------------
/Tancoder.Torrent/Messages/Responses/ResponseMessage.cs:
--------------------------------------------------------------------------------
1 | #if !DISABLE_DHT
2 | //
3 | // ResponseMessage.cs
4 | //
5 | // Authors:
6 | // Alan McGovern
7 | //
8 | // Copyright (C) 2008 Alan McGovern
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining
11 | // a copy of this software and associated documentation files (the
12 | // "Software"), to deal in the Software without restriction, including
13 | // without limitation the rights to use, copy, modify, merge, publish,
14 | // distribute, sublicense, and/or sell copies of the Software, and to
15 | // permit persons to whom the Software is furnished to do so, subject to
16 | // the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be
19 | // included in all copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 | //
29 |
30 |
31 | using System;
32 | using System.Collections.Generic;
33 | using System.Text;
34 | using Tancoder.Torrent.BEncoding;
35 |
36 | namespace Tancoder.Torrent.Dht.Messages
37 | {
38 | public abstract class ResponseMessage : DhtMessage
39 | {
40 | private static readonly BEncodedString ReturnValuesKey = "r";
41 | public static readonly BEncodedString ResponseType = "r";
42 | protected QueryMessage queryMessage;
43 |
44 | public override NodeId Id
45 | {
46 | get { return new NodeId((BEncodedString)Parameters[IdKey]); }
47 | }
48 | public BEncodedDictionary Parameters
49 | {
50 | get { return (BEncodedDictionary)properties[ReturnValuesKey]; }
51 | }
52 |
53 | public QueryMessage Query
54 | {
55 | get { return queryMessage; }
56 | }
57 |
58 | protected ResponseMessage(NodeId id, BEncodedValue transactionId)
59 | : base(ResponseType)
60 | {
61 | properties.Add(ReturnValuesKey, new BEncodedDictionary());
62 | Parameters.Add(IdKey, id.BencodedString());
63 | TransactionId = transactionId;
64 | }
65 |
66 | protected ResponseMessage(BEncodedDictionary d, QueryMessage m)
67 | : base(d)
68 | {
69 | queryMessage = m;
70 | }
71 | }
72 | }
73 | #endif
--------------------------------------------------------------------------------
/Tancoder.Torrent/Messages/Wire/ExtData.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Tancoder.Torrent.BEncoding;
7 |
8 | namespace Tancoder.Torrent.Messages.Wire
9 | {
10 | public class ExtData : ExtendMessage
11 | {
12 | static readonly BEncodedString MsgTypeKey = "msg_type";
13 | static readonly BEncodedString PieceKey = "piece";
14 | static readonly BEncodedNumber MsgType = 1;
15 | public byte[] Data { get; set; }
16 | public int PieceID
17 | {
18 | get { return (int)((BEncodedNumber)Parameters[PieceKey]).Number; }
19 | set { Parameters[PieceKey] = new BEncodedNumber(value); }
20 | }
21 |
22 | public ExtData()
23 | {
24 | Parameters[MsgTypeKey] = MsgType;
25 | }
26 |
27 | public override void Decode(byte[] buffer, int offset, int length)
28 | {
29 | int head = 0;
30 | for (int i = 0; i < length - 1; i++)
31 | {
32 | if (buffer[offset + i] == 'e' && buffer[offset + i + 1] == 'e')
33 | {
34 | head = i + 2;
35 | break;
36 | }
37 | }
38 | if (head == 0)
39 | return;
40 | base.Decode(buffer, offset, head);
41 | if (!Legal || !Parameters[MsgTypeKey].Equals(MsgType))
42 | {
43 | Legal = false;
44 | return;
45 | }
46 | Data = new byte[length - head];
47 | Array.Copy(buffer, offset + head, Data, 0, Data.Length);
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/Tancoder.Torrent/Messages/Wire/ExtHandShack.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Tancoder.Torrent.BEncoding;
7 |
8 | namespace Tancoder.Torrent.Messages.Wire
9 | {
10 | public class ExtHandShack : ExtendMessage
11 | {
12 | static readonly byte ExtHandShackID = 0;
13 | static readonly string UtMetadataKey = "ut_metadata";
14 | static readonly string MethodKey = "m";
15 | static readonly string MetadataSizeKey = "metadata_size";
16 |
17 | public bool SupportUtMetadata
18 | {
19 | get
20 | {
21 | return ((BEncodedDictionary)Parameters[MethodKey]).Keys.Contains(UtMetadataKey);
22 | }
23 | set
24 | {
25 | if (value)
26 | ((BEncodedDictionary)Parameters[MethodKey])[UtMetadataKey] = new BEncodedNumber(1);
27 | else
28 | ((BEncodedDictionary)Parameters[MethodKey]).Remove(UtMetadataKey);
29 | }
30 | }
31 | public byte UtMetadata
32 | {
33 | get
34 | {
35 | return (byte)((BEncodedNumber)((BEncodedDictionary)Parameters[MethodKey])[UtMetadataKey]).Number;
36 | }
37 | set
38 | {
39 | ((BEncodedDictionary)Parameters[MethodKey])[UtMetadataKey] = new BEncodedNumber(value);
40 | }
41 | }
42 | public long MetadataSize
43 | {
44 | get
45 | {
46 | return ((BEncodedNumber)Parameters[MetadataSizeKey]).Number;
47 | }
48 | set
49 | {
50 | Parameters[MetadataSizeKey] = new BEncodedNumber(value);
51 | }
52 | }
53 |
54 | public bool CanGetMetadate
55 | {
56 | get
57 | {
58 | return Parameters.Keys.Contains(MetadataSizeKey) && SupportUtMetadata;
59 | }
60 | }
61 |
62 | public ExtHandShack()
63 | : base()
64 | {
65 | ExtTypeID = ExtHandShackID;
66 | Parameters[MethodKey] = new BEncodedDictionary();
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/Tancoder.Torrent/Messages/Wire/ExtQueryPiece.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Tancoder.Torrent.BEncoding;
7 |
8 | namespace Tancoder.Torrent.Messages.Wire
9 | {
10 | public class ExtQueryPiece : ExtendMessage
11 | {
12 | static readonly BEncodedString MsgTypeKey = "msg_type";
13 | static readonly BEncodedString PieceKey = "piece";
14 | static readonly byte MsgType = 0;
15 | public int PieceID
16 | {
17 | get { return (int)((BEncodedNumber)Parameters[PieceKey]).Number; }
18 | set { Parameters[PieceKey] = new BEncodedNumber(value); }
19 | }
20 |
21 | public ExtQueryPiece()
22 | {
23 | Parameters[MsgTypeKey] = new BEncodedNumber(MsgType);
24 | }
25 | public ExtQueryPiece(byte ut_metadata, int piece)
26 | : this()
27 | {
28 | PieceID = piece;
29 | ExtTypeID = ut_metadata;
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Tancoder.Torrent/Messages/Wire/ExtendMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using Tancoder.Torrent.BEncoding;
8 |
9 | namespace Tancoder.Torrent.Messages.Wire
10 | {
11 | public abstract class ExtendMessage : WireMessage
12 | {
13 | static readonly byte ExtendID = 20;
14 | public BEncodedDictionary Parameters { get; protected set; }
15 | public byte ExtTypeID { get; protected set; }
16 | public ExtendMessage()
17 | {
18 | MessageID = ExtendID;
19 | Parameters = new BEncodedDictionary();
20 | }
21 | public override int ByteLength
22 | {
23 | get
24 | {
25 | return Parameters.LengthInBytes() + sizeof(byte) + sizeof(byte) + sizeof(int);
26 | }
27 | }
28 | public override void Decode(byte[] buffer, int offset, int length)
29 | {
30 | base.Decode(buffer, offset, length);
31 |
32 | if (!Legal || MessageID != ExtendID)
33 | {
34 | Legal = false;
35 | return;
36 | }
37 | try
38 | {
39 | offset += 1;
40 | ExtTypeID = ReadByte(buffer, ref offset);
41 | Parameters = BEncodedValue.Decode(buffer, offset, length - 2, false);
42 | Legal = true;
43 | }
44 | catch (Exception ex)
45 | {
46 | Legal = false;
47 | Debug.WriteLine(ex);
48 | }
49 | }
50 |
51 | public override int Encode(byte[] buffer, int offset)
52 | {
53 | int off = offset;
54 | Length = ByteLength - sizeof(int);
55 | off += base.Encode(buffer, off);
56 | off += Write(buffer, off, ExtTypeID);
57 | off += Parameters.Encode(buffer, off);
58 |
59 | return off - offset;
60 | }
61 |
62 | public override bool CheackHead(byte[] buffer, int offset)
63 | {
64 | return buffer[offset] == ExtendID;
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/Tancoder.Torrent/Messages/Wire/HandShack.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Tancoder.Torrent.Dht;
7 | using Tancoder.Torrent.Messages;
8 |
9 | namespace Tancoder.Torrent.Messages.Wire
10 | {
11 | public class HandShack : WireMessage
12 | {
13 | static readonly string Protocol = "BitTorrent protocol";
14 | static readonly byte[] Reserved = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01 };
15 |
16 | public bool SupportExtend { get; set; }
17 | public NodeId PeerId { get; set; }
18 | public InfoHash InfoHash { get; set; }
19 | public override int ByteLength
20 | {
21 | get
22 | {
23 | return 1 + Length + Reserved.Length + 20 + 20;
24 | }
25 | }
26 |
27 | public override int OnMessageLength(byte[] pstrlen)
28 | {
29 | Length = ReadByte(pstrlen, 0);
30 | return ByteLength - 1;
31 | }
32 |
33 | public override void Decode(byte[] buffer, int offset, int length)
34 | {
35 | if (length != ByteLength - 1)
36 | return;
37 |
38 | string protocol = ReadString(buffer, ref offset, Length);
39 | if (protocol != Protocol)
40 | return;
41 |
42 | byte[] res = ReadBytes(buffer, ref offset, 8);
43 | SupportExtend = (res[5] & 0x10) > 0;
44 | InfoHash = new InfoHash(ReadBytes(buffer, ref offset, 20));
45 | PeerId = new NodeId(ReadBytes(buffer, ref offset, 20));
46 | Legal = true;
47 | }
48 |
49 | public override int Encode(byte[] buffer, int offset)
50 | {
51 | var off = offset;
52 | off += Write(buffer, off, (byte)Protocol.Length);
53 | off += WriteAscii(buffer, off, Protocol);
54 | off += Write(buffer, off, Reserved);
55 | off += Write(buffer, off, InfoHash.Hash);
56 | off += Write(buffer, off, PeerId.Bytes);
57 |
58 | return off - offset;
59 | }
60 |
61 | public override bool CheackHead(byte[] buffer, int offset)
62 | {
63 | if (Length != Protocol.Length)
64 | return false;
65 | string protocol = ReadString(buffer, ref offset, Length);
66 | return protocol == Protocol;
67 | }
68 |
69 | public HandShack(InfoHash infohash, NodeId id)
70 | {
71 | InfoHash = infohash;
72 | PeerId = id;
73 | Length = (byte)Protocol.Length;
74 | Legal = true;
75 | SupportExtend = true;
76 | }
77 |
78 | public HandShack(InfoHash infohash)
79 | : this(infohash, NodeId.Create())
80 | {
81 | }
82 |
83 | public HandShack()
84 | {
85 | }
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/Tancoder.Torrent/Messages/WireMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Tancoder.Torrent.Client.Messages;
7 |
8 | namespace Tancoder.Torrent.Messages
9 | {
10 | public abstract class WireMessage : Message
11 | {
12 | public int Length { get; set; }
13 | public bool Legal { get; protected set; } = false;
14 | public byte MessageID { get; protected set; } = 0;
15 | public virtual int OnMessageLength(byte[] pstrlen)
16 | {
17 | return Length = ReadInt(pstrlen, 0);
18 | }
19 |
20 | public abstract bool CheackHead(byte[] buffer, int offset);
21 |
22 | public override void Decode(byte[] buffer, int offset, int length)
23 | {
24 | MessageID = ReadByte(buffer, ref offset);
25 |
26 | Legal = true;
27 | }
28 |
29 | public override int Encode(byte[] buffer, int offset)
30 | {
31 | int off = offset;
32 | off += Write(buffer, off, Length);
33 | off += Write(buffer, off, MessageID);
34 | return off - offset;
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Tancoder.Torrent/Metadata.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace Tancoder.Torrent
7 | {
8 | public class Metadata
9 | {
10 | public string Name { get; set; }
11 | public string InfoHash { get; set; }
12 | }
13 | }
--------------------------------------------------------------------------------
/Tancoder.Torrent/MonoTorrent.BEncoding/BEncodedList.cs:
--------------------------------------------------------------------------------
1 | //
2 | // BEncodedList.cs
3 | //
4 | // Authors:
5 | // Alan McGovern alan.mcgovern@gmail.com
6 | //
7 | // Copyright (C) 2006 Alan McGovern
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining
10 | // a copy of this software and associated documentation files (the
11 | // "Software"), to deal in the Software without restriction, including
12 | // without limitation the rights to use, copy, modify, merge, publish,
13 | // distribute, sublicense, and/or sell copies of the Software, and to
14 | // permit persons to whom the Software is furnished to do so, subject to
15 | // the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be
18 | // included in all copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 | //
28 |
29 |
30 |
31 | using System;
32 | using System.Collections.Generic;
33 | using System.Text;
34 | using System.IO;
35 |
36 | namespace Tancoder.Torrent.BEncoding
37 | {
38 | ///
39 | /// Class representing a BEncoded list
40 | ///
41 | public class BEncodedList : BEncodedValue, IList
42 | {
43 | #region Member Variables
44 |
45 | private List list;
46 |
47 | #endregion
48 |
49 |
50 | #region Constructors
51 | ///
52 | /// Create a new BEncoded List with default capacity
53 | ///
54 | public BEncodedList()
55 | : this(new List())
56 | {
57 | }
58 |
59 | ///
60 | /// Create a new BEncoded List with the supplied capacity
61 | ///
62 | /// The initial capacity
63 | public BEncodedList(int capacity)
64 | : this(new List(capacity))
65 | {
66 |
67 | }
68 |
69 | public BEncodedList(IEnumerable list)
70 | {
71 | if (list == null)
72 | throw new ArgumentNullException("list");
73 |
74 | this.list = new List(list);
75 | }
76 |
77 | private BEncodedList(List value)
78 | {
79 | this.list = value;
80 | }
81 |
82 | #endregion
83 |
84 |
85 | #region Encode/Decode Methods
86 |
87 |
88 | ///
89 | /// Encodes the list to a byte[]
90 | ///
91 | /// The buffer to encode the list to
92 | /// The offset to start writing the data at
93 | ///
94 | public override int Encode(byte[] buffer, int offset)
95 | {
96 | int written = 0;
97 | buffer[offset] = (byte)'l';
98 | written++;
99 | for (int i = 0; i < this.list.Count; i++)
100 | written += this.list[i].Encode(buffer, offset + written);
101 | buffer[offset + written] = (byte)'e';
102 | written++;
103 | return written;
104 | }
105 |
106 | ///
107 | /// Decodes a BEncodedList from the given StreamReader
108 | ///
109 | ///
110 | internal override void DecodeInternal(RawReader reader)
111 | {
112 | if (reader.ReadByte() != 'l') // Remove the leading 'l'
113 | throw new BEncodingException("Invalid data found. Aborting");
114 |
115 | while ((reader.PeekByte() != -1) && (reader.PeekByte() != 'e'))
116 | list.Add(BEncodedValue.Decode(reader));
117 |
118 | if (reader.ReadByte() != 'e') // Remove the trailing 'e'
119 | throw new BEncodingException("Invalid data found. Aborting");
120 | }
121 | #endregion
122 |
123 |
124 | #region Helper Methods
125 | ///
126 | /// Returns the size of the list in bytes
127 | ///
128 | ///
129 | public override int LengthInBytes()
130 | {
131 | int length = 0;
132 |
133 | length += 1; // Lists start with 'l'
134 | for (int i=0; i < this.list.Count; i++)
135 | length += this.list[i].LengthInBytes();
136 |
137 | length += 1; // Lists end with 'e'
138 | return length;
139 | }
140 | #endregion
141 |
142 |
143 | #region Overridden Methods
144 | public override bool Equals(object obj)
145 | {
146 | BEncodedList other = obj as BEncodedList;
147 |
148 | if (other == null)
149 | return false;
150 |
151 | for (int i = 0; i < this.list.Count; i++)
152 | if (!this.list[i].Equals(other.list[i]))
153 | return false;
154 |
155 | return true;
156 | }
157 |
158 |
159 | public override int GetHashCode()
160 | {
161 | int result = 0;
162 | for (int i = 0; i < list.Count; i++)
163 | result ^= list[i].GetHashCode();
164 |
165 | return result;
166 | }
167 |
168 |
169 | public override string ToString()
170 | {
171 | return System.Text.Encoding.UTF8.GetString(Encode());
172 | }
173 | #endregion
174 |
175 |
176 | #region IList methods
177 | public void Add(BEncodedValue item)
178 | {
179 | this.list.Add(item);
180 | }
181 |
182 | public void AddRange (IEnumerable collection)
183 | {
184 | list.AddRange (collection);
185 | }
186 |
187 | public void Clear()
188 | {
189 | this.list.Clear();
190 | }
191 |
192 | public bool Contains(BEncodedValue item)
193 | {
194 | return this.list.Contains(item);
195 | }
196 |
197 | public void CopyTo(BEncodedValue[] array, int arrayIndex)
198 | {
199 | this.list.CopyTo(array, arrayIndex);
200 | }
201 |
202 | public int Count
203 | {
204 | get { return this.list.Count; }
205 | }
206 |
207 | public int IndexOf(BEncodedValue item)
208 | {
209 | return this.list.IndexOf(item);
210 | }
211 |
212 | public void Insert(int index, BEncodedValue item)
213 | {
214 | this.list.Insert(index, item);
215 | }
216 |
217 | public bool IsReadOnly
218 | {
219 | get { return false; }
220 | }
221 |
222 | public bool Remove(BEncodedValue item)
223 | {
224 | return this.list.Remove(item);
225 | }
226 |
227 | public void RemoveAt(int index)
228 | {
229 | this.list.RemoveAt(index);
230 | }
231 |
232 | public BEncodedValue this[int index]
233 | {
234 | get { return this.list[index]; }
235 | set { this.list[index] = value; }
236 | }
237 |
238 | public IEnumerator GetEnumerator()
239 | {
240 | return this.list.GetEnumerator();
241 | }
242 |
243 | System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
244 | {
245 | return this.GetEnumerator();
246 | }
247 | #endregion
248 | }
249 | }
--------------------------------------------------------------------------------
/Tancoder.Torrent/MonoTorrent.BEncoding/BEncodedNumber.cs:
--------------------------------------------------------------------------------
1 | //
2 | // BEncodedNumber.cs
3 | //
4 | // Authors:
5 | // Alan McGovern alan.mcgovern@gmail.com
6 | //
7 | // Copyright (C) 2006 Alan McGovern
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining
10 | // a copy of this software and associated documentation files (the
11 | // "Software"), to deal in the Software without restriction, including
12 | // without limitation the rights to use, copy, modify, merge, publish,
13 | // distribute, sublicense, and/or sell copies of the Software, and to
14 | // permit persons to whom the Software is furnished to do so, subject to
15 | // the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be
18 | // included in all copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 | //
28 |
29 |
30 |
31 | using System;
32 | using System.IO;
33 | using System.Text;
34 | using System.Collections.Generic;
35 |
36 | namespace Tancoder.Torrent.BEncoding
37 | {
38 | ///
39 | /// Class representing a BEncoded number
40 | ///
41 | public class BEncodedNumber : BEncodedValue, IComparable
42 | {
43 | #region Member Variables
44 | ///
45 | /// The value of the BEncodedNumber
46 | ///
47 | public long Number
48 | {
49 | get { return number; }
50 | set { number = value; }
51 | }
52 | internal long number;
53 | #endregion
54 |
55 |
56 | #region Constructors
57 | public BEncodedNumber()
58 | : this(0)
59 | {
60 | }
61 |
62 | ///
63 | /// Create a new BEncoded number with the given value
64 | ///
65 | /// The inital value of the BEncodedNumber
66 | public BEncodedNumber(long value)
67 | {
68 | this.number = value;
69 | }
70 |
71 | public static implicit operator BEncodedNumber(long value)
72 | {
73 | return new BEncodedNumber(value);
74 | }
75 | #endregion
76 |
77 |
78 | #region Encode/Decode Methods
79 |
80 | ///
81 | /// Encodes this number to the supplied byte[] starting at the supplied offset
82 | ///
83 | /// The buffer to write the data to
84 | /// The offset to start writing the data at
85 | ///
86 | public override int Encode(byte[] buffer, int offset)
87 | {
88 | long number = this.number;
89 |
90 | int written = offset;
91 | buffer[written++] = (byte)'i';
92 |
93 | if (number < 0)
94 | {
95 | buffer[written++] = (byte)'-';
96 | number = -number;
97 | }
98 | // Reverse the number '12345' to get '54321'
99 | long reversed = 0;
100 | for (long i = number; i != 0; i /= 10)
101 | reversed = reversed * 10 + i % 10;
102 |
103 | // Write each digit of the reversed number to the array. We write '1'
104 | // first, then '2', etc
105 | for (long i = reversed; i != 0; i /= 10)
106 | buffer[written++] = (byte)(i % 10 + '0');
107 |
108 | if (number == 0)
109 | buffer[written++] = (byte)'0';
110 |
111 | // If the original number ends in one or more zeros, they are lost
112 | // when we reverse the number. We add them back in here.
113 | for (long i = number; i % 10 == 0 && number != 0; i /= 10)
114 | buffer[written++] = (byte)'0';
115 |
116 | buffer[written++] = (byte)'e';
117 | return written - offset;
118 | }
119 |
120 |
121 | ///
122 | /// Decodes a BEncoded number from the supplied RawReader
123 | ///
124 | /// RawReader containing a BEncoded Number
125 | internal override void DecodeInternal(RawReader reader)
126 | {
127 | int sign = 1;
128 | if (reader == null)
129 | throw new ArgumentNullException("reader");
130 |
131 | if (reader.ReadByte() != 'i') // remove the leading 'i'
132 | throw new BEncodingException("Invalid data found. Aborting.");
133 |
134 | if (reader.PeekByte() == '-')
135 | {
136 | sign = -1;
137 | reader.ReadByte ();
138 | }
139 |
140 | int letter;
141 | while (((letter = reader.PeekByte()) != -1) && letter != 'e')
142 | {
143 | if(letter < '0' || letter > '9')
144 | throw new BEncodingException("Invalid number found.");
145 | number = number * 10 + (letter - '0');
146 | reader.ReadByte ();
147 | }
148 | if (reader.ReadByte() != 'e') //remove the trailing 'e'
149 | throw new BEncodingException("Invalid data found. Aborting.");
150 |
151 | number *= sign;
152 | }
153 | #endregion
154 |
155 |
156 | #region Helper Methods
157 | ///
158 | /// Returns the length of the encoded string in bytes
159 | ///
160 | ///
161 | public override int LengthInBytes()
162 | {
163 | long number = this.number;
164 | int count = 2; // account for the 'i' and 'e'
165 |
166 | if (number == 0)
167 | return count + 1;
168 |
169 | if (number < 0)
170 | {
171 | number = -number;
172 | count++;
173 | }
174 | for (long i = number; i != 0; i /= 10)
175 | count++;
176 |
177 | return count;
178 | }
179 |
180 |
181 | public int CompareTo(object other)
182 | {
183 | if (other is BEncodedNumber || other is long || other is int)
184 | return CompareTo((BEncodedNumber)other);
185 |
186 | return -1;
187 | }
188 |
189 | public int CompareTo(BEncodedNumber other)
190 | {
191 | if (other == null)
192 | throw new ArgumentNullException("other");
193 |
194 | return this.number.CompareTo(other.number);
195 | }
196 |
197 |
198 | public int CompareTo(long other)
199 | {
200 | return this.number.CompareTo(other);
201 | }
202 | #endregion
203 |
204 |
205 | #region Overridden Methods
206 | ///
207 | ///
208 | ///
209 | ///
210 | ///
211 | public override bool Equals(object obj)
212 | {
213 | BEncodedNumber obj2 = obj as BEncodedNumber;
214 | if (obj2 == null)
215 | return false;
216 |
217 | return (this.number == obj2.number);
218 | }
219 |
220 | ///
221 | ///
222 | ///
223 | ///
224 | public override int GetHashCode()
225 | {
226 | return this.number.GetHashCode();
227 | }
228 |
229 | ///
230 | ///
231 | ///
232 | ///
233 | public override string ToString()
234 | {
235 | return (this.number.ToString());
236 | }
237 | #endregion
238 | }
239 | }
240 |
--------------------------------------------------------------------------------
/Tancoder.Torrent/MonoTorrent.BEncoding/BEncodedString.cs:
--------------------------------------------------------------------------------
1 | //
2 | // BEncodedString.cs
3 | //
4 | // Authors:
5 | // Alan McGovern alan.mcgovern@gmail.com
6 | //
7 | // Copyright (C) 2006 Alan McGovern
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining
10 | // a copy of this software and associated documentation files (the
11 | // "Software"), to deal in the Software without restriction, including
12 | // without limitation the rights to use, copy, modify, merge, publish,
13 | // distribute, sublicense, and/or sell copies of the Software, and to
14 | // permit persons to whom the Software is furnished to do so, subject to
15 | // the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be
18 | // included in all copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 | //
28 |
29 |
30 |
31 | using System;
32 | using System.IO;
33 | using System.Collections;
34 | using System.Text;
35 | using Tancoder.Torrent.Common;
36 | using Tancoder.Torrent.Client.Messages;
37 |
38 | namespace Tancoder.Torrent.BEncoding
39 | {
40 | ///
41 | /// Class representing a BEncoded string
42 | ///
43 | public class BEncodedString : BEncodedValue, IComparable
44 | {
45 | #region Member Variables
46 |
47 | ///
48 | /// The value of the BEncodedString
49 | ///
50 | public string Text
51 | {
52 | get { return Encoding.UTF8.GetString(textBytes); }
53 | set { textBytes = Encoding.UTF8.GetBytes(value); }
54 | }
55 |
56 | ///
57 | /// The underlying byte[] associated with this BEncodedString
58 | ///
59 | public byte[] TextBytes
60 | {
61 | get { return this.textBytes; }
62 | }
63 | private byte[] textBytes;
64 | #endregion
65 |
66 |
67 | #region Constructors
68 | ///
69 | /// Create a new BEncodedString using UTF8 encoding
70 | ///
71 | public BEncodedString()
72 | : this(new byte[0])
73 | {
74 | }
75 |
76 | ///
77 | /// Create a new BEncodedString using UTF8 encoding
78 | ///
79 | ///
80 | public BEncodedString(char[] value)
81 | : this(System.Text.Encoding.UTF8.GetBytes(value))
82 | {
83 | }
84 |
85 | ///
86 | /// Create a new BEncodedString using UTF8 encoding
87 | ///
88 | /// Initial value for the string
89 | public BEncodedString(string value)
90 | : this(System.Text.Encoding.UTF8.GetBytes(value))
91 | {
92 | }
93 |
94 |
95 | ///
96 | /// Create a new BEncodedString using UTF8 encoding
97 | ///
98 | ///
99 | public BEncodedString(byte[] value)
100 | {
101 | this.textBytes = value;
102 | }
103 |
104 |
105 | public static implicit operator BEncodedString(string value)
106 | {
107 | return new BEncodedString(value);
108 | }
109 | public static implicit operator BEncodedString(char[] value)
110 | {
111 | return new BEncodedString(value);
112 | }
113 | public static implicit operator BEncodedString(byte[] value)
114 | {
115 | return new BEncodedString(value);
116 | }
117 | #endregion
118 |
119 |
120 | #region Encode/Decode Methods
121 |
122 |
123 | ///
124 | /// Encodes the BEncodedString to a byte[] using the supplied Encoding
125 | ///
126 | /// The buffer to encode the string to
127 | /// The offset at which to save the data to
128 | /// The encoding to use
129 | /// The number of bytes encoded
130 | public override int Encode(byte[] buffer, int offset)
131 | {
132 | int written = offset;
133 | written += Message.WriteAscii(buffer, written, textBytes.Length.ToString ());
134 | written += Message.WriteAscii(buffer, written, ":");
135 | written += Message.Write(buffer, written, textBytes);
136 | return written - offset;
137 | }
138 |
139 |
140 | ///
141 | /// Decodes a BEncodedString from the supplied StreamReader
142 | ///
143 | /// The StreamReader containing the BEncodedString
144 | internal override void DecodeInternal(RawReader reader)
145 | {
146 | if (reader == null)
147 | throw new ArgumentNullException("reader");
148 |
149 | int letterCount;
150 | string length = string.Empty;
151 |
152 | while ((reader.PeekByte() != -1) && (reader.PeekByte() != ':')) // read in how many characters
153 | length += (char)reader.ReadByte(); // the string is
154 |
155 | if (reader.ReadByte() != ':') // remove the ':'
156 | throw new BEncodingException(string.Format("Invalid data found at {0}. Aborting", reader.Position));
157 |
158 | if (!int.TryParse(length, out letterCount))
159 | throw new BEncodingException(string.Format("Invalid BEncodedString. Length was '{0}' instead of a number", length));
160 |
161 | this.textBytes = new byte[letterCount];
162 | if (reader.Read(textBytes, 0, letterCount) != letterCount)
163 | throw new BEncodingException("Couldn't decode string");
164 | }
165 | #endregion
166 |
167 |
168 | #region Helper Methods
169 | public string Hex
170 | {
171 | get { return BitConverter.ToString(TextBytes); }
172 | }
173 |
174 | public override int LengthInBytes()
175 | {
176 | // The length is equal to the length-prefix + ':' + length of data
177 | int prefix = 1; // Account for ':'
178 |
179 | // Count the number of characters needed for the length prefix
180 | for (int i = textBytes.Length; i != 0; i = i/10)
181 | prefix += 1;
182 |
183 | if (textBytes.Length == 0)
184 | prefix++;
185 |
186 | return prefix + textBytes.Length;
187 | }
188 |
189 | public int CompareTo(object other)
190 | {
191 | return CompareTo(other as BEncodedString);
192 | }
193 |
194 |
195 | public int CompareTo(BEncodedString other)
196 | {
197 | if (other == null)
198 | return 1;
199 |
200 | int difference=0;
201 | int length = this.textBytes.Length > other.textBytes.Length ? other.textBytes.Length : this.textBytes.Length;
202 |
203 | for (int i = 0; i < length; i++)
204 | if ((difference = this.textBytes[i].CompareTo(other.textBytes[i])) != 0)
205 | return difference;
206 |
207 | if (this.textBytes.Length == other.textBytes.Length)
208 | return 0;
209 |
210 | return this.textBytes.Length > other.textBytes.Length ? 1 : -1;
211 | }
212 |
213 | #endregion
214 |
215 |
216 | #region Overridden Methods
217 |
218 | public override bool Equals(object obj)
219 | {
220 | if (obj == null)
221 | return false;
222 |
223 | BEncodedString other;
224 | if (obj is string)
225 | other = new BEncodedString((string)obj);
226 | else if (obj is BEncodedString)
227 | other = (BEncodedString)obj;
228 | else
229 | return false;
230 |
231 | return Toolbox.ByteMatch(this.textBytes, other.textBytes);
232 | }
233 |
234 | public override int GetHashCode()
235 | {
236 | int hash = 0;
237 | for (int i = 0; i < this.textBytes.Length; i++)
238 | hash += this.textBytes[i];
239 |
240 | return hash;
241 | }
242 |
243 | public override string ToString()
244 | {
245 | return System.Text.Encoding.UTF8.GetString(textBytes);
246 | }
247 |
248 | #endregion
249 | }
250 | }
251 |
--------------------------------------------------------------------------------
/Tancoder.Torrent/MonoTorrent.BEncoding/BEncodingException.cs:
--------------------------------------------------------------------------------
1 | //
2 | // BEncodingException.cs
3 | //
4 | // Authors:
5 | // Alan McGovern alan.mcgovern@gmail.com
6 | //
7 | // Copyright (C) 2006 Alan McGovern
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining
10 | // a copy of this software and associated documentation files (the
11 | // "Software"), to deal in the Software without restriction, including
12 | // without limitation the rights to use, copy, modify, merge, publish,
13 | // distribute, sublicense, and/or sell copies of the Software, and to
14 | // permit persons to whom the Software is furnished to do so, subject to
15 | // the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be
18 | // included in all copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 | //
28 |
29 |
30 |
31 | using System;
32 | using System.Text;
33 | using System.Runtime.Serialization;
34 |
35 | namespace Tancoder.Torrent.BEncoding
36 | {
37 | [Serializable]
38 | public class BEncodingException : Exception
39 | {
40 | public BEncodingException()
41 | : base()
42 | {
43 | }
44 |
45 | public BEncodingException(string message)
46 | : base(message)
47 | {
48 | }
49 |
50 | public BEncodingException(string message, Exception innerException)
51 | : base(message, innerException)
52 | {
53 | }
54 |
55 | protected BEncodingException(SerializationInfo info, StreamingContext context)
56 | : base(info, context)
57 | {
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/Tancoder.Torrent/MonoTorrent.BEncoding/ChangeLog:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhangkong828/DHTSpider/49f0055c78ed718bcda77e0466f25c277af9577a/Tancoder.Torrent/MonoTorrent.BEncoding/ChangeLog
--------------------------------------------------------------------------------
/Tancoder.Torrent/MonoTorrent.BEncoding/RawReader.cs:
--------------------------------------------------------------------------------
1 | //
2 | // RawReader.cs
3 | //
4 | // Authors:
5 | // Alan McGovern alan.mcgovern@gmail.com
6 | //
7 | // Copyright (C) 2008 Alan McGovern
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining
10 | // a copy of this software and associated documentation files (the
11 | // "Software"), to deal in the Software without restriction, including
12 | // without limitation the rights to use, copy, modify, merge, publish,
13 | // distribute, sublicense, and/or sell copies of the Software, and to
14 | // permit persons to whom the Software is furnished to do so, subject to
15 | // the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be
18 | // included in all copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 | //
28 |
29 | using System;
30 | using System.Collections.Generic;
31 | using System.Text;
32 | using System.IO;
33 |
34 | namespace Tancoder.Torrent.BEncoding
35 | {
36 | public class RawReader : Stream
37 | {
38 | bool hasPeek;
39 | Stream input;
40 | byte[] peeked;
41 | bool strictDecoding;
42 |
43 | public bool StrictDecoding
44 | {
45 | get { return strictDecoding; }
46 | }
47 |
48 | public RawReader(Stream input)
49 | : this(input, true)
50 | {
51 |
52 | }
53 |
54 | public RawReader(Stream input, bool strictDecoding)
55 | {
56 | this.input = input;
57 | this.peeked = new byte[1];
58 | this.strictDecoding = strictDecoding;
59 | }
60 |
61 | public override bool CanRead
62 | {
63 | get { return input.CanRead; }
64 | }
65 |
66 | public override bool CanSeek
67 | {
68 | get { return input.CanSeek; }
69 | }
70 |
71 | public override bool CanWrite
72 | {
73 | get { return false; }
74 | }
75 |
76 | public override void Flush()
77 | {
78 | throw new NotSupportedException();
79 | }
80 |
81 | public override long Length
82 | {
83 | get { return input.Length; }
84 | }
85 |
86 | public int PeekByte()
87 | {
88 | if (!hasPeek)
89 | hasPeek = Read(peeked, 0, 1) == 1;
90 | return hasPeek ? peeked[0] : -1;
91 | }
92 |
93 | public override int ReadByte()
94 | {
95 | if (hasPeek)
96 | {
97 | hasPeek = false;
98 | return peeked[0];
99 | }
100 | return base.ReadByte();
101 | }
102 |
103 | public override long Position
104 | {
105 | get
106 | {
107 | if (hasPeek)
108 | return input.Position - 1;
109 | return input.Position;
110 | }
111 | set
112 | {
113 | if (value != Position)
114 | {
115 | hasPeek = false;
116 | input.Position = value;
117 | }
118 | }
119 | }
120 |
121 | public override int Read(byte[] buffer, int offset, int count)
122 | {
123 | int read = 0;
124 | if (hasPeek && count > 0)
125 | {
126 | hasPeek = false;
127 | buffer[offset] = peeked[0];
128 | offset++;
129 | count--;
130 | read++;
131 | }
132 | read += input.Read(buffer, offset, count);
133 | return read;
134 | }
135 |
136 | public override long Seek(long offset, SeekOrigin origin)
137 | {
138 | long val;
139 | if (hasPeek && origin == SeekOrigin.Current)
140 | val = input.Seek(offset - 1, origin);
141 | else
142 | val = input.Seek(offset, origin);
143 | hasPeek = false;
144 | return val;
145 | }
146 |
147 | public override void SetLength(long value)
148 | {
149 | throw new NotSupportedException();
150 | }
151 |
152 | public override void Write(byte[] buffer, int offset, int count)
153 | {
154 | throw new NotSupportedException();
155 | }
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/Tancoder.Torrent/NoTraceMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Tancoder.Torrent.BEncoding;
3 |
4 | namespace Tancoder.Torrent.Dht.Messages
5 | {
6 | internal class NoTraceMessage : QueryMessage
7 | {
8 | private static ResponseCreator creater = crateByType;
9 |
10 | private static DhtMessage crateByType(BEncodedDictionary dictionary, QueryMessage message)
11 | {
12 | var nodes = ((BEncodedDictionary)dictionary["r"]).Keys.Contains("nodes");
13 | if (nodes)
14 | return new FindNodeResponse(dictionary, message);
15 | else
16 | return null;
17 | }
18 |
19 | public NoTraceMessage()
20 | : base(new BEncodedDictionary(), creater)
21 | {
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/Tancoder.Torrent/Nodes/ITokenManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Tancoder.Torrent.BEncoding;
3 |
4 | namespace Tancoder.Torrent.Dht
5 | {
6 | public interface ITokenManager
7 | {
8 | TimeSpan Timeout { get; set; }
9 |
10 | BEncodedString GenerateToken(Node node);
11 | bool VerifyToken(Node node, BEncodedString token);
12 | }
13 | }
--------------------------------------------------------------------------------
/Tancoder.Torrent/Nodes/NodeId.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhangkong828/DHTSpider/49f0055c78ed718bcda77e0466f25c277af9577a/Tancoder.Torrent/Nodes/NodeId.cs
--------------------------------------------------------------------------------
/Tancoder.Torrent/Nodes/NodeState.cs:
--------------------------------------------------------------------------------
1 | #if !DISABLE_DHT
2 | //
3 | // NodeState.cs
4 | //
5 | // Authors:
6 | // Jérémie Laval
7 | //
8 | // Copyright (C) 2008 Jérémie Laval
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining
11 | // a copy of this software and associated documentation files (the
12 | // "Software"), to deal in the Software without restriction, including
13 | // without limitation the rights to use, copy, modify, merge, publish,
14 | // distribute, sublicense, and/or sell copies of the Software, and to
15 | // permit persons to whom the Software is furnished to do so, subject to
16 | // the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be
19 | // included in all copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 | //
29 |
30 |
31 | using System;
32 |
33 | namespace Tancoder.Torrent.Dht
34 | {
35 | public enum NodeState
36 | {
37 | Unknown,
38 | Good,
39 | Questionable,
40 | Bad
41 | }
42 | }
43 | #endif
--------------------------------------------------------------------------------
/Tancoder.Torrent/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的一般信息由以下
6 | // 控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle("Tancoder.Torrent")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Tancoder.Torrent")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | //将 ComVisible 设置为 false 将使此程序集中的类型
18 | //对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
19 | //请将此类型的 ComVisible 特性设置为 true。
20 | [assembly: ComVisible(false)]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid("b3fdea8e-20f3-4be3-b73a-505b45ba9501")]
24 |
25 | // 程序集的版本信息由下列四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 生成号
30 | // 修订号
31 | //
32 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
33 | // 方法是按如下所示使用“*”: :
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Tancoder.Torrent/Source/Check.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Tancoder.Torrent
4 | {
5 | public static class Check
6 | {
7 | static void DoCheck(object toCheck, string name)
8 | {
9 | if (toCheck == null)
10 | throw new ArgumentNullException(name);
11 | }
12 |
13 | static void IsNullOrEmpty(string toCheck, string name)
14 | {
15 | DoCheck(toCheck, name);
16 | if (toCheck.Length == 0)
17 | throw new ArgumentException("Cannot be empty", name);
18 | }
19 |
20 | public static void Address(object address)
21 | {
22 | DoCheck(address, "address");
23 | }
24 |
25 | public static void AddressRange(object addressRange)
26 | {
27 | DoCheck(addressRange, "addressRange");
28 | }
29 |
30 | public static void AddressRanges(object addressRanges)
31 | {
32 | DoCheck(addressRanges, "addressRanges");
33 | }
34 |
35 | public static void Announces(object announces)
36 | {
37 | DoCheck(announces, "announces");
38 | }
39 |
40 | public static void BaseDirectory(object baseDirectory)
41 | {
42 | DoCheck(baseDirectory, "baseDirectory");
43 | }
44 |
45 | internal static void BaseType(Type baseType)
46 | {
47 | DoCheck(baseType, "baseType");
48 | }
49 |
50 | internal static void Buffer(object buffer)
51 | {
52 | DoCheck(buffer, "buffer");
53 | }
54 |
55 | internal static void Cache(object cache)
56 | {
57 | DoCheck(cache, "cache");
58 | }
59 |
60 | public static void Data(object data)
61 | {
62 | DoCheck(data, "data");
63 | }
64 |
65 | public static void Destination (object destination)
66 | {
67 | DoCheck (destination, "destination");
68 | }
69 |
70 | public static void Endpoint(object endpoint)
71 | {
72 | DoCheck(endpoint, "endpoint");
73 | }
74 |
75 | public static void File(object file)
76 | {
77 | DoCheck(file, "file");
78 | }
79 |
80 | public static void Files(object files)
81 | {
82 | DoCheck(files, "files");
83 | }
84 |
85 | public static void FileSource(object fileSource)
86 | {
87 | DoCheck(fileSource, "fileSource");
88 | }
89 |
90 | public static void InfoHash(object infoHash)
91 | {
92 | DoCheck(infoHash, "infoHash");
93 | }
94 |
95 | public static void Key (object key)
96 | {
97 | DoCheck (key, "key");
98 | }
99 |
100 | public static void Limiter(object limiter)
101 | {
102 | DoCheck(limiter, "limiter");
103 | }
104 |
105 | public static void Listener(object listener)
106 | {
107 | DoCheck(listener, "listener");
108 | }
109 |
110 | public static void Location(object location)
111 | {
112 | DoCheck(location, "location");
113 | }
114 |
115 | public static void MagnetLink(object magnetLink)
116 | {
117 | DoCheck(magnetLink, "magnetLink");
118 | }
119 |
120 | public static void Manager(object manager)
121 | {
122 | DoCheck(manager, "manager");
123 | }
124 |
125 | public static void Mappings (object mappings)
126 | {
127 | DoCheck (mappings, "mappings");
128 | }
129 |
130 | public static void Metadata(object metadata)
131 | {
132 | DoCheck(metadata, "metadata");
133 | }
134 |
135 | public static void Name (object name)
136 | {
137 | DoCheck (name, "name");
138 | }
139 |
140 | public static void Path(object path)
141 | {
142 | DoCheck(path, "path");
143 | }
144 |
145 | public static void Paths (object paths)
146 | {
147 | DoCheck (paths, "paths");
148 | }
149 |
150 | public static void PathNotEmpty(string path)
151 | {
152 | IsNullOrEmpty(path, "path");
153 | }
154 |
155 | public static void Peer (object peer)
156 | {
157 | DoCheck (peer, "peer");
158 | }
159 |
160 | public static void Peers (object peers)
161 | {
162 | DoCheck (peers, "peers");
163 | }
164 |
165 | public static void Picker(object picker)
166 | {
167 | DoCheck(picker, "picker");
168 | }
169 |
170 | public static void Result(object result)
171 | {
172 | DoCheck(result, "result");
173 | }
174 |
175 | public static void SavePath(object savePath)
176 | {
177 | DoCheck(savePath, "savePath");
178 | }
179 |
180 | public static void Settings(object settings)
181 | {
182 | DoCheck(settings, "settings");
183 | }
184 |
185 | internal static void SpecificType(Type specificType)
186 | {
187 | DoCheck(specificType, "specificType");
188 | }
189 |
190 | public static void Stream(object stream)
191 | {
192 | DoCheck(stream, "stream");
193 | }
194 |
195 | public static void Torrent(object torrent)
196 | {
197 | DoCheck(torrent, "torrent");
198 | }
199 |
200 | public static void TorrentInformation(object torrentInformation)
201 | {
202 | DoCheck(torrentInformation, "torrentInformation");
203 | }
204 |
205 | public static void TorrentSave(object torrentSave)
206 | {
207 | DoCheck(torrentSave, "torrentSave");
208 | }
209 |
210 | public static void Tracker(object tracker)
211 | {
212 | DoCheck(tracker, "tracker");
213 | }
214 |
215 | public static void Url(object url)
216 | {
217 | DoCheck(url, "url");
218 | }
219 |
220 | public static void Uri(Uri uri)
221 | {
222 | DoCheck(uri, "uri");
223 | }
224 |
225 | public static void Value(object value)
226 | {
227 | DoCheck(value, "value");
228 | }
229 |
230 | public static void Writer(object writer)
231 | {
232 | DoCheck(writer, "writer");
233 | }
234 | }
235 | }
--------------------------------------------------------------------------------
/Tancoder.Torrent/Source/Enums.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Enums.cs
3 | //
4 | // Authors:
5 | // Alan McGovern alan.mcgovern@gmail.com
6 | //
7 | // Copyright (C) 2006 Alan McGovern
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining
10 | // a copy of this software and associated documentation files (the
11 | // "Software"), to deal in the Software without restriction, including
12 | // without limitation the rights to use, copy, modify, merge, publish,
13 | // distribute, sublicense, and/or sell copies of the Software, and to
14 | // permit persons to whom the Software is furnished to do so, subject to
15 | // the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be
18 | // included in all copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 | //
28 |
29 |
30 |
31 | using System;
32 |
33 | namespace Tancoder.Torrent
34 | {
35 | public enum DhtState
36 | {
37 | NotReady,
38 | Initialising,
39 | Ready
40 | }
41 | }
42 |
43 | namespace Tancoder.Torrent.Common
44 | {
45 | public enum ListenerStatus
46 | {
47 | Listening,
48 | PortNotFree,
49 | NotListening
50 | }
51 |
52 | public enum PeerStatus
53 | {
54 | Available,
55 | Connecting,
56 | Connected
57 | }
58 |
59 | public enum Direction
60 | {
61 | None,
62 | Incoming,
63 | Outgoing
64 | }
65 |
66 | public enum TorrentState
67 | {
68 | Stopped,
69 | Paused,
70 | Downloading,
71 | Seeding,
72 | Hashing,
73 | Stopping,
74 | Error,
75 | Metadata
76 | }
77 |
78 | public enum Priority
79 | {
80 | DoNotDownload = 0,
81 | Lowest = 1,
82 | Low = 2,
83 | Normal = 4,
84 | High = 8,
85 | Highest = 16,
86 | Immediate = 32
87 | }
88 |
89 | public enum TrackerState
90 | {
91 | Ok,
92 | Offline,
93 | InvalidResponse
94 | }
95 |
96 | public enum TorrentEvent
97 | {
98 | None,
99 | Started,
100 | Stopped,
101 | Completed
102 | }
103 |
104 | public enum PeerConnectionEvent
105 | {
106 | IncomingConnectionReceived,
107 | OutgoingConnectionCreated,
108 | Disconnected
109 | }
110 |
111 | public enum PieceEvent
112 | {
113 | BlockWriteQueued,
114 | BlockNotRequested,
115 | BlockWrittenToDisk,
116 | HashPassed,
117 | HashFailed
118 | }
119 |
120 | public enum PeerListType
121 | {
122 | NascentPeers,
123 | CandidatePeers,
124 | OptimisticUnchokeCandidatePeers
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/Tancoder.Torrent/Source/IMessage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace Tancoder.Torrent.Client.Messages
6 | {
7 | interface IMessage
8 | {
9 | int ByteLength { get;}
10 |
11 | byte[] Encode();
12 | int Encode(byte[] buffer, int offset);
13 |
14 | void Decode(byte[] buffer, int offset, int length);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Tancoder.Torrent/Source/Message.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Message.cs
3 | //
4 | // Authors:
5 | // Alan McGovern alan.mcgovern@gmail.com
6 | //
7 | // Copyright (C) 2008 Alan McGovern
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining
10 | // a copy of this software and associated documentation files (the
11 | // "Software"), to deal in the Software without restriction, including
12 | // without limitation the rights to use, copy, modify, merge, publish,
13 | // distribute, sublicense, and/or sell copies of the Software, and to
14 | // permit persons to whom the Software is furnished to do so, subject to
15 | // the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be
18 | // included in all copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 | //
28 |
29 |
30 |
31 | using System;
32 | using System.Collections.Generic;
33 | using System.Text;
34 | using System.Net;
35 |
36 | namespace Tancoder.Torrent.Client.Messages
37 | {
38 | public abstract class Message : IMessage
39 | {
40 | public abstract int ByteLength { get; }
41 |
42 | protected int CheckWritten(int written)
43 | {
44 | if (written != ByteLength)
45 | throw new MessageException("Message encoded incorrectly. Incorrect number of bytes written");
46 | return written;
47 | }
48 |
49 | public abstract void Decode(byte[] buffer, int offset, int length);
50 |
51 | public byte[] Encode()
52 | {
53 | byte[] buffer = new byte[ByteLength];
54 | Encode(buffer, 0);
55 | return buffer;
56 | }
57 |
58 | public abstract int Encode(byte[] buffer, int offset);
59 |
60 | static public byte ReadByte(byte[] buffer, int offset)
61 | {
62 | return buffer[offset];
63 | }
64 |
65 | static public byte ReadByte(byte[] buffer, ref int offset)
66 | {
67 | byte b = buffer[offset];
68 | offset++;
69 | return b;
70 | }
71 |
72 | static public byte[] ReadBytes(byte[] buffer, int offset, int count)
73 | {
74 | return ReadBytes(buffer, ref offset, count);
75 | }
76 |
77 | static public byte[] ReadBytes(byte[] buffer, ref int offset, int count)
78 | {
79 | byte[] result = new byte[count];
80 | Buffer.BlockCopy(buffer, offset, result, 0, count);
81 | offset += count;
82 | return result;
83 | }
84 |
85 | static public short ReadShort(byte[] buffer, int offset)
86 | {
87 | return ReadShort(buffer, ref offset);
88 | }
89 |
90 | static public short ReadShort(byte[] buffer, ref int offset)
91 | {
92 | short ret = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(buffer, offset));
93 | offset += 2;
94 | return ret;
95 | }
96 |
97 | static public string ReadString(byte[] buffer, int offset, int count)
98 | {
99 | return ReadString(buffer, ref offset, count);
100 | }
101 |
102 | static public string ReadString(byte[] buffer, ref int offset, int count)
103 | {
104 | string s = System.Text.Encoding.ASCII.GetString(buffer, offset, count);
105 | offset += count;
106 | return s;
107 | }
108 |
109 | static public int ReadInt(byte[] buffer, int offset)
110 | {
111 | return ReadInt(buffer, ref offset);
112 | }
113 |
114 | static public int ReadInt(byte[] buffer, ref int offset)
115 | {
116 | int ret = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(buffer, offset));
117 | offset += 4;
118 | return ret;
119 | }
120 |
121 | static public long ReadLong(byte[] buffer, int offset)
122 | {
123 | return ReadLong(buffer, ref offset);
124 | }
125 |
126 | static public long ReadLong(byte[] buffer, ref int offset)
127 | {
128 | long ret = IPAddress.NetworkToHostOrder(BitConverter.ToInt64(buffer, offset));
129 | offset += 8;
130 | return ret;
131 | }
132 |
133 | static public int Write(byte[] buffer, int offset, byte value)
134 | {
135 | buffer[offset] = value;
136 | return 1;
137 | }
138 |
139 | static public int Write(byte[] dest, int destOffset, byte[] src, int srcOffset, int count)
140 | {
141 | Buffer.BlockCopy(src, srcOffset, dest, destOffset, count);
142 | return count;
143 | }
144 |
145 | static public int Write(byte[] buffer, int offset, ushort value)
146 | {
147 | return Write(buffer, offset, (short)value);
148 | }
149 |
150 | static public int Write(byte[] buffer, int offset, short value)
151 | {
152 | offset += Write(buffer, offset, (byte)(value >> 8));
153 | offset += Write(buffer, offset, (byte)value);
154 | return 2;
155 | }
156 |
157 | static public int Write(byte[] buffer, int offset, int value)
158 | {
159 | offset += Write(buffer, offset, (byte)(value >> 24));
160 | offset += Write(buffer, offset, (byte)(value >> 16));
161 | offset += Write(buffer, offset, (byte)(value >> 8));
162 | offset += Write(buffer, offset, (byte)(value));
163 | return 4;
164 | }
165 |
166 | static public int Write(byte[] buffer, int offset, uint value)
167 | {
168 | return Write(buffer, offset, (int)value);
169 | }
170 |
171 | static public int Write(byte[] buffer, int offset, long value)
172 | {
173 | offset += Write(buffer, offset, (int)(value >> 32));
174 | offset += Write(buffer, offset, (int)value);
175 | return 8;
176 | }
177 |
178 | static public int Write(byte[] buffer, int offset, ulong value)
179 | {
180 | return Write(buffer, offset, (long)value);
181 | }
182 |
183 | static public int Write(byte[] buffer, int offset, byte[] value)
184 | {
185 | return Write(buffer, offset, value, 0, value.Length);
186 | }
187 |
188 | static public int WriteAscii(byte[] buffer, int offset, string text)
189 | {
190 | for (int i = 0; i < text.Length; i++)
191 | Write(buffer, offset + i, (byte)text[i]);
192 | return text.Length;
193 | }
194 | }
195 | }
--------------------------------------------------------------------------------
/Tancoder.Torrent/Source/ToolBox.cs:
--------------------------------------------------------------------------------
1 | //
2 | // ToolBox.cs
3 | //
4 | // Authors:
5 | // Alan McGovern alan.mcgovern@gmail.com
6 | //
7 | // Copyright (C) 2006 Alan McGovern
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining
10 | // a copy of this software and associated documentation files (the
11 | // "Software"), to deal in the Software without restriction, including
12 | // without limitation the rights to use, copy, modify, merge, publish,
13 | // distribute, sublicense, and/or sell copies of the Software, and to
14 | // permit persons to whom the Software is furnished to do so, subject to
15 | // the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be
18 | // included in all copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 | //
28 |
29 |
30 |
31 | using System;
32 | using System.Collections;
33 | using System.Text;
34 | using System.Collections.Generic;
35 | using System.Threading;
36 | //using Tancoder.Torrent.Client.Encryption;
37 |
38 | namespace Tancoder.Torrent.Common
39 | {
40 | public delegate long Operation(T target);
41 |
42 | public static class Toolbox
43 | {
44 | private static Random r = new Random();
45 | public static int Count(IEnumerable enumerable, Predicate predicate)
46 | {
47 | int count = 0;
48 |
49 | foreach (T t in enumerable)
50 | if (predicate(t))
51 | count++;
52 |
53 | return count;
54 | }
55 |
56 | public static long Accumulate(IEnumerable enumerable, Operation action)
57 | {
58 | long count = 0;
59 |
60 | foreach (T t in enumerable)
61 | count += action(t);
62 |
63 | return count;
64 | }
65 |
66 | public static void RaiseAsyncEvent(EventHandler e, object o, T args)
67 | where T : EventArgs
68 | {
69 | if (e == null)
70 | return;
71 |
72 | ThreadPool.QueueUserWorkItem(delegate {
73 | if (e != null)
74 | e(o, args);
75 | });
76 | }
77 | ///
78 | /// Randomizes the contents of the array
79 | ///
80 | ///
81 | ///
82 | public static void Randomize(List array)
83 | {
84 | List clone = new List(array);
85 | array.Clear();
86 |
87 | while (clone.Count > 0)
88 | {
89 | int index = r.Next(0, clone.Count);
90 | array.Add(clone[index]);
91 | clone.RemoveAt(index);
92 | }
93 | }
94 |
95 | ///
96 | /// Switches the positions of two elements in an array
97 | ///
98 | ///
99 | ///
100 | ///
101 | ///
102 | public static void Switch(IList array, int first, int second)
103 | {
104 | T obj = array[first];
105 | array[first] = array[second];
106 | array[second] = obj;
107 | }
108 |
109 | ///
110 | /// Checks to see if the contents of two byte arrays are equal
111 | ///
112 | /// The first array
113 | /// The second array
114 | /// True if the arrays are equal, false if they aren't
115 | public static bool ByteMatch(byte[] array1, byte[] array2)
116 | {
117 | if (array1 == null)
118 | throw new ArgumentNullException("array1");
119 | if (array2 == null)
120 | throw new ArgumentNullException("array2");
121 |
122 | if (array1.Length != array2.Length)
123 | return false;
124 |
125 | return ByteMatch(array1, 0, array2, 0, array1.Length);
126 | }
127 |
128 | ///
129 | /// Checks to see if the contents of two byte arrays are equal
130 | ///
131 | /// The first array
132 | /// The second array
133 | /// The starting index for the first array
134 | /// The starting index for the second array
135 | /// The number of bytes to check
136 | ///
137 | public static bool ByteMatch(byte[] array1, int offset1, byte[] array2, int offset2, int count)
138 | {
139 | if (array1 == null)
140 | throw new ArgumentNullException("array1");
141 | if (array2 == null)
142 | throw new ArgumentNullException("array2");
143 |
144 | // If either of the arrays is too small, they're not equal
145 | if ((array1.Length - offset1) < count || (array2.Length - offset2) < count)
146 | return false;
147 |
148 | // Check if any elements are unequal
149 | for (int i = 0; i < count; i++)
150 | if (array1[offset1 + i] != array2[offset2 + i])
151 | return false;
152 |
153 | return true;
154 | }
155 |
156 | //internal static bool HasEncryption(EncryptionTypes available, EncryptionTypes check)
157 | //{
158 | // return (available & check) == check;
159 | //}
160 | }
161 | }
162 |
--------------------------------------------------------------------------------
/Tancoder.Torrent/Source/TorrentException.cs:
--------------------------------------------------------------------------------
1 | //
2 | // TorrentException.cs
3 | //
4 | // Authors:
5 | // Alan McGovern alan.mcgovern@gmail.com
6 | //
7 | // Copyright (C) 2006 Alan McGovern
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining
10 | // a copy of this software and associated documentation files (the
11 | // "Software"), to deal in the Software without restriction, including
12 | // without limitation the rights to use, copy, modify, merge, publish,
13 | // distribute, sublicense, and/or sell copies of the Software, and to
14 | // permit persons to whom the Software is furnished to do so, subject to
15 | // the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be
18 | // included in all copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 | //
28 |
29 |
30 |
31 | using System;
32 | using System.Collections.Generic;
33 | using System.Text;
34 |
35 | namespace Tancoder.Torrent.Common
36 | {
37 | [Serializable]
38 | public class TorrentException : Exception
39 | {
40 | public TorrentException()
41 | : base()
42 | {
43 | }
44 |
45 | public TorrentException(string message)
46 | : base(message)
47 | {
48 | }
49 |
50 | public TorrentException(string message, Exception innerException)
51 | : base(message, innerException)
52 | {
53 | }
54 |
55 | public TorrentException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
56 | : base(info, context)
57 | {
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/Tancoder.Torrent/Source/UriHelper.cs:
--------------------------------------------------------------------------------
1 | //
2 | // System.Web.HttpUtility/HttpEncoder
3 | //
4 | // Authors:
5 | // Patrik Torstensson (Patrik.Torstensson@labs2.com)
6 | // Wictor Wilén (decode/encode functions) (wictor@ibizkit.se)
7 | // Tim Coleman (tim@timcoleman.com)
8 | // Gonzalo Paniagua Javier (gonzalo@ximian.com)
9 | // Marek Habersack
10 | //
11 | // Copyright (C) 2005-2010 Novell, Inc (http://www.novell.com)
12 | //
13 | // Permission is hereby granted, free of charge, to any person obtaining
14 | // a copy of this software and associated documentation files (the
15 | // "Software"), to deal in the Software without restriction, including
16 | // without limitation the rights to use, copy, modify, merge, publish,
17 | // distribute, sublicense, and/or sell copies of the Software, and to
18 | // permit persons to whom the Software is furnished to do so, subject to
19 | // the following conditions:
20 | //
21 | // The above copyright notice and this permission notice shall be
22 | // included in all copies or substantial portions of the Software.
23 | //
24 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 | //
32 |
33 | // THIS FILE IS COPIED/PASTED FROM THE MONO SOURCE TREE TO AVOID
34 | // A DEPENDENCY ON SYSTEM.WEB WHICH IS NOT ALWAYS AVAILABLE.
35 |
36 | using System;
37 | using System.Text;
38 | using System.IO;
39 | using System.Collections.Generic;
40 |
41 | namespace Tancoder.Torrent
42 | {
43 | static class UriHelper
44 | {
45 | static readonly char [] hexChars = "0123456789abcdef".ToCharArray ();
46 |
47 | public static string UrlEncode (byte[] bytes)
48 | {
49 | if (bytes == null)
50 | throw new ArgumentNullException ("bytes");
51 |
52 | var result = new MemoryStream (bytes.Length);
53 | for (int i = 0; i < bytes.Length; i++)
54 | UrlEncodeChar ((char)bytes [i], result, false);
55 |
56 | return Encoding.ASCII.GetString (result.ToArray());
57 | }
58 |
59 | public static byte [] UrlDecode (string s)
60 | {
61 | if (null == s)
62 | return null;
63 |
64 | var e = Encoding.UTF8;
65 | if (s.IndexOf ('%') == -1 && s.IndexOf ('+') == -1)
66 | return e.GetBytes (s);
67 |
68 | long len = s.Length;
69 | var bytes = new List ();
70 | int xchar;
71 | char ch;
72 |
73 | for (int i = 0; i < len; i++) {
74 | ch = s [i];
75 | if (ch == '%' && i + 2 < len && s [i + 1] != '%') {
76 | if (s [i + 1] == 'u' && i + 5 < len) {
77 | // unicode hex sequence
78 | xchar = GetChar (s, i + 2, 4);
79 | if (xchar != -1) {
80 | WriteCharBytes (bytes, (char)xchar, e);
81 | i += 5;
82 | } else
83 | WriteCharBytes (bytes, '%', e);
84 | } else if ((xchar = GetChar (s, i + 1, 2)) != -1) {
85 | WriteCharBytes (bytes, (char)xchar, e);
86 | i += 2;
87 | } else {
88 | WriteCharBytes (bytes, '%', e);
89 | }
90 | continue;
91 | }
92 |
93 | if (ch == '+')
94 | WriteCharBytes (bytes, ' ', e);
95 | else
96 | WriteCharBytes (bytes, ch, e);
97 | }
98 |
99 | return bytes.ToArray ();
100 | }
101 |
102 | static void UrlEncodeChar (char c, Stream result, bool isUnicode) {
103 | if (c > ' ' && NotEncoded (c)) {
104 | result.WriteByte ((byte)c);
105 | return;
106 | }
107 | if (c==' ') {
108 | result.WriteByte ((byte)'+');
109 | return;
110 | }
111 | if ( (c < '0') ||
112 | (c < 'A' && c > '9') ||
113 | (c > 'Z' && c < 'a') ||
114 | (c > 'z')) {
115 | if (isUnicode && c > 127) {
116 | result.WriteByte ((byte)'%');
117 | result.WriteByte ((byte)'u');
118 | result.WriteByte ((byte)'0');
119 | result.WriteByte ((byte)'0');
120 | }
121 | else
122 | result.WriteByte ((byte)'%');
123 |
124 | int idx = ((int) c) >> 4;
125 | result.WriteByte ((byte)hexChars [idx]);
126 | idx = ((int) c) & 0x0F;
127 | result.WriteByte ((byte)hexChars [idx]);
128 | }
129 | else {
130 | result.WriteByte ((byte)c);
131 | }
132 | }
133 |
134 | static int GetChar (string str, int offset, int length)
135 | {
136 | int val = 0;
137 | int end = length + offset;
138 | for (int i = offset; i < end; i++) {
139 | char c = str [i];
140 | if (c > 127)
141 | return -1;
142 |
143 | int current = GetInt ((byte) c);
144 | if (current == -1)
145 | return -1;
146 | val = (val << 4) + current;
147 | }
148 |
149 | return val;
150 | }
151 |
152 | static int GetInt (byte b)
153 | {
154 | char c = (char) b;
155 | if (c >= '0' && c <= '9')
156 | return c - '0';
157 |
158 | if (c >= 'a' && c <= 'f')
159 | return c - 'a' + 10;
160 |
161 | if (c >= 'A' && c <= 'F')
162 | return c - 'A' + 10;
163 |
164 | return -1;
165 | }
166 |
167 | static bool NotEncoded (char c)
168 | {
169 | return c == '!' || c == '(' || c == ')' || c == '*' || c == '-' || c == '.' || c == '_' || c == '\'';
170 | }
171 |
172 | static void WriteCharBytes (List buf, char ch, Encoding e)
173 | {
174 | if (ch > 255) {
175 | foreach (byte b in e.GetBytes (new char[] { ch }))
176 | buf.Add (b);
177 | } else
178 | buf.Add ((byte)ch);
179 | }
180 | }
181 | }
182 |
--------------------------------------------------------------------------------
/Tancoder.Torrent/Source/VersionInfo.cs:
--------------------------------------------------------------------------------
1 | //
2 | // VersionInfo.cs
3 | //
4 | // Authors:
5 | // Alan McGovern alan.mcgovern@gmail.com
6 | //
7 | // Copyright (C) 2006 Alan McGovern
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining
10 | // a copy of this software and associated documentation files (the
11 | // "Software"), to deal in the Software without restriction, including
12 | // without limitation the rights to use, copy, modify, merge, publish,
13 | // distribute, sublicense, and/or sell copies of the Software, and to
14 | // permit persons to whom the Software is furnished to do so, subject to
15 | // the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be
18 | // included in all copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 | //
28 |
29 |
30 |
31 | using System;
32 | using System.Collections.Generic;
33 | using System.Reflection;
34 | using System.Runtime.CompilerServices;
35 | using System.Text;
36 |
37 | namespace Tancoder.Torrent.Common
38 | {
39 | public static class VersionInfo
40 | {
41 | ///
42 | /// Protocol string for version 1.0 of Bittorrent Protocol
43 | ///
44 | public static readonly string ProtocolStringV100 = "BitTorrent protocol";
45 |
46 | public static readonly string DhtClientVersion = "TT00";
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Tancoder.Torrent/Tancoder.Torrent.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {B3FDEA8E-20F3-4BE3-B73A-505B45BA9501}
8 | Library
9 | Properties
10 | Tancoder.Torrent
11 | Tancoder.Torrent
12 | v4.5.2
13 | 512
14 |
15 |
16 |
17 |
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 | true
26 | false
27 |
28 |
29 | pdbonly
30 | true
31 | bin\Release\
32 | TRACE
33 | prompt
34 | 4
35 | true
36 | false
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
124 |
--------------------------------------------------------------------------------
/Tancoder.Torrent/TransactionId.cs:
--------------------------------------------------------------------------------
1 | #if !DISABLE_DHT
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Text;
5 | using Tancoder.Torrent.BEncoding;
6 |
7 | namespace Tancoder.Torrent.Dht
8 | {
9 | public static class TransactionId
10 | {
11 | private static byte[] current = new byte[2];
12 |
13 | public static BEncodedString NextId()
14 | {
15 | lock (current)
16 | {
17 | BEncodedString result = new BEncodedString((byte[])current.Clone());
18 | if (current[0]++ == 255)
19 | current[1]++;
20 | return result;
21 | }
22 | }
23 | }
24 | }
25 | #endif
--------------------------------------------------------------------------------
/Tancoder.Torrent/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhangkong828/DHTSpider/49f0055c78ed718bcda77e0466f25c277af9577a/demo.png
--------------------------------------------------------------------------------