summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--TODO6
-rw-r--r--po/aria2c.pot191
-rw-r--r--po/ja.gmobin14810 -> 14810 bytes
-rw-r--r--po/ja.po201
-rw-r--r--src/AbstractDiskWriter.cc63
-rw-r--r--src/AbstractDiskWriter.h9
-rw-r--r--src/BitfieldMan.cc277
-rw-r--r--src/BitfieldMan.h90
-rw-r--r--src/ConsoleDownloadEngine.cc34
-rw-r--r--src/ConsoleDownloadEngine.h7
-rw-r--r--src/Data.cc81
-rw-r--r--src/Data.h54
-rw-r--r--src/DefaultDiskWriter.cc7
-rw-r--r--src/DefaultDiskWriter.h2
-rw-r--r--src/Dictionary.cc57
-rw-r--r--src/Dictionary.h51
-rw-r--r--src/Directory.cc59
-rw-r--r--src/Directory.h44
-rw-r--r--src/DiskWriter.h6
-rw-r--r--src/DownloadEngine.cc40
-rw-r--r--src/DownloadEngine.h10
-rw-r--r--src/File.cc8
-rw-r--r--src/File.h2
-rw-r--r--src/HandshakeMessage.h47
-rw-r--r--src/HttpConnection.cc71
-rw-r--r--src/HttpConnection.h6
-rw-r--r--src/HttpRequestCommand.cc9
-rw-r--r--src/HttpRequestCommand.h2
-rw-r--r--src/HttpResponseCommand.cc36
-rw-r--r--src/List.cc47
-rw-r--r--src/List.h48
-rw-r--r--src/Makefile.am32
-rw-r--r--src/Makefile.in462
-rw-r--r--src/MetaEntry.h40
-rw-r--r--src/MetaEntryVisitor.h34
-rw-r--r--src/MetaFileUtil.cc170
-rw-r--r--src/MetaFileUtil.h50
-rw-r--r--src/Peer.cc48
-rw-r--r--src/Peer.h115
-rw-r--r--src/PeerAbstractCommand.cc181
-rw-r--r--src/PeerAbstractCommand.h58
-rw-r--r--src/PeerConnection.cc378
-rw-r--r--src/PeerConnection.h82
-rw-r--r--src/PeerInitiateConnectionCommand.cc74
-rw-r--r--src/PeerInitiateConnectionCommand.h40
-rw-r--r--src/PeerInteractionCommand.cc477
-rw-r--r--src/PeerInteractionCommand.h76
-rw-r--r--src/PeerListenCommand.cc91
-rw-r--r--src/PeerListenCommand.h42
-rw-r--r--src/PeerMessage.cc72
-rw-r--r--src/PeerMessage.h83
-rw-r--r--src/PeerMessageUtil.cc231
-rw-r--r--src/PeerMessageUtil.h51
-rw-r--r--src/PendingMessage.cc115
-rw-r--r--src/PendingMessage.h71
-rw-r--r--src/Piece.cc84
-rw-r--r--src/Piece.h81
-rw-r--r--src/PreAllocationDiskWriter.cc51
-rw-r--r--src/PreAllocationDiskWriter.h6
-rw-r--r--src/Request.cc2
-rw-r--r--src/Request.h13
-rw-r--r--src/RequestSlot.cc70
-rw-r--r--src/RequestSlot.h63
-rw-r--r--src/RequestSlotMan.cc98
-rw-r--r--src/RequestSlotMan.h72
-rw-r--r--src/ShaVisitor.cc82
-rw-r--r--src/ShaVisitor.h47
-rw-r--r--src/Socket.cc8
-rw-r--r--src/Socket.h7
-rw-r--r--src/SocketCore.cc26
-rw-r--r--src/SocketCore.h16
-rw-r--r--src/TorrentAutoSaveCommand.cc37
-rw-r--r--src/TorrentAutoSaveCommand.h40
-rw-r--r--src/TorrentConsoleDownloadEngine.cc132
-rw-r--r--src/TorrentConsoleDownloadEngine.h52
-rw-r--r--src/TorrentDownloadEngine.cc32
-rw-r--r--src/TorrentDownloadEngine.h38
-rw-r--r--src/TorrentMan.cc505
-rw-r--r--src/TorrentMan.h217
-rw-r--r--src/TrackerDownloadCommand.cc99
-rw-r--r--src/TrackerDownloadCommand.h50
-rw-r--r--src/TrackerInitCommand.cc67
-rw-r--r--src/TrackerInitCommand.h40
-rw-r--r--src/TrackerUpdateCommand.cc126
-rw-r--r--src/TrackerUpdateCommand.h42
-rw-r--r--src/Util.cc72
-rw-r--r--src/Util.h9
-rw-r--r--src/common.h2
-rw-r--r--src/main.cc209
-rw-r--r--src/message.h12
-rw-r--r--src/prefs.h2
-rw-r--r--test/BitfieldManTest.cc76
-rw-r--r--test/DataTest.cc70
-rw-r--r--test/DefaultDiskWriterTest.cc35
-rw-r--r--test/DictionaryTest.cc35
-rw-r--r--test/FileTest.cc7
-rw-r--r--test/ListTest.cc33
-rw-r--r--test/Makefile.am11
-rw-r--r--test/Makefile.in155
-rw-r--r--test/MetaFileUtilTest.cc77
-rw-r--r--test/PeerMessageUtilTest.cc352
-rw-r--r--test/ShaVisitorTest.cc60
-rw-r--r--test/TorrentManTest.cc188
-rw-r--r--test/test.torrent1
105 files changed, 7899 insertions, 352 deletions
diff --git a/ChangeLog b/ChangeLog
index 3ff83770..1c491187 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2006-03-17 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
+
+ * SocketCore.cc: remove the assignment of addrinfo.ai_addr.
+
2006-03-09 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
* ChunkedEncoding.{h,cc}: fixed the bug that if chunk data is binary,
diff --git a/TODO b/TODO
index e05708c1..671f9b44 100644
--- a/TODO
+++ b/TODO
@@ -5,4 +5,8 @@
* Better HTTP status handling
* Download files listed in a specifed file.
* check MD5 checksum
-* Add the feature which adds or removes URLs on-the-fly. \ No newline at end of file
+* Add the feature which adds or removes URLs on-the-fly.
+* Tracker UDP protocol
+* no-compact peers format
+* Add port range command-line option
+* Add max peers command-line option \ No newline at end of file
diff --git a/po/aria2c.pot b/po/aria2c.pot
index d6c5bf3c..3c0f1734 100644
--- a/po/aria2c.pot
+++ b/po/aria2c.pot
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: http://aria2.sourceforge.net/\n"
-"POT-Creation-Date: 2006-03-07 22:57+0900\n"
+"POT-Creation-Date: 2006-03-21 23:10+0900\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -77,122 +77,135 @@ msgstr ""
msgid "CUID#%d - Unregistering cuid from segmentManager."
msgstr ""
-#: src/message.h:39
+#: src/message.h:48
#, c-format
msgid "The segment file %s exists."
msgstr ""
-#: src/message.h:40
+#: src/message.h:49
#, c-format
msgid "The segment file %s does not exist."
msgstr ""
-#: src/message.h:41
+#: src/message.h:50
#, c-format
msgid "Saving the segment file %s"
msgstr ""
-#: src/message.h:42
+#: src/message.h:51
msgid "The segment file was saved successfully."
msgstr ""
-#: src/message.h:43
+#: src/message.h:52
#, c-format
msgid "Loading the segment file %s."
msgstr ""
-#: src/message.h:44
+#: src/message.h:53
msgid "The segment file was loaded successfully."
msgstr ""
-#: src/message.h:46
+#: src/message.h:55
msgid "Timeout."
msgstr ""
-#: src/message.h:47
+#: src/message.h:56
msgid "Invalid chunk size."
msgstr ""
-#: src/message.h:48
+#: src/message.h:57
#, c-format
msgid "Too large chunk. size = %d"
msgstr ""
-#: src/message.h:49
+#: src/message.h:58
msgid "Invalid header."
msgstr ""
-#: src/message.h:50
+#: src/message.h:59
msgid "Invalid response."
msgstr ""
-#: src/message.h:51
+#: src/message.h:60
msgid "No header found."
msgstr ""
-#: src/message.h:52
+#: src/message.h:61
msgid "No status header."
msgstr ""
-#: src/message.h:53
+#: src/message.h:62
msgid "Proxy connection failed."
msgstr ""
-#: src/message.h:54
+#: src/message.h:63
msgid "Connection failed."
msgstr ""
-#: src/message.h:55
+#: src/message.h:64
#, c-format
msgid ""
"The requested filename and the previously registered one are not same. %s != "
"%s"
msgstr ""
-#: src/message.h:56
+#: src/message.h:65
#, c-format
msgid "The response status is not successful. status = %d"
msgstr ""
-#: src/message.h:57
+#: src/message.h:66
#, c-format
msgid "Too large file size. size = %lld"
msgstr ""
-#: src/message.h:58
+#: src/message.h:67
#, c-format
msgid "Transfer encoding %s is not supported."
msgstr ""
-#: src/message.h:59
+#: src/message.h:68
msgid "SSL initialization failed."
msgstr ""
-#: src/message.h:60
+#: src/message.h:69
#, c-format
msgid "Size mismatch %lld != %lld"
msgstr ""
-#: src/message.h:61
+#: src/message.h:70
msgid "Got EOF from the server."
msgstr ""
-#: src/main.cc:57
+#: src/main.cc:58
+#, c-format
+msgid ""
+"\n"
+"The download was complete. <%s>\n"
+msgstr ""
+
+#: src/main.cc:62
+msgid ""
+"\n"
+"The download was not complete because of errors. Check the log.\n"
+msgstr ""
+
+#: src/main.cc:73 src/main.cc:82
msgid ""
"\n"
"SIGINT signal received."
msgstr ""
-#: src/main.cc:72
+#: src/main.cc:104
#, c-format
msgid "Unrecognized URL or unsupported protocol: %s\n"
msgstr ""
-#: src/main.cc:78
+#: src/main.cc:110
msgid " version "
msgstr ""
-#: src/main.cc:82
+#: src/main.cc:114
msgid ""
"This program is free software; you can redistribute it and/or modify\n"
"it under the terms of the GNU General Public License as published by\n"
@@ -209,40 +222,40 @@ msgid ""
"Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n"
msgstr ""
-#: src/main.cc:96
+#: src/main.cc:128
#, c-format
msgid "Contact Info: %s\n"
msgstr ""
-#: src/main.cc:102
+#: src/main.cc:134
#, c-format
msgid "Usage: %s [options] URL ...\n"
msgstr ""
-#: src/main.cc:104
+#: src/main.cc:136
msgid "Options:"
msgstr ""
-#: src/main.cc:105
+#: src/main.cc:137
msgid " -d, --dir=DIR The directory to store downloaded file."
msgstr ""
-#: src/main.cc:106
+#: src/main.cc:138
msgid " -o, --out=FILE The file name for downloaded file."
msgstr ""
-#: src/main.cc:107
+#: src/main.cc:139
msgid ""
" -l, --log=LOG The file path to store log. If '-' is "
"specified,\n"
" log is written to stdout."
msgstr ""
-#: src/main.cc:109
+#: src/main.cc:141
msgid " -D, --daemon Run as daemon."
msgstr ""
-#: src/main.cc:110
+#: src/main.cc:142
msgid ""
" -s, --split=N Download a file using N connections. N must "
"be\n"
@@ -252,24 +265,24 @@ msgid ""
" N connections."
msgstr ""
-#: src/main.cc:114
+#: src/main.cc:146
msgid ""
" --retry-wait=SEC Set amount of time in second between requests\n"
" for errors. Specify a value between 0 and 60.\n"
" Default: 5"
msgstr ""
-#: src/main.cc:117
+#: src/main.cc:149
msgid " -t, --timeout=SEC Set timeout in second. Default: 60"
msgstr ""
-#: src/main.cc:118
+#: src/main.cc:150
msgid ""
" -m, --max-tries=N Set number of tries. 0 means unlimited.\n"
" Default: 5"
msgstr ""
-#: src/main.cc:120
+#: src/main.cc:152
msgid ""
" --min-segment-size=SIZE[K|M] Set minimum segment size. You can append\n"
" K or M(1K = 1024, 1M = 1024K). This\n"
@@ -277,40 +290,40 @@ msgid ""
" 1024."
msgstr ""
-#: src/main.cc:124
+#: src/main.cc:156
msgid ""
" --http-proxy=HOST:PORT Use HTTP proxy server. This affects to all\n"
" URLs."
msgstr ""
-#: src/main.cc:126
+#: src/main.cc:158
msgid " --http-user=USER Set HTTP user. This affects to all URLs."
msgstr ""
-#: src/main.cc:127
+#: src/main.cc:159
msgid ""
" --http-passwd=PASSWD Set HTTP password. This affects to all URLs."
msgstr ""
-#: src/main.cc:128
+#: src/main.cc:160
msgid ""
" --http-proxy-user=USER Set HTTP proxy user. This affects to all URLs"
msgstr ""
-#: src/main.cc:129
+#: src/main.cc:161
msgid ""
" --http-proxy-passwd=PASSWD Set HTTP proxy password. This affects to all "
"URLs."
msgstr ""
-#: src/main.cc:130
+#: src/main.cc:162
msgid ""
" --http-proxy-method=METHOD Set the method to use in proxy request.\n"
" METHOD is either 'get' or 'tunnel'.\n"
" Default: tunnel"
msgstr ""
-#: src/main.cc:133
+#: src/main.cc:165
msgid ""
" --http-auth-scheme=SCHEME Set HTTP authentication scheme. Currently, "
"basic\n"
@@ -321,23 +334,23 @@ msgid ""
" as well as --http-user and --http-passwd."
msgstr ""
-#: src/main.cc:137
+#: src/main.cc:169
msgid " --referer=REFERER Set Referer. This affects to all URLs."
msgstr ""
-#: src/main.cc:138
+#: src/main.cc:170
msgid ""
" --ftp-user=USER Set FTP user. This affects to all URLs.\n"
" Default: anonymous"
msgstr ""
-#: src/main.cc:140
+#: src/main.cc:172
msgid ""
" --ftp-passwd=PASSWD Set FTP password. This affects to all URLs.\n"
" Default: ARIA2USER@"
msgstr ""
-#: src/main.cc:142
+#: src/main.cc:174
msgid ""
" --ftp-type=TYPE Set FTP transfer type. TYPE is either "
"'binary'\n"
@@ -345,11 +358,11 @@ msgid ""
" Default: binary"
msgstr ""
-#: src/main.cc:145
+#: src/main.cc:177
msgid " -p, --ftp-pasv Use passive mode in FTP."
msgstr ""
-#: src/main.cc:146
+#: src/main.cc:178
msgid ""
" --ftp-via-http-proxy=METHOD Use HTTP proxy in FTP. METHOD is either 'get' "
"or\n"
@@ -357,98 +370,106 @@ msgid ""
" Default: tunnel"
msgstr ""
-#: src/main.cc:149
+#: src/main.cc:181
+msgid " --torrent-file=TORRENT_FILE The file path to .torrent file."
+msgstr ""
+
+#: src/main.cc:182
+msgid ""
+" --follow-torrent=true|false Setting this option to false prevents aria2 "
+"to\n"
+" enter BitTorrent mode even if the filename of\n"
+" downloaded file ends with .torrent.\n"
+" Default: true"
+msgstr ""
+
+#: src/main.cc:186
msgid " -v, --version Print the version number and exit."
msgstr ""
-#: src/main.cc:150
+#: src/main.cc:187
msgid " -h, --help Print this message and exit."
msgstr ""
-#: src/main.cc:153
+#: src/main.cc:190
msgid ""
" You can specify multiple URLs. All URLs must point to the same file\n"
" or downloading fails."
msgstr ""
-#: src/main.cc:156
+#: src/main.cc:193
msgid "Examples:"
msgstr ""
-#: src/main.cc:157
+#: src/main.cc:194
msgid " Download a file by 1 connection:"
msgstr ""
-#: src/main.cc:159
+#: src/main.cc:196
msgid " Download a file by 2 connections:"
msgstr ""
-#: src/main.cc:161
+#: src/main.cc:198
msgid " Download a file by 2 connections, each connects to a different server:"
msgstr ""
-#: src/main.cc:163
+#: src/main.cc:200
msgid " You can mix up different protocols:"
msgstr ""
-#: src/main.cc:166
+#: src/main.cc:202
+msgid " Download a torrent"
+msgstr ""
+
+#: src/main.cc:205
#, c-format
msgid "Reports bugs to %s"
msgstr ""
-#: src/main.cc:240
+#: src/main.cc:284
msgid "unrecognized proxy format"
msgstr ""
-#: src/main.cc:266
+#: src/main.cc:310
msgid "Currently, supported authentication scheme is basic."
msgstr ""
-#: src/main.cc:275
+#: src/main.cc:319
msgid "retry-wait must be between 0 and 60."
msgstr ""
-#: src/main.cc:292
+#: src/main.cc:336
msgid "ftp-type must be either 'binary' or 'ascii'."
msgstr ""
-#: src/main.cc:301
+#: src/main.cc:345
msgid "ftp-via-http-proxy must be either 'get' or 'tunnel'."
msgstr ""
-#: src/main.cc:319
+#: src/main.cc:363
msgid "min-segment-size invalid"
msgstr ""
-#: src/main.cc:330
+#: src/main.cc:374
msgid "http-proxy-method must be either 'get' or 'tunnel'."
msgstr ""
-#: src/main.cc:357
+#: src/main.cc:388
+msgid "follow-torrent must be either 'true' or 'false'."
+msgstr ""
+
+#: src/main.cc:414
msgid "split must be between 1 and 5."
msgstr ""
-#: src/main.cc:367
+#: src/main.cc:424
msgid "timeout must be between 1 and 600"
msgstr ""
-#: src/main.cc:376
+#: src/main.cc:433
msgid "max-tries invalid"
msgstr ""
-#: src/main.cc:398
+#: src/main.cc:456
msgid "specify at least one URL"
msgstr ""
-
-#: src/main.cc:449
-#, c-format
-msgid ""
-"\n"
-"The download was complete. <%s>\n"
-msgstr ""
-
-#: src/main.cc:451
-msgid ""
-"\n"
-"The download was not complete because of errors. Check the log.\n"
-msgstr ""
diff --git a/po/ja.gmo b/po/ja.gmo
index da5d6ee6..087c4e0a 100644
--- a/po/ja.gmo
+++ b/po/ja.gmo
Binary files differ
diff --git a/po/ja.po b/po/ja.po
index 7a4f6564..ce5e6f8d 100644
--- a/po/ja.po
+++ b/po/ja.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: aria2c 0.2.1\n"
"Report-Msgid-Bugs-To: http://aria2.sourceforge.net/\n"
-"POT-Creation-Date: 2006-03-07 22:57+0900\n"
+"POT-Creation-Date: 2006-03-21 23:10+0900\n"
"PO-Revision-Date: 2006-03-05 15:21+0900\n"
"Last-Translator: Tatsuhiro Tsujikawa <tujikawa@rednoah.com>\n"
"Language-Team: Japanese <ja@li.org>\n"
@@ -85,107 +85,124 @@ msgstr ""
msgid "CUID#%d - Unregistering cuid from segmentManager."
msgstr "CUID#%d - cuid ¤ò¥»¥°¥á¥ó¥È¥Þ¥Í¥¸¥ã¡¼¤«¤éºï½ü¤·¤Þ¤¹."
-#: src/message.h:39
+#: src/message.h:48
#, c-format
msgid "The segment file %s exists."
msgstr "¥»¥°¥á¥ó¥È¥Õ¥¡¥¤¥ë %s ¤¬Â¸ºß¤·¤Þ¤¹."
-#: src/message.h:40
+#: src/message.h:49
#, c-format
msgid "The segment file %s does not exist."
msgstr "¥»¥°¥á¥ó¥È¥Õ¥¡¥¤¥ë %s ¤¬Â¸ºß¤·¤Þ¤»¤ó."
-#: src/message.h:41
+#: src/message.h:50
#, c-format
msgid "Saving the segment file %s"
msgstr "¥»¥°¥á¥ó¥È¥Õ¥¡¥¤¥ë %s ¤òÊݸ¤·¤Æ¤¤¤Þ¤¹."
-#: src/message.h:42
+#: src/message.h:51
msgid "The segment file was saved successfully."
msgstr "¥»¥°¥á¥ó¥È¥Õ¥¡¥¤¥ë¤ÎÊݸ¤¬´°Î»¤·¤Þ¤·¤¿."
-#: src/message.h:43
+#: src/message.h:52
#, c-format
msgid "Loading the segment file %s."
msgstr "¥»¥°¥á¥ó¥È¥Õ¥¡¥¤¥ë %s ¤ò¥í¡¼¥É¤·¤Æ¤¤¤Þ¤¹."
-#: src/message.h:44
+#: src/message.h:53
msgid "The segment file was loaded successfully."
msgstr "¥»¥°¥á¥ó¥È¥Õ¥¡¥¤¥ë¤Î¥í¡¼¥É¤¬´°Î»¤·¤Þ¤·¤¿."
-#: src/message.h:46
+#: src/message.h:55
msgid "Timeout."
msgstr "¥¿¥¤¥à¥¢¥¦¥È¤·¤Þ¤·¤¿."
-#: src/message.h:47
+#: src/message.h:56
msgid "Invalid chunk size."
msgstr "chunk ¥µ¥¤¥º¤¬ÉÔÀµ¤Ç¤¹."
-#: src/message.h:48
+#: src/message.h:57
#, c-format
msgid "Too large chunk. size = %d"
msgstr "chunk ¥µ¥¤¥º (%d) ¤¬Â礭¤¹¤®¤Þ¤¹."
-#: src/message.h:49
+#: src/message.h:58
msgid "Invalid header."
msgstr "¥Ø¥Ã¥À¡¼¤¬ÉÔÀµ¤Ç¤¹."
-#: src/message.h:50
+#: src/message.h:59
msgid "Invalid response."
msgstr "¥µ¡¼¥Ð¡¼¤«¤éÉÔÀµ¤Ê¥ì¥¹¥Ý¥ó¥¹¤ò¼õ¤±¼è¤ê¤Þ¤·¤¿."
-#: src/message.h:51
+#: src/message.h:60
msgid "No header found."
msgstr "¥Ø¥Ã¥À¡¼¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó."
-#: src/message.h:52
+#: src/message.h:61
msgid "No status header."
msgstr "status ¥Ø¥Ã¥À¡¼¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó."
-#: src/message.h:53
+#: src/message.h:62
msgid "Proxy connection failed."
msgstr "Proxy Àܳ¤Ë¼ºÇÔ¤·¤Þ¤·¤¿."
-#: src/message.h:54
+#: src/message.h:63
msgid "Connection failed."
msgstr "Àܳ¤Ë¼ºÇÔ¤·¤Þ¤·¤¿."
-#: src/message.h:55
+#: src/message.h:64
#, c-format
msgid ""
"The requested filename and the previously registered one are not same. %s != "
"%s"
msgstr "¥ê¥¯¥¨¥¹¥È¤·¤¿¥Õ¥¡¥¤¥ë̾ (%s) ¤ÈÅÐÏ¿ºÑ¤ß¥Õ¥¡¥¤¥ë̾ (%s) ¤¬°Û¤Ê¤ê¤Þ¤¹."
-#: src/message.h:56
+#: src/message.h:65
#, c-format
msgid "The response status is not successful. status = %d"
msgstr "¥ì¥¹¥Ý¥ó¥¹¤Î¥¹¥Æ¡¼¥¿¥¹ (%d) ¤¬°Û¾ï¤Ç¤¹."
-#: src/message.h:57
+#: src/message.h:66
#, c-format
msgid "Too large file size. size = %lld"
msgstr "¥Õ¥¡¥¤¥ë¥µ¥¤¥º (%lld) ¤¬Â礭¤¹¤®¤Þ¤¹."
-#: src/message.h:58
+#: src/message.h:67
#, c-format
msgid "Transfer encoding %s is not supported."
msgstr "¥È¥é¥ó¥¹¥Õ¥¡¡¼¡¦¥¨¥ó¥³¡¼¥Ç¥£¥ó¥° %s ¤Ï¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤Þ¤»¤ó."
-#: src/message.h:59
+#: src/message.h:68
msgid "SSL initialization failed."
msgstr "SSL ½é´ü²½¤Ë¼ºÇÔ¤·¤Þ¤·¤¿."
-#: src/message.h:60
+#: src/message.h:69
#, c-format
msgid "Size mismatch %lld != %lld"
msgstr "¥µ¥¤¥º¤¬¹ç¤¤¤Þ¤»¤ó (%lld != %lld)"
-#: src/message.h:61
+#: src/message.h:70
msgid "Got EOF from the server."
msgstr "¥µ¡¼¥Ð¡¼¤«¤é EOF ¤ò¼õ¤±¤È¤ê¤Þ¤·¤¿."
-#: src/main.cc:57
+#: src/main.cc:58
+#, c-format
+msgid ""
+"\n"
+"The download was complete. <%s>\n"
+msgstr ""
+"\n"
+"<%s> ¤Î¥À¥¦¥ó¥í¡¼¥É¤¬´°Î»¤·¤Þ¤·¤¿.\n"
+
+#: src/main.cc:62
+msgid ""
+"\n"
+"The download was not complete because of errors. Check the log.\n"
+msgstr ""
+"\n"
+"¥À¥¦¥ó¥í¡¼¥É¤Ï¥¨¥é¡¼¤Î¤¿¤á´°Î»¤·¤Æ¤¤¤Þ¤»¤ó. ¥í¥°¤ò³Îǧ¤·¤Æ¤¯¤À¤µ¤¤.\n"
+
+#: src/main.cc:73 src/main.cc:82
msgid ""
"\n"
"SIGINT signal received."
@@ -193,18 +210,18 @@ msgstr ""
"\n"
"SIGINT ¥·¥°¥Ê¥ë¤ò¼õ¤±¼è¤ê¤Þ¤·¤¿."
-#: src/main.cc:72
+#: src/main.cc:104
#, c-format
msgid "Unrecognized URL or unsupported protocol: %s\n"
msgstr ""
"%s ¤Ï, Íý²ò¤Ç¤­¤Ê¤¤ URL ¥Õ¥©¡¼¥Þ¥Ã¥È, ¤Þ¤¿¤Ï, ¥µ¥Ý¡¼¥È¤µ¤ì¤Ê¤¤¥×¥í¥È¥³¥ë¤Ç"
"¤¹.\n"
-#: src/main.cc:78
+#: src/main.cc:110
msgid " version "
msgstr " ¥Ð¡¼¥¸¥ç¥ó "
-#: src/main.cc:82
+#: src/main.cc:114
msgid ""
"This program is free software; you can redistribute it and/or modify\n"
"it under the terms of the GNU General Public License as published by\n"
@@ -235,31 +252,31 @@ msgstr ""
"Temple Place, Suite 330, Boston, MA 02111-1307 USA)¡£\n"
"(Ìõ: http://www.opensource.jp/gpl/gpl.ja.html.euc-jp)\n"
-#: src/main.cc:96
+#: src/main.cc:128
#, c-format
msgid "Contact Info: %s\n"
msgstr "Ï¢ÍíÀè: %s\n"
-#: src/main.cc:102
+#: src/main.cc:134
#, c-format
msgid "Usage: %s [options] URL ...\n"
msgstr "»È¤¤Êý: %s [¥ª¥×¥·¥ç¥ó] URL ...\n"
-#: src/main.cc:104
+#: src/main.cc:136
msgid "Options:"
msgstr "¥ª¥×¥·¥ç¥ó:"
-#: src/main.cc:105
+#: src/main.cc:137
msgid " -d, --dir=DIR The directory to store downloaded file."
msgstr ""
" -d, --dir=DIR ¥À¥¦¥ó¥í¡¼¥É¤·¤¿¥Õ¥¡¥¤¥ë¤òÊݸ¤¹¤ë¥Ç¥£¥ì¥¯¥È¥ê."
-#: src/main.cc:106
+#: src/main.cc:138
msgid " -o, --out=FILE The file name for downloaded file."
msgstr ""
" -o, --out=FILE ¥À¥¦¥ó¥í¡¼¥É¤·¤¿¥Õ¥¡¥¤¥ë¤ÎÊݸÀè¥Õ¥¡¥¤¥ë̾."
-#: src/main.cc:107
+#: src/main.cc:139
msgid ""
" -l, --log=LOG The file path to store log. If '-' is "
"specified,\n"
@@ -269,11 +286,11 @@ msgstr ""
"ÎÏ\n"
" ¤Ë½ÐÎϤ·¤Þ¤¹."
-#: src/main.cc:109
+#: src/main.cc:141
msgid " -D, --daemon Run as daemon."
msgstr " -D, --daemon ¥Ç¡¼¥â¥ó¤È¤·¤Æµ¯Æ°¤·¤Þ¤¹."
-#: src/main.cc:110
+#: src/main.cc:142
msgid ""
" -s, --split=N Download a file using N connections. N must "
"be\n"
@@ -292,7 +309,7 @@ msgstr ""
"¥·¥ç\n"
" ¥ó¤ò³ÎΩ¤·¤Þ¤¹."
-#: src/main.cc:114
+#: src/main.cc:146
msgid ""
" --retry-wait=SEC Set amount of time in second between requests\n"
" for errors. Specify a value between 0 and 60.\n"
@@ -303,13 +320,13 @@ msgstr ""
" ¤¹. 0 - 60 ¤ÎÃͤò»ØÄꤷ¤Æ¤¯¤À¤µ¤¤.\n"
" ¥Ç¥Õ¥©¥ë¥ÈÃÍ: 5"
-#: src/main.cc:117
+#: src/main.cc:149
msgid " -t, --timeout=SEC Set timeout in second. Default: 60"
msgstr ""
" -t, --timeout=SEC ¥¿¥¤¥à¥¢¥¦¥È¤È¤Ê¤ë»þ´Ö¤òÉäǻØÄꤷ¤Þ¤¹.\n"
" ¥Ç¥Õ¥©¥ë¥ÈÃÍ: 60"
-#: src/main.cc:118
+#: src/main.cc:150
msgid ""
" -m, --max-tries=N Set number of tries. 0 means unlimited.\n"
" Default: 5"
@@ -318,7 +335,7 @@ msgstr ""
"¹Ô\n"
" ¤·¤Þ¤¹. ¥Ç¥Õ¥©¥ë¥ÈÃÍ: 5"
-#: src/main.cc:120
+#: src/main.cc:152
msgid ""
" --min-segment-size=SIZE[K|M] Set minimum segment size. You can append\n"
" K or M(1K = 1024, 1M = 1024K). This\n"
@@ -331,7 +348,7 @@ msgstr ""
"1024K).\n"
" 1024 °Ê¾å¤ÎÃͤò»ØÄꤷ¤Æ¤¯¤À¤µ¤¤."
-#: src/main.cc:124
+#: src/main.cc:156
msgid ""
" --http-proxy=HOST:PORT Use HTTP proxy server. This affects to all\n"
" URLs."
@@ -340,14 +357,14 @@ msgstr ""
"¥·\n"
" ¥ç¥ó¤Ï¤¹¤Ù¤Æ¤Î URL ¤Ë±Æ¶Á¤·¤Þ¤¹."
-#: src/main.cc:126
+#: src/main.cc:158
msgid " --http-user=USER Set HTTP user. This affects to all URLs."
msgstr ""
" --http-user=USER HTTP ¤Ç¤Îǧ¾Ú¥æ¡¼¥¶¡¼¤ò»ØÄꤷ¤Þ¤¹. ¤³¤Î¥ª¥×¥·¥ç"
"¥ó\n"
" ¤Ï¤¹¤Ù¤Æ¤Î URL ¤Ë±Æ¶Á¤·¤Þ¤¹."
-#: src/main.cc:127
+#: src/main.cc:159
msgid ""
" --http-passwd=PASSWD Set HTTP password. This affects to all URLs."
msgstr ""
@@ -355,7 +372,7 @@ msgstr ""
"¥·¥ç\n"
" ¥ó¤Ï¤¹¤Ù¤Æ¤Î URL ¤Ë±Æ¶Á¤·¤Þ¤¹."
-#: src/main.cc:128
+#: src/main.cc:160
msgid ""
" --http-proxy-user=USER Set HTTP proxy user. This affects to all URLs"
msgstr ""
@@ -365,7 +382,7 @@ msgstr ""
"¤Þ\n"
" ¤¹."
-#: src/main.cc:129
+#: src/main.cc:161
msgid ""
" --http-proxy-passwd=PASSWD Set HTTP proxy password. This affects to all "
"URLs."
@@ -376,7 +393,7 @@ msgstr ""
"¤·\n"
" ¤Þ¤¹."
-#: src/main.cc:130
+#: src/main.cc:162
msgid ""
" --http-proxy-method=METHOD Set the method to use in proxy request.\n"
" METHOD is either 'get' or 'tunnel'.\n"
@@ -387,7 +404,7 @@ msgstr ""
" ¤¹. 'get' ¤Þ¤¿¤Ï 'tunnel' ¤ò»ØÄꤷ¤Æ¤¯¤À¤µ¤¤.\n"
" ¥Ç¥Õ¥©¥ë¥ÈÃÍ: tunnel"
-#: src/main.cc:133
+#: src/main.cc:165
msgid ""
" --http-auth-scheme=SCHEME Set HTTP authentication scheme. Currently, "
"basic\n"
@@ -405,14 +422,14 @@ msgstr ""
"Äê\n"
" ¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹."
-#: src/main.cc:137
+#: src/main.cc:169
msgid " --referer=REFERER Set Referer. This affects to all URLs."
msgstr ""
" --referer=REFERER ¥ê¥Õ¥¡¥é¡¼¤ò»ØÄꤷ¤Þ¤¹. ¤³¤Î¥ª¥×¥·¥ç¥ó¤Ï¤¹¤Ù¤Æ"
"¤Î\n"
" URL ¤Ë±Æ¶Á¤·¤Þ¤¹."
-#: src/main.cc:138
+#: src/main.cc:170
msgid ""
" --ftp-user=USER Set FTP user. This affects to all URLs.\n"
" Default: anonymous"
@@ -422,7 +439,7 @@ msgstr ""
" ¤Ï¤¹¤Ù¤Æ¤Î URL ¤Ë±Æ¶Á¤·¤Þ¤¹.\n"
" ¥Ç¥Õ¥©¥ë¥ÈÃÍ: anonymous"
-#: src/main.cc:140
+#: src/main.cc:172
msgid ""
" --ftp-passwd=PASSWD Set FTP password. This affects to all URLs.\n"
" Default: ARIA2USER@"
@@ -432,7 +449,7 @@ msgstr ""
" ¥ó¤Ï¤¹¤Ù¤Æ¤Î URL ¤Ë±Æ¶Á¤·¤Þ¤¹.\n"
" ¥Ç¥Õ¥©¥ë¥ÈÃÍ: ARIA2USER@"
-#: src/main.cc:142
+#: src/main.cc:174
msgid ""
" --ftp-type=TYPE Set FTP transfer type. TYPE is either "
"'binary'\n"
@@ -443,11 +460,11 @@ msgstr ""
" 'ascii' ¤ò»ØÄꤷ¤Æ¤¯¤À¤µ¤¤. ¥Ç¥Õ¥©¥ë¥ÈÃÍ: "
"binary"
-#: src/main.cc:145
+#: src/main.cc:177
msgid " -p, --ftp-pasv Use passive mode in FTP."
msgstr " -p, --ftp-pasv FTP ¤Ç passive ¥â¡¼¥É¤ò»ÈÍѤ·¤Þ¤¹."
-#: src/main.cc:146
+#: src/main.cc:178
msgid ""
" --ftp-via-http-proxy=METHOD Use HTTP proxy in FTP. METHOD is either 'get' "
"or\n"
@@ -460,16 +477,29 @@ msgstr ""
"¤¯\n"
" ¤À¤µ¤¤. ¥Ç¥Õ¥©¥ë¥ÈÃÍ: tunnel"
-#: src/main.cc:149
+#: src/main.cc:181
+msgid " --torrent-file=TORRENT_FILE The file path to .torrent file."
+msgstr ""
+
+#: src/main.cc:182
+msgid ""
+" --follow-torrent=true|false Setting this option to false prevents aria2 "
+"to\n"
+" enter BitTorrent mode even if the filename of\n"
+" downloaded file ends with .torrent.\n"
+" Default: true"
+msgstr ""
+
+#: src/main.cc:186
msgid " -v, --version Print the version number and exit."
msgstr " -v, --version ¥Ð¡¼¥¸¥ç¥óÈÖ¹æ¤òɽ¼¨¤·, ½ªÎ»¤·¤Þ¤¹."
-#: src/main.cc:150
+#: src/main.cc:187
msgid " -h, --help Print this message and exit."
msgstr ""
" -h, --help ¤³¤Î¥Ø¥ë¥×¥á¥Ã¥»¡¼¥¸¤òɽ¼¨¤·, ½ªÎ»¤·¤Þ¤¹."
-#: src/main.cc:153
+#: src/main.cc:190
msgid ""
" You can specify multiple URLs. All URLs must point to the same file\n"
" or downloading fails."
@@ -478,88 +508,81 @@ msgstr ""
"¤ì\n"
" ¤Ð¤Ê¤ê¤Þ¤»¤ó. ¤µ¤â¤Ê¤¯¤Ð¥À¥¦¥ó¥í¡¼¥É¤Ï¼ºÇÔ¤·¤Þ¤¹."
-#: src/main.cc:156
+#: src/main.cc:193
msgid "Examples:"
msgstr "Îã:"
-#: src/main.cc:157
+#: src/main.cc:194
msgid " Download a file by 1 connection:"
msgstr " 1 ¥³¥Í¥¯¥·¥ç¥ó¤Ç¤Î¥À¥¦¥ó¥í¡¼¥É:"
-#: src/main.cc:159
+#: src/main.cc:196
msgid " Download a file by 2 connections:"
msgstr " 2 ¥³¥Í¥¯¥·¥ç¥ó¤Ç¤Î¥À¥¦¥ó¥í¡¼¥É:"
-#: src/main.cc:161
+#: src/main.cc:198
msgid " Download a file by 2 connections, each connects to a different server:"
msgstr " Æó¤Ä¤Î°Û¤Ê¤ë¥µ¡¼¥Ð¡¼¤ËÀܳ¤·¤Æ¥À¥¦¥ó¥í¡¼¥É:"
-#: src/main.cc:163
+#: src/main.cc:200
msgid " You can mix up different protocols:"
msgstr " °Û¤Ê¤ë¥×¥í¥È¥³¥ë¤òº®¹ç¤µ¤»¤Æ¥À¥¦¥ó¥í¡¼¥É:"
-#: src/main.cc:166
+#: src/main.cc:202
+#, fuzzy
+msgid " Download a torrent"
+msgstr "CUID#%d - ¥À¥¦¥ó¥í¡¼¥É¤òÃæ»ß¤·¤Þ¤¹."
+
+#: src/main.cc:205
#, c-format
msgid "Reports bugs to %s"
msgstr "¥Ð¥°¥ì¥Ý¡¼¥È¤Ï¤³¤Á¤é¤Ø: %s"
-#: src/main.cc:240
+#: src/main.cc:284
msgid "unrecognized proxy format"
msgstr "Íý²ò¤Ç¤­¤Ê¤¤Proxy¥Õ¥©¡¼¥Þ¥Ã¥È¤Ç¤¹."
-#: src/main.cc:266
+#: src/main.cc:310
msgid "Currently, supported authentication scheme is basic."
msgstr "¸½ºß¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤ëǧ¾ÚÊýË¡¤Ï basic ¤Ç¤¹."
-#: src/main.cc:275
+#: src/main.cc:319
msgid "retry-wait must be between 0 and 60."
msgstr "retry-wait ¤Ï 0 ¤«¤é 60 ¤Î´Ö¤Ç»ØÄꤷ¤Æ¤¯¤À¤µ¤¤."
-#: src/main.cc:292
+#: src/main.cc:336
msgid "ftp-type must be either 'binary' or 'ascii'."
msgstr "ftp-type ¤Ï 'binary' ¤Þ¤¿¤Ï 'ascii' ¤ò»ØÄꤷ¤Æ¤¯¤À¤µ¤¤."
-#: src/main.cc:301
+#: src/main.cc:345
msgid "ftp-via-http-proxy must be either 'get' or 'tunnel'."
msgstr "ftp-via-http-proxy ¤Ï 'get' ¤Þ¤¿¤Ï 'tunnel' ¤ò»ØÄꤷ¤Æ¤¯¤À¤µ¤¤."
-#: src/main.cc:319
+#: src/main.cc:363
msgid "min-segment-size invalid"
msgstr "min-segment-size ¤¬ÉÔÀµ¤Ç¤¹."
-#: src/main.cc:330
+#: src/main.cc:374
msgid "http-proxy-method must be either 'get' or 'tunnel'."
msgstr "http-proxy-method ¤Ï 'get' ¤Þ¤¿¤Ï 'tunnel' ¤ò»ØÄꤷ¤Æ¤¯¤À¤µ¤¤."
-#: src/main.cc:357
+#: src/main.cc:388
+#, fuzzy
+msgid "follow-torrent must be either 'true' or 'false'."
+msgstr "ftp-type ¤Ï 'binary' ¤Þ¤¿¤Ï 'ascii' ¤ò»ØÄꤷ¤Æ¤¯¤À¤µ¤¤."
+
+#: src/main.cc:414
msgid "split must be between 1 and 5."
msgstr "split ¤Ï 1 - 5 ¤ÎÃͤò»ØÄꤷ¤Æ¤¯¤À¤µ¤¤."
-#: src/main.cc:367
+#: src/main.cc:424
msgid "timeout must be between 1 and 600"
msgstr "timeout ¤Ï 1 - 600 ¤ÎÃͤò»ØÄꤷ¤Æ¤¯¤À¤µ¤¤."
-#: src/main.cc:376
+#: src/main.cc:433
msgid "max-tries invalid"
msgstr "max-tries ¤¬ÉÔÀµ¤Ç¤¹."
-#: src/main.cc:398
+#: src/main.cc:456
msgid "specify at least one URL"
msgstr "°ì¸Ä°Ê¾å¤Î URL ¤ò»ØÄꤷ¤Æ¤¯¤À¤µ¤¤."
-
-#: src/main.cc:449
-#, c-format
-msgid ""
-"\n"
-"The download was complete. <%s>\n"
-msgstr ""
-"\n"
-"<%s> ¤Î¥À¥¦¥ó¥í¡¼¥É¤¬´°Î»¤·¤Þ¤·¤¿.\n"
-
-#: src/main.cc:451
-msgid ""
-"\n"
-"The download was not complete because of errors. Check the log.\n"
-msgstr ""
-"\n"
-"¥À¥¦¥ó¥í¡¼¥É¤Ï¥¨¥é¡¼¤Î¤¿¤á´°Î»¤·¤Æ¤¤¤Þ¤»¤ó. ¥í¥°¤ò³Îǧ¤·¤Æ¤¯¤À¤µ¤¤.\n"
diff --git a/src/AbstractDiskWriter.cc b/src/AbstractDiskWriter.cc
index 501b1bbf..7cdf75e7 100644
--- a/src/AbstractDiskWriter.cc
+++ b/src/AbstractDiskWriter.cc
@@ -27,6 +27,8 @@
#include <fcntl.h>
#include "DlAbortEx.h"
#include "File.h"
+#include <openssl/evp.h>
+#include "Util.h"
AbstractDiskWriter::AbstractDiskWriter():fd(0) {}
@@ -49,7 +51,7 @@ void AbstractDiskWriter::openExistingFile(string filename) {
throw new DlAbortEx(strerror(errno));
}
- if((fd = open(filename.c_str(), O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
+ if((fd = open(filename.c_str(), O_RDWR, S_IRUSR|S_IWUSR)) < 0) {
throw new DlAbortEx(strerror(errno));
}
}
@@ -60,7 +62,7 @@ void AbstractDiskWriter::createFile(string filename, int addFlags) {
// if(filename.empty()) {
// filename = "index.html";
// }
- if((fd = open(filename.c_str(), O_CREAT|O_WRONLY|O_TRUNC|addFlags, S_IRUSR|S_IWUSR)) < 0) {
+ if((fd = open(filename.c_str(), O_CREAT|O_RDWR|O_TRUNC|addFlags, S_IRUSR|S_IWUSR)) < 0) {
throw new DlAbortEx(strerror(errno));
}
}
@@ -70,3 +72,60 @@ void AbstractDiskWriter::writeDataInternal(const char* data, int len) {
throw new DlAbortEx(strerror(errno));
}
}
+
+int AbstractDiskWriter::readDataInternal(char* data, int len) {
+ int ret;
+ if((ret = read(fd, data, len)) < 0) {
+ throw new DlAbortEx(strerror(errno));
+ }
+ return ret;
+}
+
+string AbstractDiskWriter::sha1Sum(long long int offset, long long int length) {
+ EVP_MD_CTX ctx;
+ EVP_MD_CTX_init(&ctx);
+ EVP_DigestInit_ex(&ctx, EVP_sha1(), NULL);
+
+ try {
+ int BUFSIZE = 4096;
+ char buf[BUFSIZE];
+ for(int i = 0; i < length/BUFSIZE; i++) {
+ if(BUFSIZE != readData(buf, BUFSIZE, offset)) {
+ throw "error";
+ }
+ EVP_DigestUpdate(&ctx, buf, BUFSIZE);
+ offset += BUFSIZE;
+ }
+ int r = length%BUFSIZE;
+ if(r > 0) {
+ if(r != readData(buf, r, offset)) {
+ throw "error";
+ }
+ EVP_DigestUpdate(&ctx, buf, r);
+ }
+ unsigned char hashValue[20];
+ int len;
+ EVP_DigestFinal_ex(&ctx, hashValue, (unsigned int*)&len);
+ EVP_MD_CTX_cleanup(&ctx);
+ return Util::toHex(hashValue, 20);
+ } catch(string ex) {
+ EVP_MD_CTX_cleanup(&ctx);
+ throw new DlAbortEx(strerror(errno));
+ }
+}
+
+void AbstractDiskWriter::seek(long long int offset) {
+ if(offset != lseek(fd, offset, SEEK_SET)) {
+ throw new DlAbortEx(strerror(errno));
+ }
+}
+
+void AbstractDiskWriter::writeData(const char* data, int len, long long int offset) {
+ seek(offset);
+ writeDataInternal(data, len);
+}
+
+int AbstractDiskWriter::readData(char* data, int len, long long int offset) {
+ seek(offset);
+ return readDataInternal(data, len);
+}
diff --git a/src/AbstractDiskWriter.h b/src/AbstractDiskWriter.h
index c32ddc34..b5221170 100644
--- a/src/AbstractDiskWriter.h
+++ b/src/AbstractDiskWriter.h
@@ -31,6 +31,7 @@ protected:
void createFile(string filename, int addFlags = 0);
void writeDataInternal(const char* data, int len);
+ int readDataInternal(char* data, int len);
public:
AbstractDiskWriter();
virtual ~AbstractDiskWriter();
@@ -38,6 +39,14 @@ public:
void closeFile();
void openExistingFile(string filename);
+
+ string sha1Sum(long long int offset, long long int length);
+
+ void seek(long long int offset);
+
+ void writeData(const char* data, int len, long long int offset);
+
+ int readData(char* data, int len, long long int offset);
};
#endif // _D_ABSTRACT_DISK_WRITER_H_
diff --git a/src/BitfieldMan.cc b/src/BitfieldMan.cc
new file mode 100644
index 00000000..d0041fe6
--- /dev/null
+++ b/src/BitfieldMan.cc
@@ -0,0 +1,277 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "BitfieldMan.h"
+#include <string.h>
+
+BitfieldMan::BitfieldMan(int blockLength, long long int totalLength)
+ :blockLength(blockLength), totalLength(totalLength) {
+ if(blockLength > 0 && totalLength > 0) {
+ blocks = totalLength/blockLength+(totalLength%blockLength ? 1 : 0);
+ bitfieldLength = blocks/8+(blocks%8 ? 1 : 0);
+ bitfield = new unsigned char[bitfieldLength];
+ useBitfield = new unsigned char[bitfieldLength];
+ memset(bitfield, 0, bitfieldLength);
+ memset(useBitfield, 0, bitfieldLength);
+ }
+}
+
+BitfieldMan::BitfieldMan(const BitfieldMan& bitfieldMan) {
+ blockLength = bitfieldMan.blockLength;
+ totalLength = bitfieldMan.totalLength;
+ blocks = bitfieldMan.blocks;
+ bitfieldLength = bitfieldMan.bitfieldLength;
+ bitfield = new unsigned char[bitfieldLength];
+ useBitfield = new unsigned char[bitfieldLength];
+ memcpy(bitfield, bitfieldMan.bitfield, bitfieldLength);
+ memcpy(useBitfield, bitfieldMan.useBitfield, bitfieldLength);
+}
+
+BitfieldMan::~BitfieldMan() {
+ delete [] bitfield;
+ delete [] useBitfield;
+}
+
+BitfieldMan& BitfieldMan::operator=(const BitfieldMan& bitfieldMan) {
+ if(this != &bitfieldMan) {
+ blockLength = bitfieldMan.blockLength;
+ totalLength = bitfieldMan.totalLength;
+ if(bitfieldLength != bitfieldMan.bitfieldLength) {
+ delete [] bitfield;
+ delete [] useBitfield;
+ bitfield = new unsigned char[bitfieldMan.bitfieldLength];
+ useBitfield = new unsigned char[bitfieldMan.bitfieldLength];
+ }
+ blocks = bitfieldMan.blocks;
+ bitfieldLength = bitfieldMan.bitfieldLength;
+ memcpy(bitfield, bitfieldMan.bitfield, bitfieldLength);
+ memcpy(useBitfield, bitfieldMan.useBitfield, bitfieldLength);
+ }
+ return *this;
+}
+
+int BitfieldMan::countSetBit(const unsigned char* bitfield, int len) const {
+ int count = 0;
+ for(int i = 0; i < len; i++) {
+ unsigned char bit = bitfield[i];
+ for(int bs = 7; bs >= 0 && i*8+7-bs < blocks; bs--) {
+ unsigned char mask = 1 << bs;
+ if(bit & mask) {
+ count++;
+ }
+ }
+ }
+ return count;
+}
+
+int BitfieldMan::getMissingIndexRandomly(const unsigned char* bitfield, int len, int randMax) const {
+ int index = -1;
+ int nth = 1+(int)(((double)randMax)*random()/(RAND_MAX+1.0));
+ for(int i = 0; i < len && index == -1; i++) {
+ unsigned char bit = bitfield[i];
+ for(int bs = 7; bs >= 0 && i*8+7-bs < blocks; bs--) {
+ unsigned char mask = 1 << bs;
+ if(bit & mask) {
+ nth--;
+ if(nth == 0) {
+ index = i*8+7-bs;
+ break;
+ }
+ }
+ }
+ }
+ return index;
+}
+
+int BitfieldMan::getMissingIndex(const unsigned char* peerBitfield, int length) const {
+ if(bitfieldLength != length) {
+ return -1;
+ }
+ unsigned char* tempBitfield = new unsigned char[bitfieldLength];
+ for(int i = 0; i < bitfieldLength; i++) {
+ tempBitfield[i] = peerBitfield[i] & ~bitfield[i];
+ }
+ int max = countSetBit(tempBitfield, bitfieldLength);
+ int index = getMissingIndexRandomly(tempBitfield, bitfieldLength, max);
+ return index;
+}
+
+int BitfieldMan::getMissingUnusedIndex(const unsigned char* peerBitfield, int length) const {
+ if(bitfieldLength != length) {
+ return -1;
+ }
+ unsigned char* tempBitfield = new unsigned char[bitfieldLength];
+ for(int i = 0; i < bitfieldLength; i++) {
+ tempBitfield[i] = peerBitfield[i] & ~bitfield[i] & ~useBitfield[i];
+ }
+ int max = countSetBit(tempBitfield, bitfieldLength);
+ /*
+ int max = 0;
+ for(int i = 0; i < bitfieldLength; i++) {
+ unsigned char bit = tempBitfield[i];
+ for(int bs = 7; bs >= 0 && i*8+7-bs < blocks; bs--) {
+ unsigned char mask = 1 << bs;
+ if(bit & mask) {
+ max++;
+ }
+ }
+ }
+ */
+ int index = getMissingIndexRandomly(tempBitfield, bitfieldLength, max);
+ /*
+ int index = -1;
+ int nth = 1+(int)(((double)max)*random()/(RAND_MAX+1.0));
+ for(int i = 0; i < bitfieldLength && index == -1; i++) {
+ unsigned char bit = tempBitfield[i];
+ for(int bs = 7; bs >= 0 && i*8+7-bs < blocks; bs--) {
+ unsigned char mask = 1 << bs;
+ if(bit & mask) {
+ nth--;
+ if(nth == 0) {
+ index = i*8+7-bs;
+ break;
+ }
+ }
+ }
+ }
+ */
+ return index;
+}
+
+int BitfieldMan::getFirstMissingUnusedIndex(const unsigned char* peerBitfield, int length) const {
+ if(bitfieldLength != length) {
+ return -1;
+ }
+ for(int i = 0; i < bitfieldLength; i++) {
+ unsigned char bit = peerBitfield[i] & ~bitfield[i] & ~useBitfield[i];
+ for(int bs = 7; bs >= 0 && i*8+7-bs < blocks; bs--) {
+ unsigned char mask = 1 << bs;
+ if(bit & mask) {
+ return i*8+7-bs;
+ }
+ }
+ }
+ return -1;
+}
+
+int BitfieldMan::getFirstMissingUnusedIndex() const {
+ for(int i = 0; i < bitfieldLength; i++) {
+ unsigned char bit = ~bitfield[i] & ~useBitfield[i];
+ for(int bs = 7; bs >= 0 && i*8+7-bs < blocks; bs--) {
+ unsigned char mask = 1 << bs;
+ if(bit & mask) {
+ return i*8+7-bs;
+ }
+ }
+ }
+ return -1;
+}
+
+vector<int> BitfieldMan::getAllMissingIndexes() const {
+ vector<int> missingIndexes;
+ for(int i = 0; i < bitfieldLength; i++) {
+ unsigned char bit = ~bitfield[i];
+ for(int bs = 7; bs >= 0 && i*8+7-bs < blocks; bs--) {
+ unsigned char mask = 1 << bs;
+ if(bit & mask) {
+ missingIndexes.push_back(i*8+7-bs);
+ }
+ }
+ }
+ return missingIndexes;
+}
+
+int BitfieldMan::countMissingBlock() const {
+ return blocks-countSetBit(bitfield, bitfieldLength);
+}
+
+bool BitfieldMan::setUseBit(int index) {
+ if(blocks <= index) { return false; }
+ unsigned char mask = 128 >> index%8;
+ useBitfield[index/8] |= mask;
+ return true;
+}
+
+bool BitfieldMan::unsetUseBit(int index) {
+ if(blocks <= index) { return false; }
+ unsigned char mask = 128 >> index%8;
+ useBitfield[index/8] &= ~mask;
+ return true;
+}
+
+bool BitfieldMan::setBit(int index) {
+ if(blocks <= index) { return false; }
+ unsigned char mask = 128 >> index%8;
+ bitfield[index/8] |= mask;
+ return true;
+}
+bool BitfieldMan::unsetBit(int index) {
+ if(blocks <= index) { return false; }
+ unsigned char mask = 128 >> index%8;
+ bitfield[index/8] &= ~mask;
+ return true;
+}
+
+bool BitfieldMan::isAllBitSet() const {
+ for(int i = 0; i < bitfieldLength-1; i++) {
+ if(bitfield[i] != 0xff) {
+ return false;
+ }
+ }
+ unsigned char b = ~((128 >> (blocks-1)%8)-1);
+ if(bitfield[bitfieldLength-1] != b) {
+ return false;
+ }
+ return true;
+}
+
+bool BitfieldMan::isBitSetInternal(const unsigned char* bitfield, int index) const {
+ if(blocks <= index) { return false; }
+ unsigned char mask = 128 >> index%8;
+ return (bitfield[index/8] & mask) != 0;
+}
+
+bool BitfieldMan::isBitSet(int index) const {
+ return isBitSetInternal(bitfield, index);
+}
+
+bool BitfieldMan::isUseBitSet(int index) const {
+ return isBitSetInternal(useBitfield, index);
+}
+
+void BitfieldMan::setBitfield(const unsigned char* bitfield, int bitfieldLength) {
+ if(this->bitfieldLength != bitfieldLength) {
+ return;
+ }
+ memcpy(this->bitfield, bitfield, this->bitfieldLength);
+ memset(this->useBitfield, 0, this->bitfieldLength);
+}
+
+void BitfieldMan::clearAllBit() {
+ memset(this->bitfield, 0, this->bitfieldLength);
+ memset(this->useBitfield, 0, this->bitfieldLength);
+}
+
+void BitfieldMan::setAllBit() {
+ for(int i = 0; i < blocks; i++) {
+ setBit(i);
+ }
+}
diff --git a/src/BitfieldMan.h b/src/BitfieldMan.h
new file mode 100644
index 00000000..28f2f026
--- /dev/null
+++ b/src/BitfieldMan.h
@@ -0,0 +1,90 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_BITFIELD_MAN_H_
+#define _D_BITFIELD_MAN_H_
+
+#include "common.h"
+#include <vector>
+
+class BitfieldMan {
+private:
+ int blockLength;
+ long long int totalLength;
+ unsigned char* bitfield;
+ unsigned char* useBitfield;
+ int bitfieldLength;
+ int blocks;
+
+ int countSetBit(const unsigned char* bitfield, int len) const;
+ int getMissingIndexRandomly(const unsigned char* bitfield, int len, int randMax) const;
+ bool isBitSetInternal(const unsigned char* bitfield, int index) const;
+public:
+ BitfieldMan(int blockLength, long long int totalLength);
+ BitfieldMan(const BitfieldMan& bitfieldMan);
+ ~BitfieldMan();
+
+ BitfieldMan& operator=(const BitfieldMan& bitfieldMan);
+
+ int getBlockLength() const { return blockLength; }
+ int getLastBlockLength() const {
+ return totalLength-blockLength*(blocks-1);
+ }
+ int getBlockLength(int index) const {
+ if(index == blocks-1) {
+ return getLastBlockLength();
+ } else if(0 <= index && index < blocks-1) {
+ return getBlockLength();
+ } else {
+ return 0;
+ }
+ }
+ long long int getTotalLength() const { return totalLength; }
+
+ int getMissingIndex(const unsigned char* bitfield, int len) const;
+ int getFirstMissingUnusedIndex(const unsigned char* bitfield, int len) const;
+ int getFirstMissingUnusedIndex() const;
+ int getMissingUnusedIndex(const unsigned char* bitfield, int len) const;
+ vector<int> getAllMissingIndexes() const;
+ int countMissingBlock() const;
+ bool setUseBit(int index);
+ bool unsetUseBit(int index);
+
+ bool setBit(int index);
+ bool unsetBit(int index);
+
+ bool isBitSet(int index) const;
+ bool isUseBitSet(int index) const;
+
+ bool isAllBitSet() const;
+
+ const unsigned char* getBitfield() const { return bitfield; }
+ int getBitfieldLength() const { return bitfieldLength; }
+
+ int countBlock() const { return blocks; }
+
+ void setBitfield(const unsigned char* bitfield, int bitfieldLength);
+
+ void clearAllBit();
+ void setAllBit();
+};
+
+#endif // _D_BITFIELD_MAN_H_
diff --git a/src/ConsoleDownloadEngine.cc b/src/ConsoleDownloadEngine.cc
index 44efd279..aa0bac17 100644
--- a/src/ConsoleDownloadEngine.cc
+++ b/src/ConsoleDownloadEngine.cc
@@ -35,3 +35,37 @@ void ConsoleDownloadEngine::sendStatistics(long long int currentSize, long long
speed/1000.0 << "KB/s " <<
"(" << commands.size() << " connections)" << flush;
}
+
+void ConsoleDownloadEngine::initStatistics() {
+ cp.tv_sec = cp.tv_usec = 0;
+ speed = 0;
+ psize = 0;
+}
+
+void ConsoleDownloadEngine::calculateStatistics() {
+ long long int dlSize = segmentMan->getDownloadedSize();
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ if(cp.tv_sec == 0 && cp.tv_usec == 0) {
+ cp = now;
+ psize = dlSize;
+ } else {
+ long long int elapsed = Util::difftv(now, cp);
+ if(elapsed >= 500000) {
+ int nspeed = (int)((dlSize-psize)/(elapsed/1000000.0));
+ speed = (nspeed+speed)/2;
+ cp = now;
+ psize = dlSize;
+ sendStatistics(dlSize, segmentMan->totalSize);
+ }
+ }
+}
+
+void ConsoleDownloadEngine::onEndOfRun() {
+ diskWriter->closeFile();
+ if(segmentMan->finished()) {
+ segmentMan->remove();
+ } else {
+ segmentMan->save();
+ }
+}
diff --git a/src/ConsoleDownloadEngine.h b/src/ConsoleDownloadEngine.h
index 80b2ceb6..64d787d7 100644
--- a/src/ConsoleDownloadEngine.h
+++ b/src/ConsoleDownloadEngine.h
@@ -25,8 +25,15 @@
#include "DownloadEngine.h"
class ConsoleDownloadEngine : public DownloadEngine {
+private:
+ struct timeval cp;
+ long long int psize;
+ int speed;
protected:
void sendStatistics(long long int currentSize, long long int totalSize);
+ void initStatistics();
+ void calculateStatistics();
+ void onEndOfRun();
public:
ConsoleDownloadEngine();
~ConsoleDownloadEngine();
diff --git a/src/Data.cc b/src/Data.cc
new file mode 100644
index 00000000..b3d49f02
--- /dev/null
+++ b/src/Data.cc
@@ -0,0 +1,81 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "Data.h"
+#include "MetaEntryVisitor.h"
+
+Data::Data(const char* data, int len, bool number):number(number) {
+ if(data == NULL) {
+ this->data = NULL;
+ this->len = 0;
+ } else {
+ this->data = new char[len];
+ memcpy(this->data, data, len);
+ this->len = len;
+ }
+}
+
+Data::~Data() {
+ delete [] data;
+}
+
+string Data::toString() const {
+ if(len == 0) {
+ return "";
+ } else {
+ char* temp = new char[len+1];
+ memcpy(temp, data, len);
+ temp[len] = '\0';
+ return string(temp);
+ }
+}
+
+const char* Data::getData() const {
+ if(this->len == 0) {
+ return NULL;
+ } else {
+ return data;
+ }
+}
+
+int Data::getLen() const {
+ return len;
+}
+
+int Data::toInt() const {
+ return (int)toLLInt();
+}
+
+long long int Data::toLLInt() const {
+ if(len == 0) {
+ return 0;
+ } else {
+ return strtoll(data, NULL, 10);
+ }
+}
+
+bool Data::isNumber() const {
+ return number;
+}
+
+void Data::accept(MetaEntryVisitor* v) const {
+ v->visit(this);
+}
diff --git a/src/Data.h b/src/Data.h
new file mode 100644
index 00000000..e7571697
--- /dev/null
+++ b/src/Data.h
@@ -0,0 +1,54 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_DATA_H_
+#define _D_DATA_H_
+
+#include "MetaEntry.h"
+#include <string>
+
+using namespace std;
+
+class Data : public MetaEntry {
+private:
+ int len;
+ char* data;
+ bool number;
+public:
+ /**
+ * This class stores the copy of data. So caller must take care of freeing
+ * memory of data.
+ */
+ Data(const char* data, int len, bool number = false);
+ ~Data();
+
+ string toString() const;
+ int toInt() const;
+ long long int toLLInt() const;
+
+ const char* getData() const;
+ int getLen() const;
+ bool isNumber() const;
+
+ void accept(MetaEntryVisitor* v) const;
+};
+
+#endif // _D_DATA_H_
diff --git a/src/DefaultDiskWriter.cc b/src/DefaultDiskWriter.cc
index ce7dd752..be71fbfc 100644
--- a/src/DefaultDiskWriter.cc
+++ b/src/DefaultDiskWriter.cc
@@ -30,10 +30,3 @@ DefaultDiskWriter::~DefaultDiskWriter() {}
void DefaultDiskWriter::initAndOpenFile(string filename) {
createFile(filename);
}
-
-void DefaultDiskWriter::writeData(const char* data, int len, long long int offset) {
- if(offset != lseek(fd, offset, SEEK_SET)) {
- throw new DlAbortEx(strerror(errno));
- }
- writeDataInternal(data, len);
-}
diff --git a/src/DefaultDiskWriter.h b/src/DefaultDiskWriter.h
index c210f40b..91dc4814 100644
--- a/src/DefaultDiskWriter.h
+++ b/src/DefaultDiskWriter.h
@@ -30,8 +30,6 @@ public:
~DefaultDiskWriter();
void initAndOpenFile(string filename);
-
- void writeData(const char* data, int len, long long int position);
};
#endif // _D_DEFAULT_DISK_WRITER_H_
diff --git a/src/Dictionary.cc b/src/Dictionary.cc
new file mode 100644
index 00000000..1c46323c
--- /dev/null
+++ b/src/Dictionary.cc
@@ -0,0 +1,57 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "Dictionary.h"
+#include "MetaEntryVisitor.h"
+
+Dictionary::Dictionary() {}
+
+Dictionary::~Dictionary() {
+ clearTable();
+}
+
+void Dictionary::clearTable() {
+ for(MetaTable::iterator itr = table.begin(); itr != table.end(); itr++) {
+ delete itr->second;
+ }
+}
+
+const MetaEntry* Dictionary::get(string name) const {
+ MetaTable::const_iterator itr = table.find(name);
+ if(itr == table.end()) {
+ return NULL;
+ } else {
+ return itr->second;
+ }
+}
+
+void Dictionary::put(string name, MetaEntry* entry) {
+ table[name] = entry;
+ order.push_back(name);
+}
+
+void Dictionary::accept(MetaEntryVisitor* v) const {
+ v->visit(this);
+}
+
+const vector<string>& Dictionary::getOrder() const {
+ return order;
+}
diff --git a/src/Dictionary.h b/src/Dictionary.h
new file mode 100644
index 00000000..07837741
--- /dev/null
+++ b/src/Dictionary.h
@@ -0,0 +1,51 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_DICTIONARY_H_
+#define _D_DICTIONARY_H_
+
+#include "MetaEntry.h"
+#include <map>
+#include <vector>
+#include <string>
+
+using namespace std;
+
+typedef map<string, MetaEntry*> MetaTable;
+
+class Dictionary : public MetaEntry {
+private:
+ MetaTable table;
+ vector<string> order;
+ void clearTable();
+public:
+ Dictionary();
+ ~Dictionary();
+
+ const MetaEntry* get(string name) const;
+ void put(string name, MetaEntry* entry);
+
+ void accept(MetaEntryVisitor* v) const;
+ const vector<string>& getOrder() const;
+
+};
+
+#endif // _D_DICTIONARY_H_
diff --git a/src/Directory.cc b/src/Directory.cc
new file mode 100644
index 00000000..7bc20396
--- /dev/null
+++ b/src/Directory.cc
@@ -0,0 +1,59 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "Directory.h"
+#include "File.h"
+#include "DlAbortEx.h"
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+Directory::Directory(string name):name(name) {}
+
+Directory::~Directory() {
+ for(Files::iterator itr = files.begin(); itr != files.end(); itr++) {
+ delete *itr;
+ }
+}
+
+void Directory::createDir(string parentDir, bool recursive) const {
+ string path = parentDir+"/"+name;
+ File f(path);
+ if(f.exists()) {
+ if(!f.isDir()) {
+ throw new DlAbortEx("%s is already exists and it is not a directory.",
+ path.c_str());
+ }
+ } else {
+ if(mkdir(path.c_str(), S_IRUSR|S_IWUSR|S_IXUSR) == -1) {
+ throw new DlAbortEx(strerror(errno));
+ }
+ }
+ if(recursive) {
+ for(Files::const_iterator itr = files.begin(); itr != files.end(); itr++) {
+ (*itr)->createDir(path, true);
+ }
+ }
+}
+
+void Directory::addFile(Directory* directory) {
+ files.push_back(directory);
+}
diff --git a/src/Directory.h b/src/Directory.h
new file mode 100644
index 00000000..700aa441
--- /dev/null
+++ b/src/Directory.h
@@ -0,0 +1,44 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_DIRECTORY_H_
+#define _D_DIRECTORY_H_
+
+#include "common.h"
+#include <string>
+#include <vector>
+
+class Directory {
+
+typedef vector<Directory*> Files;
+
+private:
+ string name;
+ Files files;
+public:
+ Directory(string name);
+ ~Directory();
+
+ void createDir(string parentDir, bool recursive) const;
+ void addFile(Directory* directory);
+};
+
+#endif // _D_DIRECTORY_H_
diff --git a/src/DiskWriter.h b/src/DiskWriter.h
index 96735882..d92419d3 100644
--- a/src/DiskWriter.h
+++ b/src/DiskWriter.h
@@ -64,6 +64,12 @@ public:
* @param position the offset of this binary stream
*/
virtual void writeData(const char* data, int len, long long int position = 0) = 0;
+
+ virtual int readData(char* data, int len, long long int position) = 0;
+
+ virtual string sha1Sum(long long int offset, long long int length) = 0;
+
+ virtual void seek(long long int offset) = 0;
};
#endif // _D_DISK_WRITER_H_
diff --git a/src/DownloadEngine.cc b/src/DownloadEngine.cc
index 25a2f3fe..57bdb831 100644
--- a/src/DownloadEngine.cc
+++ b/src/DownloadEngine.cc
@@ -29,7 +29,7 @@
using namespace std;
-DownloadEngine::DownloadEngine():noWait(false) {}
+DownloadEngine::DownloadEngine():noWait(false), segmentMan(NULL) {}
DownloadEngine::~DownloadEngine() {
assert(rsockets.empty());
@@ -47,43 +47,23 @@ void DownloadEngine::run() {
delete(com);
}
}
+ shortSleep();
if(!noWait && !commands.empty()) {
waitData();
}
noWait = false;
calculateStatistics();
}
- diskWriter->closeFile();
- if(segmentMan->finished()) {
- segmentMan->remove();
- } else {
- segmentMan->save();
- }
+ onEndOfRun();
}
-void DownloadEngine::initStatistics() {
- cp.tv_sec = cp.tv_usec = 0;
- speed = 0;
- psize = 0;
-}
-
-void DownloadEngine::calculateStatistics() {
- long long int dlSize = segmentMan->getDownloadedSize();
- struct timeval now;
- gettimeofday(&now, NULL);
- if(cp.tv_sec == 0 && cp.tv_usec == 0) {
- cp = now;
- psize = dlSize;
- } else {
- long long int elapsed = Util::difftv(now, cp);
- if(elapsed >= 500000) {
- int nspeed = (int)((dlSize-psize)/(elapsed/1000000.0));
- speed = (nspeed+speed)/2;
- cp = now;
- psize = dlSize;
- sendStatistics(dlSize, segmentMan->totalSize);
- }
- }
+void DownloadEngine::shortSleep() const {
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 1000;
+ fd_set rfds;
+ FD_ZERO(&rfds);
+ select(0, &rfds, NULL, NULL, &tv);
}
void DownloadEngine::waitData() {
diff --git a/src/DownloadEngine.h b/src/DownloadEngine.h
index d5d6b290..1a9fc742 100644
--- a/src/DownloadEngine.h
+++ b/src/DownloadEngine.h
@@ -41,15 +41,13 @@ private:
vector<Socket*> rsockets;
vector<Socket*> wsockets;
+ void shortSleep() const;
bool addSocket(vector<Socket*>& sockets, Socket* socket);
bool deleteSocket(vector<Socket*>& sockets, Socket* socket);
- struct timeval cp;
- long long int psize;
- void initStatistics();
- void calculateStatistics();
protected:
- int speed;
- virtual void sendStatistics(long long int currentSize, long long int totalSize) {};
+ virtual void initStatistics() = 0;
+ virtual void calculateStatistics() = 0;
+ virtual void onEndOfRun() = 0;
public:
bool noWait;
queue<Command*> commands;
diff --git a/src/File.cc b/src/File.cc
index e5dc24e2..683fa99a 100644
--- a/src/File.cc
+++ b/src/File.cc
@@ -62,3 +62,11 @@ bool File::remove() {
return false;
}
}
+
+long long int File::size() {
+ struct stat fstat;
+ if(fillStat(fstat) < 0) {
+ return 0;
+ }
+ return fstat.st_size;
+}
diff --git a/src/File.h b/src/File.h
index f450fb97..fa11f4c1 100644
--- a/src/File.h
+++ b/src/File.h
@@ -58,6 +58,8 @@ public:
* If name denotes a directory, it must be empty in order to delete.
*/
bool remove();
+
+ long long int size();
};
#endif // _D_FILE_H_
diff --git a/src/HandshakeMessage.h b/src/HandshakeMessage.h
new file mode 100644
index 00000000..b67a210f
--- /dev/null
+++ b/src/HandshakeMessage.h
@@ -0,0 +1,47 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_HANDSHAKE_MESSAGE_H_
+#define _D_HANDSHAKE_MESSAGE_H_
+
+#include "common.h"
+#include "Util.h"
+
+#define PSTR "BitTorrent protocol"
+#define HANDSHAKE_MESSAGE_LENGTH 68
+
+class HandshakeMessage {
+public:
+ char pstrlen;
+ string pstr;
+ unsigned char infoHash[20];
+ char peerId[20];
+public:
+ HandshakeMessage() {}
+ ~HandshakeMessage() {}
+
+ string toString() const {
+ return "handshake peerId="+
+ Util::urlencode((unsigned char*)peerId, sizeof(peerId));
+ }
+};
+
+#endif // _D_HANDSHAKE_MESSAGE_H_
diff --git a/src/HttpConnection.cc b/src/HttpConnection.cc
index 8122141d..f93faead 100644
--- a/src/HttpConnection.cc
+++ b/src/HttpConnection.cc
@@ -27,7 +27,7 @@
#include "prefs.h"
HttpConnection::HttpConnection(int cuid, const Socket* socket, const Request* req, const Option* op, const Logger* logger):
- cuid(cuid), socket(socket), req(req), option(op), logger(logger) {}
+ cuid(cuid), socket(socket), req(req), option(op), logger(logger), headerBufLength(0) {}
void HttpConnection::sendRequest(const Segment& segment) const {
string request = createRequest(segment);
@@ -101,39 +101,60 @@ string HttpConnection::createRequest(const Segment& segment) const {
return request;
}
-int HttpConnection::receiveResponse(HttpHeader& headers) {
- char buf[512];
- while(socket->isReadable(0)) {
- int size = sizeof(buf)-1;
- socket->peekData(buf, size);
- if(size == 0) {
- throw new DlRetryEx(EX_INVALID_RESPONSE);
+int HttpConnection::findEndOfHeader(const char* buf, const char* substr, int bufLength) const {
+ const char* p = buf;
+ while(bufLength > p-buf && bufLength-(p-buf) >= (int)strlen(substr)) {
+ if(memcmp(p, substr, strlen(substr)) == 0) {
+ return p-buf;
}
- buf[size] = '\0';
- int hlenTemp = header.size();
- header += buf;
- string::size_type p;
- if((p = header.find("\r\n\r\n")) == string::npos) {
- socket->readData(buf, size);
+ p++;
+ }
+ return -1;
+}
+
+int HttpConnection::receiveResponse(HttpHeader& headers) {
+ //char buf[512];
+ string header;
+ int delimiterSwith = 0;
+ char* delimiters[] = { "\r\n", "\n" };
+
+ int size = HEADERBUF_SIZE-headerBufLength;
+ if(size < 0) {
+ // TODO too large header
+ throw new DlRetryEx("too large header > 4096");
+ }
+ socket->peekData(headerBuf+headerBufLength, size);
+ if(size == 0) {
+ throw new DlRetryEx(EX_INVALID_RESPONSE);
+ }
+ //buf[size] = '\0';
+ int hlenTemp = headerBufLength+size;
+ //header += buf;
+ //string::size_type p;
+ int eohIndex;
+ if((eohIndex = findEndOfHeader(headerBuf, "\r\n\r\n", hlenTemp)) == -1 &&
+ (eohIndex = findEndOfHeader(headerBuf, "\n\n", hlenTemp)) == -1) {
+ socket->readData(headerBuf+headerBufLength, size);
+ } else {
+ if(eohIndex[headerBuf] == '\n') {
+ // for crapping non-standard HTTP server
+ delimiterSwith = 1;
} else {
- if(Util::endsWith(header, "\r\n\r\n")) {
- socket->readData(buf, size);
- } else {
- header.erase(p+4);
- size = p+4-hlenTemp;
- socket->readData(buf, size);
- }
- break;
+ delimiterSwith = 0;
}
+ headerBuf[eohIndex+strlen(delimiters[delimiterSwith])*2] = '\0';
+ header = headerBuf;
+ size = eohIndex+strlen(delimiters[delimiterSwith])*2-headerBufLength;
+ socket->readData(headerBuf+headerBufLength, size);
}
- if(!Util::endsWith(header, "\r\n\r\n")) {
+ if(!Util::endsWith(header, "\r\n\r\n") && !Util::endsWith(header, "\n\n")) {
return 0;
}
// OK, we got all headers.
logger->info(MSG_RECEIVE_RESPONSE, cuid, header.c_str());
string::size_type p, np;
p = np = 0;
- np = header.find("\r\n", p);
+ np = header.find(delimiters[delimiterSwith], p);
if(np == string::npos) {
throw new DlRetryEx(EX_NO_STATUS_HEADER);
}
@@ -141,7 +162,7 @@ int HttpConnection::receiveResponse(HttpHeader& headers) {
string status = header.substr(9, 3);
p = np+2;
// retreive status name-value pairs, then push these into map
- while((np = header.find("\r\n", p)) != string::npos && np != p) {
+ while((np = header.find(delimiters[delimiterSwith], p)) != string::npos && np != p) {
string line = header.substr(p, np-p);
p = np+2;
pair<string, string> hp;
diff --git a/src/HttpConnection.h b/src/HttpConnection.h
index 33b14caf..c3e1deba 100644
--- a/src/HttpConnection.h
+++ b/src/HttpConnection.h
@@ -33,10 +33,13 @@
using namespace std;
+#define HEADERBUF_SIZE 4096
+
class HttpConnection {
private:
string getHost(const string& host, int port) const;
string createRequest(const Segment& segment) const;
+ int findEndOfHeader(const char* buf, const char* substr, int bufLength) const;
bool useProxy() const;
bool useProxyAuth() const;
bool useProxyGet() const;
@@ -46,7 +49,8 @@ private:
const Request* req;
const Option* option;
const Logger* logger;
- string header;
+ char headerBuf[HEADERBUF_SIZE+1];
+ int headerBufLength;
public:
HttpConnection(int cuid, const Socket* socket, const Request* req, const Option* op, const Logger* logger);
diff --git a/src/HttpRequestCommand.cc b/src/HttpRequestCommand.cc
index 42090bef..84439b6b 100644
--- a/src/HttpRequestCommand.cc
+++ b/src/HttpRequestCommand.cc
@@ -21,9 +21,6 @@
/* copyright --> */
#include "HttpRequestCommand.h"
#include "HttpResponseCommand.h"
-#include "HttpInitiateConnectionCommand.h"
-#include "Socket.h"
-#include "Util.h"
#include "HttpConnection.h"
HttpRequestCommand::HttpRequestCommand(int cuid, Request* req, DownloadEngine* e, Socket* s):AbstractCommand(cuid, req, e, s) {
@@ -43,7 +40,11 @@ bool HttpRequestCommand::executeInternal(Segment seg) {
req->seg = seg;
http.sendRequest(seg);
- HttpResponseCommand* command = new HttpResponseCommand(cuid, req, e, socket);
+ Command* command = getNextCommand();
e->commands.push(command);
return true;
}
+
+Command* HttpRequestCommand::getNextCommand() const {
+ return new HttpResponseCommand(cuid, req, e, socket);
+}
diff --git a/src/HttpRequestCommand.h b/src/HttpRequestCommand.h
index 2e1b4cef..f387cdce 100644
--- a/src/HttpRequestCommand.h
+++ b/src/HttpRequestCommand.h
@@ -27,7 +27,7 @@
class HttpRequestCommand:public AbstractCommand {
protected:
bool executeInternal(Segment segment);
-
+ Command* getNextCommand() const;
public:
HttpRequestCommand(int cuid, Request* req, DownloadEngine* e, Socket* s);
~HttpRequestCommand();
diff --git a/src/HttpResponseCommand.cc b/src/HttpResponseCommand.cc
index fd2526b8..48783d24 100644
--- a/src/HttpResponseCommand.cc
+++ b/src/HttpResponseCommand.cc
@@ -26,6 +26,9 @@
#include "HttpInitiateConnectionCommand.h"
#include "message.h"
#include "Util.h"
+#include "TrackerDownloadCommand.h"
+// TODO
+#include "TorrentDownloadEngine.h"
HttpResponseCommand::HttpResponseCommand(int cuid, Request* req, DownloadEngine* e, Socket* s):
AbstractCommand(cuid, req, e, s) {
@@ -89,6 +92,15 @@ bool HttpResponseCommand::handleRedirect(string url, const HttpHeader& headers)
}
bool HttpResponseCommand::handleDefaultEncoding(const HttpHeader& headers) {
+ // TODO quick and dirty way
+ if(req->isTorrent) {
+ long long int size = headers.getFirstAsLLInt("Content-Length");
+ e->segmentMan->totalSize = size;
+ e->segmentMan->isSplittable = false;
+ createHttpDownloadCommand();
+ return true;
+ }
+
long long int size = headers.getFirstAsLLInt("Content-Length");
if(size == LONG_LONG_MAX || size < 0) {
throw new DlAbortEx(EX_TOO_LARGE_FILE, size);
@@ -126,16 +138,22 @@ bool HttpResponseCommand::handleOtherEncoding(string transferEncoding, const Htt
}
void HttpResponseCommand::createHttpDownloadCommand(string transferEncoding) {
- HttpDownloadCommand* command = new HttpDownloadCommand(cuid, req, e, socket);
- TransferEncoding* enc = NULL;
- if(transferEncoding.size() && (enc = command->getTransferEncoding(transferEncoding)) == NULL) {
- delete(command);
- throw new DlAbortEx(EX_TRANSFER_ENCODING_NOT_SUPPORTED, transferEncoding.c_str());
- } else {
- if(enc != NULL) {
- command->transferEncoding = transferEncoding;
- enc->init();
+ if(!req->isTorrent) {
+ HttpDownloadCommand* command = new HttpDownloadCommand(cuid, req, e, socket);
+ TransferEncoding* enc = NULL;
+ if(transferEncoding.size() && (enc = command->getTransferEncoding(transferEncoding)) == NULL) {
+ delete(command);
+ throw new DlAbortEx(EX_TRANSFER_ENCODING_NOT_SUPPORTED, transferEncoding.c_str());
+ } else {
+ if(enc != NULL) {
+ command->transferEncoding = transferEncoding;
+ enc->init();
+ }
+ e->commands.push(command);
}
+ } else {
+ // TODO
+ TrackerDownloadCommand* command = new TrackerDownloadCommand(cuid, req, (TorrentDownloadEngine*)e, socket);
e->commands.push(command);
}
}
diff --git a/src/List.cc b/src/List.cc
new file mode 100644
index 00000000..be123769
--- /dev/null
+++ b/src/List.cc
@@ -0,0 +1,47 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "List.h"
+#include "MetaEntryVisitor.h"
+
+List::List() {}
+
+List::~List() {
+ clearList();
+}
+
+void List::clearList() {
+ for(MetaList::iterator itr = mlist.begin(); itr != mlist.end(); itr++) {
+ delete *itr;
+ }
+}
+
+void List::add(MetaEntry* entry) {
+ mlist.push_back(entry);
+}
+
+const MetaList& List::getList() const {
+ return mlist;
+}
+
+void List::accept(MetaEntryVisitor* v) const {
+ v->visit(this);
+}
diff --git a/src/List.h b/src/List.h
new file mode 100644
index 00000000..64c2a462
--- /dev/null
+++ b/src/List.h
@@ -0,0 +1,48 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_LIST_H_
+#define _D_LIST_H_
+
+#include "MetaEntry.h"
+#include <vector>
+
+using namespace std;
+
+typedef vector<MetaEntry*> MetaList;
+
+class List : public MetaEntry {
+private:
+ MetaList mlist;
+
+ void clearList();
+public:
+ List();
+ ~List();
+
+ void add(MetaEntry* entry);
+
+ const MetaList& getList() const;
+
+ void accept(MetaEntryVisitor* v) const;
+};
+
+#endif // _D_LIST_H_
diff --git a/src/Makefile.am b/src/Makefile.am
index da3e770e..fa85602d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -41,11 +41,41 @@ SRCS = Socket.cc Socket.h\
ChunkedEncoding.cc ChunkedEncoding.h\
DiskWriter.h\
DefaultDiskWriter.cc DefaultDiskWriter.h\
+ PreAllocationDiskWriter.cc PreAllocationDiskWriter.h\
AbstractDiskWriter.cc AbstractDiskWriter.h\
File.cc File.h\
Option.cc Option.h\
Base64.cc Base64.h\
- CookieBox.cc CookieBox.h
+ CookieBox.cc CookieBox.h\
+ MetaEntry.h\
+ Data.cc Data.h\
+ Dictionary.cc Dictionary.h\
+ List.cc List.h\
+ MetaFileUtil.cc MetaFileUtil.h\
+ MetaEntryVisitor.h\
+ ShaVisitor.cc ShaVisitor.h\
+ TrackerInitCommand.cc TrackerInitCommand.h\
+ TrackerDownloadCommand.cc TrackerDownloadCommand.h\
+ TrackerUpdateCommand.cc TrackerUpdateCommand.h\
+ TorrentMan.cc TorrentMan.h\
+ PeerConnection.cc PeerConnection.h\
+ PeerMessageUtil.cc PeerMessageUtil.h\
+ PeerAbstractCommand.cc PeerAbstractCommand.h\
+ PeerInitiateConnectionCommand.cc PeerInitiateConnectionCommand.h\
+ PeerInteractionCommand.cc PeerInteractionCommand.h\
+ Peer.cc Peer.h\
+ BitfieldMan.cc BitfieldMan.h\
+ TorrentDownloadEngine.cc TorrentDownloadEngine.h\
+ TorrentConsoleDownloadEngine.cc TorrentConsoleDownloadEngine.h\
+ PeerListenCommand.cc PeerListenCommand.h\
+ PendingMessage.cc PendingMessage.h\
+ PeerMessage.cc PeerMessage.h\
+ HandshakeMessage.h\
+ Piece.cc Piece.h\
+ RequestSlot.cc RequestSlot.h\
+ RequestSlotMan.cc RequestSlotMan.h\
+ TorrentAutoSaveCommand.cc TorrentAutoSaveCommand.h\
+ Directory.cc Directory.h
noinst_LIBRARIES = libaria2c.a
libaria2c_a_SOURCES = $(SRCS)
aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@
diff --git a/src/Makefile.in b/src/Makefile.in
index 100443ea..fd10d964 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -91,9 +91,32 @@ am__objects_1 = libaria2c_a-Socket.$(OBJEXT) \
libaria2c_a-SimpleLogger.$(OBJEXT) \
libaria2c_a-ChunkedEncoding.$(OBJEXT) \
libaria2c_a-DefaultDiskWriter.$(OBJEXT) \
+ libaria2c_a-PreAllocationDiskWriter.$(OBJEXT) \
libaria2c_a-AbstractDiskWriter.$(OBJEXT) \
libaria2c_a-File.$(OBJEXT) libaria2c_a-Option.$(OBJEXT) \
- libaria2c_a-Base64.$(OBJEXT) libaria2c_a-CookieBox.$(OBJEXT)
+ libaria2c_a-Base64.$(OBJEXT) libaria2c_a-CookieBox.$(OBJEXT) \
+ libaria2c_a-Data.$(OBJEXT) libaria2c_a-Dictionary.$(OBJEXT) \
+ libaria2c_a-List.$(OBJEXT) libaria2c_a-MetaFileUtil.$(OBJEXT) \
+ libaria2c_a-ShaVisitor.$(OBJEXT) \
+ libaria2c_a-TrackerInitCommand.$(OBJEXT) \
+ libaria2c_a-TrackerDownloadCommand.$(OBJEXT) \
+ libaria2c_a-TrackerUpdateCommand.$(OBJEXT) \
+ libaria2c_a-TorrentMan.$(OBJEXT) \
+ libaria2c_a-PeerConnection.$(OBJEXT) \
+ libaria2c_a-PeerMessageUtil.$(OBJEXT) \
+ libaria2c_a-PeerAbstractCommand.$(OBJEXT) \
+ libaria2c_a-PeerInitiateConnectionCommand.$(OBJEXT) \
+ libaria2c_a-PeerInteractionCommand.$(OBJEXT) \
+ libaria2c_a-Peer.$(OBJEXT) libaria2c_a-BitfieldMan.$(OBJEXT) \
+ libaria2c_a-TorrentDownloadEngine.$(OBJEXT) \
+ libaria2c_a-TorrentConsoleDownloadEngine.$(OBJEXT) \
+ libaria2c_a-PeerListenCommand.$(OBJEXT) \
+ libaria2c_a-PendingMessage.$(OBJEXT) \
+ libaria2c_a-PeerMessage.$(OBJEXT) libaria2c_a-Piece.$(OBJEXT) \
+ libaria2c_a-RequestSlot.$(OBJEXT) \
+ libaria2c_a-RequestSlotMan.$(OBJEXT) \
+ libaria2c_a-TorrentAutoSaveCommand.$(OBJEXT) \
+ libaria2c_a-Directory.$(OBJEXT)
am_libaria2c_a_OBJECTS = $(am__objects_1)
libaria2c_a_OBJECTS = $(am_libaria2c_a_OBJECTS)
am__installdirs = "$(DESTDIR)$(bindir)"
@@ -275,11 +298,41 @@ SRCS = Socket.cc Socket.h\
ChunkedEncoding.cc ChunkedEncoding.h\
DiskWriter.h\
DefaultDiskWriter.cc DefaultDiskWriter.h\
+ PreAllocationDiskWriter.cc PreAllocationDiskWriter.h\
AbstractDiskWriter.cc AbstractDiskWriter.h\
File.cc File.h\
Option.cc Option.h\
Base64.cc Base64.h\
- CookieBox.cc CookieBox.h
+ CookieBox.cc CookieBox.h\
+ MetaEntry.h\
+ Data.cc Data.h\
+ Dictionary.cc Dictionary.h\
+ List.cc List.h\
+ MetaFileUtil.cc MetaFileUtil.h\
+ MetaEntryVisitor.h\
+ ShaVisitor.cc ShaVisitor.h\
+ TrackerInitCommand.cc TrackerInitCommand.h\
+ TrackerDownloadCommand.cc TrackerDownloadCommand.h\
+ TrackerUpdateCommand.cc TrackerUpdateCommand.h\
+ TorrentMan.cc TorrentMan.h\
+ PeerConnection.cc PeerConnection.h\
+ PeerMessageUtil.cc PeerMessageUtil.h\
+ PeerAbstractCommand.cc PeerAbstractCommand.h\
+ PeerInitiateConnectionCommand.cc PeerInitiateConnectionCommand.h\
+ PeerInteractionCommand.cc PeerInteractionCommand.h\
+ Peer.cc Peer.h\
+ BitfieldMan.cc BitfieldMan.h\
+ TorrentDownloadEngine.cc TorrentDownloadEngine.h\
+ TorrentConsoleDownloadEngine.cc TorrentConsoleDownloadEngine.h\
+ PeerListenCommand.cc PeerListenCommand.h\
+ PendingMessage.cc PendingMessage.h\
+ PeerMessage.cc PeerMessage.h\
+ HandshakeMessage.h\
+ Piece.cc Piece.h\
+ RequestSlot.cc RequestSlot.h\
+ RequestSlotMan.cc RequestSlotMan.h\
+ TorrentAutoSaveCommand.cc TorrentAutoSaveCommand.h\
+ Directory.cc Directory.h
noinst_LIBRARIES = libaria2c.a
libaria2c_a_SOURCES = $(SRCS)
@@ -366,10 +419,14 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-AbstractCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-AbstractDiskWriter.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-Base64.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-BitfieldMan.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-ChunkedEncoding.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-ConsoleDownloadEngine.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-CookieBox.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-Data.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-DefaultDiskWriter.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-Dictionary.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-Directory.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-DownloadCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-DownloadEngine.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-File.Po@am__quote@
@@ -388,16 +445,39 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-HttpRequestCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-HttpResponseCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-InitiateConnectionCommandFactory.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-List.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-MetaFileUtil.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-Option.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-Peer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-PeerAbstractCommand.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-PeerConnection.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-PeerInitiateConnectionCommand.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-PeerInteractionCommand.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-PeerListenCommand.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-PeerMessage.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-PeerMessageUtil.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-PendingMessage.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-Piece.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-PreAllocationDiskWriter.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-Request.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-RequestSlot.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-RequestSlotMan.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-SegmentMan.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-SegmentSplitter.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-ShaVisitor.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-SimpleLogger.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-SleepCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-Socket.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-SocketCore.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-SplitFirstSegmentSplitter.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-SplitSlowestSegmentSplitter.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-TorrentAutoSaveCommand.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-TorrentConsoleDownloadEngine.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-TorrentDownloadEngine.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-TorrentMan.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-TrackerDownloadCommand.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-TrackerInitCommand.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-TrackerUpdateCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-Util.Po@am__quote@
.cc.o:
@@ -848,6 +928,20 @@ libaria2c_a-DefaultDiskWriter.obj: DefaultDiskWriter.cc
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-DefaultDiskWriter.obj `if test -f 'DefaultDiskWriter.cc'; then $(CYGPATH_W) 'DefaultDiskWriter.cc'; else $(CYGPATH_W) '$(srcdir)/DefaultDiskWriter.cc'; fi`
+libaria2c_a-PreAllocationDiskWriter.o: PreAllocationDiskWriter.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-PreAllocationDiskWriter.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-PreAllocationDiskWriter.Tpo" -c -o libaria2c_a-PreAllocationDiskWriter.o `test -f 'PreAllocationDiskWriter.cc' || echo '$(srcdir)/'`PreAllocationDiskWriter.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-PreAllocationDiskWriter.Tpo" "$(DEPDIR)/libaria2c_a-PreAllocationDiskWriter.Po"; else rm -f "$(DEPDIR)/libaria2c_a-PreAllocationDiskWriter.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='PreAllocationDiskWriter.cc' object='libaria2c_a-PreAllocationDiskWriter.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-PreAllocationDiskWriter.o `test -f 'PreAllocationDiskWriter.cc' || echo '$(srcdir)/'`PreAllocationDiskWriter.cc
+
+libaria2c_a-PreAllocationDiskWriter.obj: PreAllocationDiskWriter.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-PreAllocationDiskWriter.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-PreAllocationDiskWriter.Tpo" -c -o libaria2c_a-PreAllocationDiskWriter.obj `if test -f 'PreAllocationDiskWriter.cc'; then $(CYGPATH_W) 'PreAllocationDiskWriter.cc'; else $(CYGPATH_W) '$(srcdir)/PreAllocationDiskWriter.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-PreAllocationDiskWriter.Tpo" "$(DEPDIR)/libaria2c_a-PreAllocationDiskWriter.Po"; else rm -f "$(DEPDIR)/libaria2c_a-PreAllocationDiskWriter.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='PreAllocationDiskWriter.cc' object='libaria2c_a-PreAllocationDiskWriter.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-PreAllocationDiskWriter.obj `if test -f 'PreAllocationDiskWriter.cc'; then $(CYGPATH_W) 'PreAllocationDiskWriter.cc'; else $(CYGPATH_W) '$(srcdir)/PreAllocationDiskWriter.cc'; fi`
+
libaria2c_a-AbstractDiskWriter.o: AbstractDiskWriter.cc
@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-AbstractDiskWriter.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-AbstractDiskWriter.Tpo" -c -o libaria2c_a-AbstractDiskWriter.o `test -f 'AbstractDiskWriter.cc' || echo '$(srcdir)/'`AbstractDiskWriter.cc; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-AbstractDiskWriter.Tpo" "$(DEPDIR)/libaria2c_a-AbstractDiskWriter.Po"; else rm -f "$(DEPDIR)/libaria2c_a-AbstractDiskWriter.Tpo"; exit 1; fi
@@ -918,6 +1012,370 @@ libaria2c_a-CookieBox.obj: CookieBox.cc
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-CookieBox.obj `if test -f 'CookieBox.cc'; then $(CYGPATH_W) 'CookieBox.cc'; else $(CYGPATH_W) '$(srcdir)/CookieBox.cc'; fi`
+libaria2c_a-Data.o: Data.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-Data.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-Data.Tpo" -c -o libaria2c_a-Data.o `test -f 'Data.cc' || echo '$(srcdir)/'`Data.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-Data.Tpo" "$(DEPDIR)/libaria2c_a-Data.Po"; else rm -f "$(DEPDIR)/libaria2c_a-Data.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Data.cc' object='libaria2c_a-Data.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-Data.o `test -f 'Data.cc' || echo '$(srcdir)/'`Data.cc
+
+libaria2c_a-Data.obj: Data.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-Data.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-Data.Tpo" -c -o libaria2c_a-Data.obj `if test -f 'Data.cc'; then $(CYGPATH_W) 'Data.cc'; else $(CYGPATH_W) '$(srcdir)/Data.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-Data.Tpo" "$(DEPDIR)/libaria2c_a-Data.Po"; else rm -f "$(DEPDIR)/libaria2c_a-Data.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Data.cc' object='libaria2c_a-Data.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-Data.obj `if test -f 'Data.cc'; then $(CYGPATH_W) 'Data.cc'; else $(CYGPATH_W) '$(srcdir)/Data.cc'; fi`
+
+libaria2c_a-Dictionary.o: Dictionary.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-Dictionary.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-Dictionary.Tpo" -c -o libaria2c_a-Dictionary.o `test -f 'Dictionary.cc' || echo '$(srcdir)/'`Dictionary.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-Dictionary.Tpo" "$(DEPDIR)/libaria2c_a-Dictionary.Po"; else rm -f "$(DEPDIR)/libaria2c_a-Dictionary.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Dictionary.cc' object='libaria2c_a-Dictionary.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-Dictionary.o `test -f 'Dictionary.cc' || echo '$(srcdir)/'`Dictionary.cc
+
+libaria2c_a-Dictionary.obj: Dictionary.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-Dictionary.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-Dictionary.Tpo" -c -o libaria2c_a-Dictionary.obj `if test -f 'Dictionary.cc'; then $(CYGPATH_W) 'Dictionary.cc'; else $(CYGPATH_W) '$(srcdir)/Dictionary.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-Dictionary.Tpo" "$(DEPDIR)/libaria2c_a-Dictionary.Po"; else rm -f "$(DEPDIR)/libaria2c_a-Dictionary.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Dictionary.cc' object='libaria2c_a-Dictionary.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-Dictionary.obj `if test -f 'Dictionary.cc'; then $(CYGPATH_W) 'Dictionary.cc'; else $(CYGPATH_W) '$(srcdir)/Dictionary.cc'; fi`
+
+libaria2c_a-List.o: List.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-List.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-List.Tpo" -c -o libaria2c_a-List.o `test -f 'List.cc' || echo '$(srcdir)/'`List.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-List.Tpo" "$(DEPDIR)/libaria2c_a-List.Po"; else rm -f "$(DEPDIR)/libaria2c_a-List.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='List.cc' object='libaria2c_a-List.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-List.o `test -f 'List.cc' || echo '$(srcdir)/'`List.cc
+
+libaria2c_a-List.obj: List.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-List.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-List.Tpo" -c -o libaria2c_a-List.obj `if test -f 'List.cc'; then $(CYGPATH_W) 'List.cc'; else $(CYGPATH_W) '$(srcdir)/List.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-List.Tpo" "$(DEPDIR)/libaria2c_a-List.Po"; else rm -f "$(DEPDIR)/libaria2c_a-List.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='List.cc' object='libaria2c_a-List.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-List.obj `if test -f 'List.cc'; then $(CYGPATH_W) 'List.cc'; else $(CYGPATH_W) '$(srcdir)/List.cc'; fi`
+
+libaria2c_a-MetaFileUtil.o: MetaFileUtil.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-MetaFileUtil.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-MetaFileUtil.Tpo" -c -o libaria2c_a-MetaFileUtil.o `test -f 'MetaFileUtil.cc' || echo '$(srcdir)/'`MetaFileUtil.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-MetaFileUtil.Tpo" "$(DEPDIR)/libaria2c_a-MetaFileUtil.Po"; else rm -f "$(DEPDIR)/libaria2c_a-MetaFileUtil.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='MetaFileUtil.cc' object='libaria2c_a-MetaFileUtil.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-MetaFileUtil.o `test -f 'MetaFileUtil.cc' || echo '$(srcdir)/'`MetaFileUtil.cc
+
+libaria2c_a-MetaFileUtil.obj: MetaFileUtil.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-MetaFileUtil.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-MetaFileUtil.Tpo" -c -o libaria2c_a-MetaFileUtil.obj `if test -f 'MetaFileUtil.cc'; then $(CYGPATH_W) 'MetaFileUtil.cc'; else $(CYGPATH_W) '$(srcdir)/MetaFileUtil.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-MetaFileUtil.Tpo" "$(DEPDIR)/libaria2c_a-MetaFileUtil.Po"; else rm -f "$(DEPDIR)/libaria2c_a-MetaFileUtil.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='MetaFileUtil.cc' object='libaria2c_a-MetaFileUtil.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-MetaFileUtil.obj `if test -f 'MetaFileUtil.cc'; then $(CYGPATH_W) 'MetaFileUtil.cc'; else $(CYGPATH_W) '$(srcdir)/MetaFileUtil.cc'; fi`
+
+libaria2c_a-ShaVisitor.o: ShaVisitor.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-ShaVisitor.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-ShaVisitor.Tpo" -c -o libaria2c_a-ShaVisitor.o `test -f 'ShaVisitor.cc' || echo '$(srcdir)/'`ShaVisitor.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-ShaVisitor.Tpo" "$(DEPDIR)/libaria2c_a-ShaVisitor.Po"; else rm -f "$(DEPDIR)/libaria2c_a-ShaVisitor.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='ShaVisitor.cc' object='libaria2c_a-ShaVisitor.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-ShaVisitor.o `test -f 'ShaVisitor.cc' || echo '$(srcdir)/'`ShaVisitor.cc
+
+libaria2c_a-ShaVisitor.obj: ShaVisitor.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-ShaVisitor.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-ShaVisitor.Tpo" -c -o libaria2c_a-ShaVisitor.obj `if test -f 'ShaVisitor.cc'; then $(CYGPATH_W) 'ShaVisitor.cc'; else $(CYGPATH_W) '$(srcdir)/ShaVisitor.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-ShaVisitor.Tpo" "$(DEPDIR)/libaria2c_a-ShaVisitor.Po"; else rm -f "$(DEPDIR)/libaria2c_a-ShaVisitor.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='ShaVisitor.cc' object='libaria2c_a-ShaVisitor.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-ShaVisitor.obj `if test -f 'ShaVisitor.cc'; then $(CYGPATH_W) 'ShaVisitor.cc'; else $(CYGPATH_W) '$(srcdir)/ShaVisitor.cc'; fi`
+
+libaria2c_a-TrackerInitCommand.o: TrackerInitCommand.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-TrackerInitCommand.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-TrackerInitCommand.Tpo" -c -o libaria2c_a-TrackerInitCommand.o `test -f 'TrackerInitCommand.cc' || echo '$(srcdir)/'`TrackerInitCommand.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-TrackerInitCommand.Tpo" "$(DEPDIR)/libaria2c_a-TrackerInitCommand.Po"; else rm -f "$(DEPDIR)/libaria2c_a-TrackerInitCommand.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='TrackerInitCommand.cc' object='libaria2c_a-TrackerInitCommand.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-TrackerInitCommand.o `test -f 'TrackerInitCommand.cc' || echo '$(srcdir)/'`TrackerInitCommand.cc
+
+libaria2c_a-TrackerInitCommand.obj: TrackerInitCommand.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-TrackerInitCommand.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-TrackerInitCommand.Tpo" -c -o libaria2c_a-TrackerInitCommand.obj `if test -f 'TrackerInitCommand.cc'; then $(CYGPATH_W) 'TrackerInitCommand.cc'; else $(CYGPATH_W) '$(srcdir)/TrackerInitCommand.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-TrackerInitCommand.Tpo" "$(DEPDIR)/libaria2c_a-TrackerInitCommand.Po"; else rm -f "$(DEPDIR)/libaria2c_a-TrackerInitCommand.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='TrackerInitCommand.cc' object='libaria2c_a-TrackerInitCommand.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-TrackerInitCommand.obj `if test -f 'TrackerInitCommand.cc'; then $(CYGPATH_W) 'TrackerInitCommand.cc'; else $(CYGPATH_W) '$(srcdir)/TrackerInitCommand.cc'; fi`
+
+libaria2c_a-TrackerDownloadCommand.o: TrackerDownloadCommand.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-TrackerDownloadCommand.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-TrackerDownloadCommand.Tpo" -c -o libaria2c_a-TrackerDownloadCommand.o `test -f 'TrackerDownloadCommand.cc' || echo '$(srcdir)/'`TrackerDownloadCommand.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-TrackerDownloadCommand.Tpo" "$(DEPDIR)/libaria2c_a-TrackerDownloadCommand.Po"; else rm -f "$(DEPDIR)/libaria2c_a-TrackerDownloadCommand.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='TrackerDownloadCommand.cc' object='libaria2c_a-TrackerDownloadCommand.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-TrackerDownloadCommand.o `test -f 'TrackerDownloadCommand.cc' || echo '$(srcdir)/'`TrackerDownloadCommand.cc
+
+libaria2c_a-TrackerDownloadCommand.obj: TrackerDownloadCommand.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-TrackerDownloadCommand.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-TrackerDownloadCommand.Tpo" -c -o libaria2c_a-TrackerDownloadCommand.obj `if test -f 'TrackerDownloadCommand.cc'; then $(CYGPATH_W) 'TrackerDownloadCommand.cc'; else $(CYGPATH_W) '$(srcdir)/TrackerDownloadCommand.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-TrackerDownloadCommand.Tpo" "$(DEPDIR)/libaria2c_a-TrackerDownloadCommand.Po"; else rm -f "$(DEPDIR)/libaria2c_a-TrackerDownloadCommand.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='TrackerDownloadCommand.cc' object='libaria2c_a-TrackerDownloadCommand.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-TrackerDownloadCommand.obj `if test -f 'TrackerDownloadCommand.cc'; then $(CYGPATH_W) 'TrackerDownloadCommand.cc'; else $(CYGPATH_W) '$(srcdir)/TrackerDownloadCommand.cc'; fi`
+
+libaria2c_a-TrackerUpdateCommand.o: TrackerUpdateCommand.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-TrackerUpdateCommand.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-TrackerUpdateCommand.Tpo" -c -o libaria2c_a-TrackerUpdateCommand.o `test -f 'TrackerUpdateCommand.cc' || echo '$(srcdir)/'`TrackerUpdateCommand.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-TrackerUpdateCommand.Tpo" "$(DEPDIR)/libaria2c_a-TrackerUpdateCommand.Po"; else rm -f "$(DEPDIR)/libaria2c_a-TrackerUpdateCommand.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='TrackerUpdateCommand.cc' object='libaria2c_a-TrackerUpdateCommand.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-TrackerUpdateCommand.o `test -f 'TrackerUpdateCommand.cc' || echo '$(srcdir)/'`TrackerUpdateCommand.cc
+
+libaria2c_a-TrackerUpdateCommand.obj: TrackerUpdateCommand.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-TrackerUpdateCommand.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-TrackerUpdateCommand.Tpo" -c -o libaria2c_a-TrackerUpdateCommand.obj `if test -f 'TrackerUpdateCommand.cc'; then $(CYGPATH_W) 'TrackerUpdateCommand.cc'; else $(CYGPATH_W) '$(srcdir)/TrackerUpdateCommand.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-TrackerUpdateCommand.Tpo" "$(DEPDIR)/libaria2c_a-TrackerUpdateCommand.Po"; else rm -f "$(DEPDIR)/libaria2c_a-TrackerUpdateCommand.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='TrackerUpdateCommand.cc' object='libaria2c_a-TrackerUpdateCommand.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-TrackerUpdateCommand.obj `if test -f 'TrackerUpdateCommand.cc'; then $(CYGPATH_W) 'TrackerUpdateCommand.cc'; else $(CYGPATH_W) '$(srcdir)/TrackerUpdateCommand.cc'; fi`
+
+libaria2c_a-TorrentMan.o: TorrentMan.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-TorrentMan.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-TorrentMan.Tpo" -c -o libaria2c_a-TorrentMan.o `test -f 'TorrentMan.cc' || echo '$(srcdir)/'`TorrentMan.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-TorrentMan.Tpo" "$(DEPDIR)/libaria2c_a-TorrentMan.Po"; else rm -f "$(DEPDIR)/libaria2c_a-TorrentMan.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='TorrentMan.cc' object='libaria2c_a-TorrentMan.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-TorrentMan.o `test -f 'TorrentMan.cc' || echo '$(srcdir)/'`TorrentMan.cc
+
+libaria2c_a-TorrentMan.obj: TorrentMan.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-TorrentMan.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-TorrentMan.Tpo" -c -o libaria2c_a-TorrentMan.obj `if test -f 'TorrentMan.cc'; then $(CYGPATH_W) 'TorrentMan.cc'; else $(CYGPATH_W) '$(srcdir)/TorrentMan.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-TorrentMan.Tpo" "$(DEPDIR)/libaria2c_a-TorrentMan.Po"; else rm -f "$(DEPDIR)/libaria2c_a-TorrentMan.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='TorrentMan.cc' object='libaria2c_a-TorrentMan.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-TorrentMan.obj `if test -f 'TorrentMan.cc'; then $(CYGPATH_W) 'TorrentMan.cc'; else $(CYGPATH_W) '$(srcdir)/TorrentMan.cc'; fi`
+
+libaria2c_a-PeerConnection.o: PeerConnection.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-PeerConnection.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-PeerConnection.Tpo" -c -o libaria2c_a-PeerConnection.o `test -f 'PeerConnection.cc' || echo '$(srcdir)/'`PeerConnection.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-PeerConnection.Tpo" "$(DEPDIR)/libaria2c_a-PeerConnection.Po"; else rm -f "$(DEPDIR)/libaria2c_a-PeerConnection.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='PeerConnection.cc' object='libaria2c_a-PeerConnection.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-PeerConnection.o `test -f 'PeerConnection.cc' || echo '$(srcdir)/'`PeerConnection.cc
+
+libaria2c_a-PeerConnection.obj: PeerConnection.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-PeerConnection.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-PeerConnection.Tpo" -c -o libaria2c_a-PeerConnection.obj `if test -f 'PeerConnection.cc'; then $(CYGPATH_W) 'PeerConnection.cc'; else $(CYGPATH_W) '$(srcdir)/PeerConnection.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-PeerConnection.Tpo" "$(DEPDIR)/libaria2c_a-PeerConnection.Po"; else rm -f "$(DEPDIR)/libaria2c_a-PeerConnection.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='PeerConnection.cc' object='libaria2c_a-PeerConnection.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-PeerConnection.obj `if test -f 'PeerConnection.cc'; then $(CYGPATH_W) 'PeerConnection.cc'; else $(CYGPATH_W) '$(srcdir)/PeerConnection.cc'; fi`
+
+libaria2c_a-PeerMessageUtil.o: PeerMessageUtil.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-PeerMessageUtil.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-PeerMessageUtil.Tpo" -c -o libaria2c_a-PeerMessageUtil.o `test -f 'PeerMessageUtil.cc' || echo '$(srcdir)/'`PeerMessageUtil.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-PeerMessageUtil.Tpo" "$(DEPDIR)/libaria2c_a-PeerMessageUtil.Po"; else rm -f "$(DEPDIR)/libaria2c_a-PeerMessageUtil.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='PeerMessageUtil.cc' object='libaria2c_a-PeerMessageUtil.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-PeerMessageUtil.o `test -f 'PeerMessageUtil.cc' || echo '$(srcdir)/'`PeerMessageUtil.cc
+
+libaria2c_a-PeerMessageUtil.obj: PeerMessageUtil.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-PeerMessageUtil.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-PeerMessageUtil.Tpo" -c -o libaria2c_a-PeerMessageUtil.obj `if test -f 'PeerMessageUtil.cc'; then $(CYGPATH_W) 'PeerMessageUtil.cc'; else $(CYGPATH_W) '$(srcdir)/PeerMessageUtil.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-PeerMessageUtil.Tpo" "$(DEPDIR)/libaria2c_a-PeerMessageUtil.Po"; else rm -f "$(DEPDIR)/libaria2c_a-PeerMessageUtil.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='PeerMessageUtil.cc' object='libaria2c_a-PeerMessageUtil.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-PeerMessageUtil.obj `if test -f 'PeerMessageUtil.cc'; then $(CYGPATH_W) 'PeerMessageUtil.cc'; else $(CYGPATH_W) '$(srcdir)/PeerMessageUtil.cc'; fi`
+
+libaria2c_a-PeerAbstractCommand.o: PeerAbstractCommand.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-PeerAbstractCommand.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-PeerAbstractCommand.Tpo" -c -o libaria2c_a-PeerAbstractCommand.o `test -f 'PeerAbstractCommand.cc' || echo '$(srcdir)/'`PeerAbstractCommand.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-PeerAbstractCommand.Tpo" "$(DEPDIR)/libaria2c_a-PeerAbstractCommand.Po"; else rm -f "$(DEPDIR)/libaria2c_a-PeerAbstractCommand.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='PeerAbstractCommand.cc' object='libaria2c_a-PeerAbstractCommand.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-PeerAbstractCommand.o `test -f 'PeerAbstractCommand.cc' || echo '$(srcdir)/'`PeerAbstractCommand.cc
+
+libaria2c_a-PeerAbstractCommand.obj: PeerAbstractCommand.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-PeerAbstractCommand.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-PeerAbstractCommand.Tpo" -c -o libaria2c_a-PeerAbstractCommand.obj `if test -f 'PeerAbstractCommand.cc'; then $(CYGPATH_W) 'PeerAbstractCommand.cc'; else $(CYGPATH_W) '$(srcdir)/PeerAbstractCommand.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-PeerAbstractCommand.Tpo" "$(DEPDIR)/libaria2c_a-PeerAbstractCommand.Po"; else rm -f "$(DEPDIR)/libaria2c_a-PeerAbstractCommand.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='PeerAbstractCommand.cc' object='libaria2c_a-PeerAbstractCommand.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-PeerAbstractCommand.obj `if test -f 'PeerAbstractCommand.cc'; then $(CYGPATH_W) 'PeerAbstractCommand.cc'; else $(CYGPATH_W) '$(srcdir)/PeerAbstractCommand.cc'; fi`
+
+libaria2c_a-PeerInitiateConnectionCommand.o: PeerInitiateConnectionCommand.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-PeerInitiateConnectionCommand.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-PeerInitiateConnectionCommand.Tpo" -c -o libaria2c_a-PeerInitiateConnectionCommand.o `test -f 'PeerInitiateConnectionCommand.cc' || echo '$(srcdir)/'`PeerInitiateConnectionCommand.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-PeerInitiateConnectionCommand.Tpo" "$(DEPDIR)/libaria2c_a-PeerInitiateConnectionCommand.Po"; else rm -f "$(DEPDIR)/libaria2c_a-PeerInitiateConnectionCommand.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='PeerInitiateConnectionCommand.cc' object='libaria2c_a-PeerInitiateConnectionCommand.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-PeerInitiateConnectionCommand.o `test -f 'PeerInitiateConnectionCommand.cc' || echo '$(srcdir)/'`PeerInitiateConnectionCommand.cc
+
+libaria2c_a-PeerInitiateConnectionCommand.obj: PeerInitiateConnectionCommand.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-PeerInitiateConnectionCommand.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-PeerInitiateConnectionCommand.Tpo" -c -o libaria2c_a-PeerInitiateConnectionCommand.obj `if test -f 'PeerInitiateConnectionCommand.cc'; then $(CYGPATH_W) 'PeerInitiateConnectionCommand.cc'; else $(CYGPATH_W) '$(srcdir)/PeerInitiateConnectionCommand.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-PeerInitiateConnectionCommand.Tpo" "$(DEPDIR)/libaria2c_a-PeerInitiateConnectionCommand.Po"; else rm -f "$(DEPDIR)/libaria2c_a-PeerInitiateConnectionCommand.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='PeerInitiateConnectionCommand.cc' object='libaria2c_a-PeerInitiateConnectionCommand.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-PeerInitiateConnectionCommand.obj `if test -f 'PeerInitiateConnectionCommand.cc'; then $(CYGPATH_W) 'PeerInitiateConnectionCommand.cc'; else $(CYGPATH_W) '$(srcdir)/PeerInitiateConnectionCommand.cc'; fi`
+
+libaria2c_a-PeerInteractionCommand.o: PeerInteractionCommand.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-PeerInteractionCommand.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-PeerInteractionCommand.Tpo" -c -o libaria2c_a-PeerInteractionCommand.o `test -f 'PeerInteractionCommand.cc' || echo '$(srcdir)/'`PeerInteractionCommand.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-PeerInteractionCommand.Tpo" "$(DEPDIR)/libaria2c_a-PeerInteractionCommand.Po"; else rm -f "$(DEPDIR)/libaria2c_a-PeerInteractionCommand.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='PeerInteractionCommand.cc' object='libaria2c_a-PeerInteractionCommand.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-PeerInteractionCommand.o `test -f 'PeerInteractionCommand.cc' || echo '$(srcdir)/'`PeerInteractionCommand.cc
+
+libaria2c_a-PeerInteractionCommand.obj: PeerInteractionCommand.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-PeerInteractionCommand.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-PeerInteractionCommand.Tpo" -c -o libaria2c_a-PeerInteractionCommand.obj `if test -f 'PeerInteractionCommand.cc'; then $(CYGPATH_W) 'PeerInteractionCommand.cc'; else $(CYGPATH_W) '$(srcdir)/PeerInteractionCommand.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-PeerInteractionCommand.Tpo" "$(DEPDIR)/libaria2c_a-PeerInteractionCommand.Po"; else rm -f "$(DEPDIR)/libaria2c_a-PeerInteractionCommand.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='PeerInteractionCommand.cc' object='libaria2c_a-PeerInteractionCommand.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-PeerInteractionCommand.obj `if test -f 'PeerInteractionCommand.cc'; then $(CYGPATH_W) 'PeerInteractionCommand.cc'; else $(CYGPATH_W) '$(srcdir)/PeerInteractionCommand.cc'; fi`
+
+libaria2c_a-Peer.o: Peer.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-Peer.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-Peer.Tpo" -c -o libaria2c_a-Peer.o `test -f 'Peer.cc' || echo '$(srcdir)/'`Peer.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-Peer.Tpo" "$(DEPDIR)/libaria2c_a-Peer.Po"; else rm -f "$(DEPDIR)/libaria2c_a-Peer.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Peer.cc' object='libaria2c_a-Peer.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-Peer.o `test -f 'Peer.cc' || echo '$(srcdir)/'`Peer.cc
+
+libaria2c_a-Peer.obj: Peer.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-Peer.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-Peer.Tpo" -c -o libaria2c_a-Peer.obj `if test -f 'Peer.cc'; then $(CYGPATH_W) 'Peer.cc'; else $(CYGPATH_W) '$(srcdir)/Peer.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-Peer.Tpo" "$(DEPDIR)/libaria2c_a-Peer.Po"; else rm -f "$(DEPDIR)/libaria2c_a-Peer.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Peer.cc' object='libaria2c_a-Peer.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-Peer.obj `if test -f 'Peer.cc'; then $(CYGPATH_W) 'Peer.cc'; else $(CYGPATH_W) '$(srcdir)/Peer.cc'; fi`
+
+libaria2c_a-BitfieldMan.o: BitfieldMan.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-BitfieldMan.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-BitfieldMan.Tpo" -c -o libaria2c_a-BitfieldMan.o `test -f 'BitfieldMan.cc' || echo '$(srcdir)/'`BitfieldMan.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-BitfieldMan.Tpo" "$(DEPDIR)/libaria2c_a-BitfieldMan.Po"; else rm -f "$(DEPDIR)/libaria2c_a-BitfieldMan.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='BitfieldMan.cc' object='libaria2c_a-BitfieldMan.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-BitfieldMan.o `test -f 'BitfieldMan.cc' || echo '$(srcdir)/'`BitfieldMan.cc
+
+libaria2c_a-BitfieldMan.obj: BitfieldMan.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-BitfieldMan.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-BitfieldMan.Tpo" -c -o libaria2c_a-BitfieldMan.obj `if test -f 'BitfieldMan.cc'; then $(CYGPATH_W) 'BitfieldMan.cc'; else $(CYGPATH_W) '$(srcdir)/BitfieldMan.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-BitfieldMan.Tpo" "$(DEPDIR)/libaria2c_a-BitfieldMan.Po"; else rm -f "$(DEPDIR)/libaria2c_a-BitfieldMan.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='BitfieldMan.cc' object='libaria2c_a-BitfieldMan.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-BitfieldMan.obj `if test -f 'BitfieldMan.cc'; then $(CYGPATH_W) 'BitfieldMan.cc'; else $(CYGPATH_W) '$(srcdir)/BitfieldMan.cc'; fi`
+
+libaria2c_a-TorrentDownloadEngine.o: TorrentDownloadEngine.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-TorrentDownloadEngine.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-TorrentDownloadEngine.Tpo" -c -o libaria2c_a-TorrentDownloadEngine.o `test -f 'TorrentDownloadEngine.cc' || echo '$(srcdir)/'`TorrentDownloadEngine.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-TorrentDownloadEngine.Tpo" "$(DEPDIR)/libaria2c_a-TorrentDownloadEngine.Po"; else rm -f "$(DEPDIR)/libaria2c_a-TorrentDownloadEngine.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='TorrentDownloadEngine.cc' object='libaria2c_a-TorrentDownloadEngine.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-TorrentDownloadEngine.o `test -f 'TorrentDownloadEngine.cc' || echo '$(srcdir)/'`TorrentDownloadEngine.cc
+
+libaria2c_a-TorrentDownloadEngine.obj: TorrentDownloadEngine.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-TorrentDownloadEngine.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-TorrentDownloadEngine.Tpo" -c -o libaria2c_a-TorrentDownloadEngine.obj `if test -f 'TorrentDownloadEngine.cc'; then $(CYGPATH_W) 'TorrentDownloadEngine.cc'; else $(CYGPATH_W) '$(srcdir)/TorrentDownloadEngine.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-TorrentDownloadEngine.Tpo" "$(DEPDIR)/libaria2c_a-TorrentDownloadEngine.Po"; else rm -f "$(DEPDIR)/libaria2c_a-TorrentDownloadEngine.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='TorrentDownloadEngine.cc' object='libaria2c_a-TorrentDownloadEngine.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-TorrentDownloadEngine.obj `if test -f 'TorrentDownloadEngine.cc'; then $(CYGPATH_W) 'TorrentDownloadEngine.cc'; else $(CYGPATH_W) '$(srcdir)/TorrentDownloadEngine.cc'; fi`
+
+libaria2c_a-TorrentConsoleDownloadEngine.o: TorrentConsoleDownloadEngine.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-TorrentConsoleDownloadEngine.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-TorrentConsoleDownloadEngine.Tpo" -c -o libaria2c_a-TorrentConsoleDownloadEngine.o `test -f 'TorrentConsoleDownloadEngine.cc' || echo '$(srcdir)/'`TorrentConsoleDownloadEngine.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-TorrentConsoleDownloadEngine.Tpo" "$(DEPDIR)/libaria2c_a-TorrentConsoleDownloadEngine.Po"; else rm -f "$(DEPDIR)/libaria2c_a-TorrentConsoleDownloadEngine.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='TorrentConsoleDownloadEngine.cc' object='libaria2c_a-TorrentConsoleDownloadEngine.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-TorrentConsoleDownloadEngine.o `test -f 'TorrentConsoleDownloadEngine.cc' || echo '$(srcdir)/'`TorrentConsoleDownloadEngine.cc
+
+libaria2c_a-TorrentConsoleDownloadEngine.obj: TorrentConsoleDownloadEngine.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-TorrentConsoleDownloadEngine.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-TorrentConsoleDownloadEngine.Tpo" -c -o libaria2c_a-TorrentConsoleDownloadEngine.obj `if test -f 'TorrentConsoleDownloadEngine.cc'; then $(CYGPATH_W) 'TorrentConsoleDownloadEngine.cc'; else $(CYGPATH_W) '$(srcdir)/TorrentConsoleDownloadEngine.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-TorrentConsoleDownloadEngine.Tpo" "$(DEPDIR)/libaria2c_a-TorrentConsoleDownloadEngine.Po"; else rm -f "$(DEPDIR)/libaria2c_a-TorrentConsoleDownloadEngine.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='TorrentConsoleDownloadEngine.cc' object='libaria2c_a-TorrentConsoleDownloadEngine.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-TorrentConsoleDownloadEngine.obj `if test -f 'TorrentConsoleDownloadEngine.cc'; then $(CYGPATH_W) 'TorrentConsoleDownloadEngine.cc'; else $(CYGPATH_W) '$(srcdir)/TorrentConsoleDownloadEngine.cc'; fi`
+
+libaria2c_a-PeerListenCommand.o: PeerListenCommand.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-PeerListenCommand.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-PeerListenCommand.Tpo" -c -o libaria2c_a-PeerListenCommand.o `test -f 'PeerListenCommand.cc' || echo '$(srcdir)/'`PeerListenCommand.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-PeerListenCommand.Tpo" "$(DEPDIR)/libaria2c_a-PeerListenCommand.Po"; else rm -f "$(DEPDIR)/libaria2c_a-PeerListenCommand.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='PeerListenCommand.cc' object='libaria2c_a-PeerListenCommand.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-PeerListenCommand.o `test -f 'PeerListenCommand.cc' || echo '$(srcdir)/'`PeerListenCommand.cc
+
+libaria2c_a-PeerListenCommand.obj: PeerListenCommand.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-PeerListenCommand.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-PeerListenCommand.Tpo" -c -o libaria2c_a-PeerListenCommand.obj `if test -f 'PeerListenCommand.cc'; then $(CYGPATH_W) 'PeerListenCommand.cc'; else $(CYGPATH_W) '$(srcdir)/PeerListenCommand.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-PeerListenCommand.Tpo" "$(DEPDIR)/libaria2c_a-PeerListenCommand.Po"; else rm -f "$(DEPDIR)/libaria2c_a-PeerListenCommand.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='PeerListenCommand.cc' object='libaria2c_a-PeerListenCommand.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-PeerListenCommand.obj `if test -f 'PeerListenCommand.cc'; then $(CYGPATH_W) 'PeerListenCommand.cc'; else $(CYGPATH_W) '$(srcdir)/PeerListenCommand.cc'; fi`
+
+libaria2c_a-PendingMessage.o: PendingMessage.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-PendingMessage.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-PendingMessage.Tpo" -c -o libaria2c_a-PendingMessage.o `test -f 'PendingMessage.cc' || echo '$(srcdir)/'`PendingMessage.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-PendingMessage.Tpo" "$(DEPDIR)/libaria2c_a-PendingMessage.Po"; else rm -f "$(DEPDIR)/libaria2c_a-PendingMessage.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='PendingMessage.cc' object='libaria2c_a-PendingMessage.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-PendingMessage.o `test -f 'PendingMessage.cc' || echo '$(srcdir)/'`PendingMessage.cc
+
+libaria2c_a-PendingMessage.obj: PendingMessage.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-PendingMessage.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-PendingMessage.Tpo" -c -o libaria2c_a-PendingMessage.obj `if test -f 'PendingMessage.cc'; then $(CYGPATH_W) 'PendingMessage.cc'; else $(CYGPATH_W) '$(srcdir)/PendingMessage.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-PendingMessage.Tpo" "$(DEPDIR)/libaria2c_a-PendingMessage.Po"; else rm -f "$(DEPDIR)/libaria2c_a-PendingMessage.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='PendingMessage.cc' object='libaria2c_a-PendingMessage.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-PendingMessage.obj `if test -f 'PendingMessage.cc'; then $(CYGPATH_W) 'PendingMessage.cc'; else $(CYGPATH_W) '$(srcdir)/PendingMessage.cc'; fi`
+
+libaria2c_a-PeerMessage.o: PeerMessage.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-PeerMessage.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-PeerMessage.Tpo" -c -o libaria2c_a-PeerMessage.o `test -f 'PeerMessage.cc' || echo '$(srcdir)/'`PeerMessage.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-PeerMessage.Tpo" "$(DEPDIR)/libaria2c_a-PeerMessage.Po"; else rm -f "$(DEPDIR)/libaria2c_a-PeerMessage.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='PeerMessage.cc' object='libaria2c_a-PeerMessage.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-PeerMessage.o `test -f 'PeerMessage.cc' || echo '$(srcdir)/'`PeerMessage.cc
+
+libaria2c_a-PeerMessage.obj: PeerMessage.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-PeerMessage.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-PeerMessage.Tpo" -c -o libaria2c_a-PeerMessage.obj `if test -f 'PeerMessage.cc'; then $(CYGPATH_W) 'PeerMessage.cc'; else $(CYGPATH_W) '$(srcdir)/PeerMessage.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-PeerMessage.Tpo" "$(DEPDIR)/libaria2c_a-PeerMessage.Po"; else rm -f "$(DEPDIR)/libaria2c_a-PeerMessage.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='PeerMessage.cc' object='libaria2c_a-PeerMessage.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-PeerMessage.obj `if test -f 'PeerMessage.cc'; then $(CYGPATH_W) 'PeerMessage.cc'; else $(CYGPATH_W) '$(srcdir)/PeerMessage.cc'; fi`
+
+libaria2c_a-Piece.o: Piece.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-Piece.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-Piece.Tpo" -c -o libaria2c_a-Piece.o `test -f 'Piece.cc' || echo '$(srcdir)/'`Piece.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-Piece.Tpo" "$(DEPDIR)/libaria2c_a-Piece.Po"; else rm -f "$(DEPDIR)/libaria2c_a-Piece.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Piece.cc' object='libaria2c_a-Piece.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-Piece.o `test -f 'Piece.cc' || echo '$(srcdir)/'`Piece.cc
+
+libaria2c_a-Piece.obj: Piece.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-Piece.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-Piece.Tpo" -c -o libaria2c_a-Piece.obj `if test -f 'Piece.cc'; then $(CYGPATH_W) 'Piece.cc'; else $(CYGPATH_W) '$(srcdir)/Piece.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-Piece.Tpo" "$(DEPDIR)/libaria2c_a-Piece.Po"; else rm -f "$(DEPDIR)/libaria2c_a-Piece.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Piece.cc' object='libaria2c_a-Piece.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-Piece.obj `if test -f 'Piece.cc'; then $(CYGPATH_W) 'Piece.cc'; else $(CYGPATH_W) '$(srcdir)/Piece.cc'; fi`
+
+libaria2c_a-RequestSlot.o: RequestSlot.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-RequestSlot.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-RequestSlot.Tpo" -c -o libaria2c_a-RequestSlot.o `test -f 'RequestSlot.cc' || echo '$(srcdir)/'`RequestSlot.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-RequestSlot.Tpo" "$(DEPDIR)/libaria2c_a-RequestSlot.Po"; else rm -f "$(DEPDIR)/libaria2c_a-RequestSlot.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='RequestSlot.cc' object='libaria2c_a-RequestSlot.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-RequestSlot.o `test -f 'RequestSlot.cc' || echo '$(srcdir)/'`RequestSlot.cc
+
+libaria2c_a-RequestSlot.obj: RequestSlot.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-RequestSlot.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-RequestSlot.Tpo" -c -o libaria2c_a-RequestSlot.obj `if test -f 'RequestSlot.cc'; then $(CYGPATH_W) 'RequestSlot.cc'; else $(CYGPATH_W) '$(srcdir)/RequestSlot.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-RequestSlot.Tpo" "$(DEPDIR)/libaria2c_a-RequestSlot.Po"; else rm -f "$(DEPDIR)/libaria2c_a-RequestSlot.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='RequestSlot.cc' object='libaria2c_a-RequestSlot.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-RequestSlot.obj `if test -f 'RequestSlot.cc'; then $(CYGPATH_W) 'RequestSlot.cc'; else $(CYGPATH_W) '$(srcdir)/RequestSlot.cc'; fi`
+
+libaria2c_a-RequestSlotMan.o: RequestSlotMan.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-RequestSlotMan.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-RequestSlotMan.Tpo" -c -o libaria2c_a-RequestSlotMan.o `test -f 'RequestSlotMan.cc' || echo '$(srcdir)/'`RequestSlotMan.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-RequestSlotMan.Tpo" "$(DEPDIR)/libaria2c_a-RequestSlotMan.Po"; else rm -f "$(DEPDIR)/libaria2c_a-RequestSlotMan.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='RequestSlotMan.cc' object='libaria2c_a-RequestSlotMan.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-RequestSlotMan.o `test -f 'RequestSlotMan.cc' || echo '$(srcdir)/'`RequestSlotMan.cc
+
+libaria2c_a-RequestSlotMan.obj: RequestSlotMan.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-RequestSlotMan.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-RequestSlotMan.Tpo" -c -o libaria2c_a-RequestSlotMan.obj `if test -f 'RequestSlotMan.cc'; then $(CYGPATH_W) 'RequestSlotMan.cc'; else $(CYGPATH_W) '$(srcdir)/RequestSlotMan.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-RequestSlotMan.Tpo" "$(DEPDIR)/libaria2c_a-RequestSlotMan.Po"; else rm -f "$(DEPDIR)/libaria2c_a-RequestSlotMan.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='RequestSlotMan.cc' object='libaria2c_a-RequestSlotMan.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-RequestSlotMan.obj `if test -f 'RequestSlotMan.cc'; then $(CYGPATH_W) 'RequestSlotMan.cc'; else $(CYGPATH_W) '$(srcdir)/RequestSlotMan.cc'; fi`
+
+libaria2c_a-TorrentAutoSaveCommand.o: TorrentAutoSaveCommand.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-TorrentAutoSaveCommand.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-TorrentAutoSaveCommand.Tpo" -c -o libaria2c_a-TorrentAutoSaveCommand.o `test -f 'TorrentAutoSaveCommand.cc' || echo '$(srcdir)/'`TorrentAutoSaveCommand.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-TorrentAutoSaveCommand.Tpo" "$(DEPDIR)/libaria2c_a-TorrentAutoSaveCommand.Po"; else rm -f "$(DEPDIR)/libaria2c_a-TorrentAutoSaveCommand.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='TorrentAutoSaveCommand.cc' object='libaria2c_a-TorrentAutoSaveCommand.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-TorrentAutoSaveCommand.o `test -f 'TorrentAutoSaveCommand.cc' || echo '$(srcdir)/'`TorrentAutoSaveCommand.cc
+
+libaria2c_a-TorrentAutoSaveCommand.obj: TorrentAutoSaveCommand.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-TorrentAutoSaveCommand.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-TorrentAutoSaveCommand.Tpo" -c -o libaria2c_a-TorrentAutoSaveCommand.obj `if test -f 'TorrentAutoSaveCommand.cc'; then $(CYGPATH_W) 'TorrentAutoSaveCommand.cc'; else $(CYGPATH_W) '$(srcdir)/TorrentAutoSaveCommand.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-TorrentAutoSaveCommand.Tpo" "$(DEPDIR)/libaria2c_a-TorrentAutoSaveCommand.Po"; else rm -f "$(DEPDIR)/libaria2c_a-TorrentAutoSaveCommand.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='TorrentAutoSaveCommand.cc' object='libaria2c_a-TorrentAutoSaveCommand.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-TorrentAutoSaveCommand.obj `if test -f 'TorrentAutoSaveCommand.cc'; then $(CYGPATH_W) 'TorrentAutoSaveCommand.cc'; else $(CYGPATH_W) '$(srcdir)/TorrentAutoSaveCommand.cc'; fi`
+
+libaria2c_a-Directory.o: Directory.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-Directory.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-Directory.Tpo" -c -o libaria2c_a-Directory.o `test -f 'Directory.cc' || echo '$(srcdir)/'`Directory.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-Directory.Tpo" "$(DEPDIR)/libaria2c_a-Directory.Po"; else rm -f "$(DEPDIR)/libaria2c_a-Directory.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Directory.cc' object='libaria2c_a-Directory.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-Directory.o `test -f 'Directory.cc' || echo '$(srcdir)/'`Directory.cc
+
+libaria2c_a-Directory.obj: Directory.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-Directory.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-Directory.Tpo" -c -o libaria2c_a-Directory.obj `if test -f 'Directory.cc'; then $(CYGPATH_W) 'Directory.cc'; else $(CYGPATH_W) '$(srcdir)/Directory.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-Directory.Tpo" "$(DEPDIR)/libaria2c_a-Directory.Po"; else rm -f "$(DEPDIR)/libaria2c_a-Directory.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Directory.cc' object='libaria2c_a-Directory.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-Directory.obj `if test -f 'Directory.cc'; then $(CYGPATH_W) 'Directory.cc'; else $(CYGPATH_W) '$(srcdir)/Directory.cc'; fi`
+
aria2c-main.o: main.cc
@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -MT aria2c-main.o -MD -MP -MF "$(DEPDIR)/aria2c-main.Tpo" -c -o aria2c-main.o `test -f 'main.cc' || echo '$(srcdir)/'`main.cc; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/aria2c-main.Tpo" "$(DEPDIR)/aria2c-main.Po"; else rm -f "$(DEPDIR)/aria2c-main.Tpo"; exit 1; fi
diff --git a/src/MetaEntry.h b/src/MetaEntry.h
new file mode 100644
index 00000000..92176221
--- /dev/null
+++ b/src/MetaEntry.h
@@ -0,0 +1,40 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_META_ENTRY_H_
+#define _D_META_ENTRY_H_
+
+//#include "MetaEntryVisitor.h"
+#include "common.h"
+
+class MetaEntryVisitor;
+
+class MetaEntry {
+protected:
+ MetaEntry() {}
+public:
+ virtual ~MetaEntry() {}
+
+ virtual void accept(MetaEntryVisitor* v) const = 0;
+
+};
+
+#endif // _D_META_ENTRY_H_
diff --git a/src/MetaEntryVisitor.h b/src/MetaEntryVisitor.h
new file mode 100644
index 00000000..e4bfe42f
--- /dev/null
+++ b/src/MetaEntryVisitor.h
@@ -0,0 +1,34 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_META_ENTRY_VISITOR_H_
+#define _D_META_ENTRY_VISITOR_H_
+
+#include "MetaEntry.h"
+
+class MetaEntryVisitor {
+public:
+ virtual ~MetaEntryVisitor() {}
+
+ virtual void visit(const MetaEntry* e) = 0;
+};
+
+#endif // _D_META_ENTRY_VISITOR_H_
diff --git a/src/MetaFileUtil.cc b/src/MetaFileUtil.cc
new file mode 100644
index 00000000..bfc662b6
--- /dev/null
+++ b/src/MetaFileUtil.cc
@@ -0,0 +1,170 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "MetaFileUtil.h"
+#include "File.h"
+#include "DlAbortEx.h"
+#include "message.h"
+#include <string.h>
+#include <stdlib.h>
+
+MetaEntry* MetaFileUtil::parseMetaFile(string file) {
+ File f(file);
+ int len = f.size();
+ char* buf = new char[len];
+ FILE* fp = fopen(file.c_str(), "r+");
+ if(fp == NULL) {
+ throw new DlAbortEx("cannot open metainfo file");
+ }
+ if(fread(buf, len, 1, fp) != 1) {
+ fclose(fp);
+ throw new DlAbortEx("cannot read metainfo");
+ }
+ fclose(fp);
+ MetaEntry* entry = bdecoding(buf, len);
+ delete [] buf;
+ return entry;
+}
+
+MetaEntry* MetaFileUtil::bdecoding(const char* buf, int len) {
+ MetaEntry* entry = NULL;
+ try{
+ const char* p = buf;
+ const char* end = buf+len;
+ entry = bdecodingR(&p, end);
+ return entry;
+ } catch(DlAbortEx* ex) {
+ if(entry != NULL) {
+ delete entry;
+ }
+ throw;
+ }
+}
+
+MetaEntry* MetaFileUtil::bdecodingR(const char** pp, const char* end) {
+ if(*pp >= end) {
+ throw new DlAbortEx("mulformed metainfo");
+ }
+ MetaEntry* e;
+ switch(**pp) {
+ case 'd':
+ (*pp)++;
+ e = parseDictionaryTree(pp, end);
+ break;
+ case 'l':
+ (*pp)++;
+ e = parseListTree(pp, end);
+ break;
+ case 'i':
+ (*pp)++;
+ e = decodeInt(pp, end);
+ break;
+ default:
+ e = decodeWord(pp, end);
+ }
+ return e;
+}
+
+Dictionary* MetaFileUtil::parseDictionaryTree(const char** pp, const char* end) {
+ if(*pp >= end) {
+ throw new DlAbortEx("mulformed metainfo");
+ }
+ Dictionary* dic = new Dictionary();
+ while(1) {
+ if(**pp == 'e') {
+ (*pp)++;
+ break;
+ }
+ string name = decodeWordAsString(pp, end);
+ MetaEntry* e = bdecodingR(pp, end);
+ dic->put(name, e);
+ }
+ return dic;
+}
+
+List* MetaFileUtil::parseListTree(const char** pp, const char* end) {
+ if(*pp >= end) {
+ throw new DlAbortEx("mulformed metainfo");
+ }
+ List* lis = new List();
+ while(1) {
+ if(**pp == 'e') {
+ (*pp)++;
+ break;
+ }
+ MetaEntry* e = bdecodingR(pp, end);
+ lis->add(e);
+ }
+ return lis;
+}
+
+Data* MetaFileUtil::decodeInt(const char** pp, const char* end) {
+ if(*pp >= end) {
+ throw new DlAbortEx(EX_MULFORMED_META_INFO);
+ }
+ char* endTerm = (char*)memchr(*pp, 'e', end-*pp);
+ // TODO if endTerm is null
+ if(endTerm == NULL) {
+ throw new DlAbortEx(EX_MULFORMED_META_INFO);
+ }
+ int numSize = endTerm-*pp;
+
+ Data* data = new Data(*pp, numSize, true);
+ *pp += numSize+1;
+ return data;
+}
+
+Data* MetaFileUtil::decodeWord(const char** pp, const char* end) {
+ if(*pp >= end) {
+ throw new DlAbortEx("mulformed metainfo");
+ }
+ char* delim = (char*)memchr(*pp, ':', end-*pp);
+ // TODO if delim is null
+ if(delim == *pp || delim == NULL) {
+ throw new DlAbortEx(EX_MULFORMED_META_INFO);
+ }
+ int numSize = delim-*pp;
+ char* temp = new char[numSize+1];
+ memcpy(temp, *pp, numSize);
+ temp[numSize] = '\0';
+ char* endptr;
+ int size = strtol(temp, &endptr, 10);
+ if(*endptr != '\0') {
+ delete [] temp;
+ throw new DlAbortEx(EX_MULFORMED_META_INFO);
+ }
+ delete [] temp;
+
+ if(delim+1+size > end) {
+ throw new DlAbortEx(EX_MULFORMED_META_INFO);
+ }
+
+ Data* data = new Data(delim+1, size);
+ *pp = delim+1+size;
+ return data;
+}
+
+string MetaFileUtil::decodeWordAsString(const char** pp, const char* end) {
+ Data* data = decodeWord(pp, end);
+ string str = data->toString();
+ delete data;
+ return str;
+}
diff --git a/src/MetaFileUtil.h b/src/MetaFileUtil.h
new file mode 100644
index 00000000..ab123dde
--- /dev/null
+++ b/src/MetaFileUtil.h
@@ -0,0 +1,50 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_META_FILE_UTIL_H_
+#define _D_META_FILE_UTIL_H_
+
+#include "MetaEntry.h"
+#include "Dictionary.h"
+#include "List.h"
+#include "Data.h"
+#include "common.h"
+#include <string>
+
+using namespace std;
+
+class MetaFileUtil {
+private:
+ MetaFileUtil() {}
+
+ static MetaEntry* bdecodingR(const char** pp, const char* end);
+ static Dictionary* parseDictionaryTree(const char** pp, const char* end);
+ static List* parseListTree(const char** pp, const char* end);
+ static Data* decodeWord(const char** pp, const char* end);
+ static Data* decodeInt(const char** pp, const char* end);
+ static string decodeWordAsString(const char** pp, const char* end);
+
+public:
+ static MetaEntry* parseMetaFile(string file);
+ static MetaEntry* bdecoding(const char* buf, int len);
+};
+
+#endif // _D_META_FILE_UTIL_H_
diff --git a/src/Peer.cc b/src/Peer.cc
new file mode 100644
index 00000000..ece5c267
--- /dev/null
+++ b/src/Peer.cc
@@ -0,0 +1,48 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "Peer.h"
+
+Peer* Peer::nullPeer = new Peer("", 0, 0, 0);
+
+void Peer::updateBitfield(int index, int operation) {
+ if(operation == 1) {
+ bitfield->setBit(index);
+ } else if(operation == 0) {
+ bitfield->unsetBit(index);
+ }
+}
+
+#define THRESHOLD 1024*1024*2
+
+bool Peer::shouldChoke() const {
+ if(bitfield->countBlock()*0.8 < bitfield->countMissingBlock()) {
+ return false;
+ }
+ if(peerDownload < pieceLength*4 && peerUpload < pieceLength*4) {
+ return false;
+ }
+ if(amChocking) {
+ return !(peerDownload+pieceLength*4 < peerUpload);
+ } else {
+ return peerDownload >= peerUpload+pieceLength*4;
+ }
+}
diff --git a/src/Peer.h b/src/Peer.h
new file mode 100644
index 00000000..ab5f62ca
--- /dev/null
+++ b/src/Peer.h
@@ -0,0 +1,115 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_PEER_H_
+#define _D_PEER_H_
+
+#include "common.h"
+#include "BitfieldMan.h"
+#include <string.h>
+#include <string>
+
+using namespace std;
+
+#define PEER_ID_LENGTH 20
+
+class Peer {
+public:
+ int entryId;
+ string ipaddr;
+ int port;
+ bool amChocking;
+ bool amInterested;
+ bool peerChoking;
+ bool peerInterested;
+ int tryCount;
+ int error;
+ int cuid;
+private:
+ char peerId[PEER_ID_LENGTH];
+ //unsigned char* bitfield;
+ BitfieldMan* bitfield;
+ //int bitfieldLength;
+ long long int peerUpload;
+ long long int peerDownload;
+ int pieceLength;
+ long long int totalLength;
+public:
+ Peer(string ipaddr, int port, int pieceLength, long long int totalLength):
+ entryId(0), ipaddr(ipaddr), port(port),
+ amChocking(true), amInterested(false),
+ peerChoking(true), peerInterested(false),
+ tryCount(0), error(0), cuid(0),
+ bitfield(NULL),// bitfieldLength(0),
+ peerUpload(0), peerDownload(0),
+ pieceLength(pieceLength), totalLength(totalLength) {
+ this->bitfield = new BitfieldMan(pieceLength, totalLength);
+ }
+
+ ~Peer() {
+ if(bitfield != NULL) {
+ delete /*[]*/ bitfield;
+ }
+ }
+
+ void setPeerId(const char* peerId) {
+ memcpy(this->peerId, peerId, PEER_ID_LENGTH);
+ }
+ const char* getPeerId() const { return this->peerId; }
+
+ void setBitfield(const unsigned char* bitfield, int bitfieldLength) {
+ this->bitfield->setBitfield(bitfield, bitfieldLength);
+ /*
+ if(this->bitfield != NULL) {
+ delete [] this->bitfield;
+ }
+ this->bitfieldLength = bitfieldLength;
+ this->bitfield = new unsigned char[this->bitfieldLength];
+ memcpy(this->bitfield, bitfield, this->bitfieldLength);
+ */
+ }
+ const unsigned char* getBitfield() const { return bitfield->getBitfield(); }
+ int getBitfieldLength() const { return bitfield->getBitfieldLength(); }
+
+ /*
+ void initBitfield(int pieces);
+ */
+
+ /**
+ * operation = 1: set index-th bit 1
+ * operation = 0: set index-th bit 0
+ */
+ void updateBitfield(int index, int operation);
+
+ void addPeerUpload(int size) { peerUpload += size; }
+ void setPeerUpload(long long int size) { peerUpload = size; }
+ long long int getPeerUpload() const { return peerUpload; }
+
+ void addPeerDownload(int size) { peerDownload += size; }
+ void setPeerDownload(long long int size) { peerDownload = size; }
+ long long int getPeerDownload() const { return peerDownload; }
+
+ bool shouldChoke() const;
+
+ static Peer* nullPeer;
+};
+
+#endif // _D_PEER_H_
diff --git a/src/PeerAbstractCommand.cc b/src/PeerAbstractCommand.cc
new file mode 100644
index 00000000..6cbd615c
--- /dev/null
+++ b/src/PeerAbstractCommand.cc
@@ -0,0 +1,181 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "PeerAbstractCommand.h"
+#include "DlAbortEx.h"
+#include "DlRetryEx.h"
+#include <sys/time.h>
+#include "Util.h"
+#include "message.h"
+#include "prefs.h"
+
+PeerAbstractCommand::PeerAbstractCommand(int cuid, Peer* peer, TorrentDownloadEngine* e, Socket* s):
+ Command(cuid), e(e), peer(peer), checkSocketIsReadable(false), checkSocketIsWritable(false) {
+
+ if(s != NULL) {
+ socket = new Socket(*s);
+ setReadCheckSocket(socket);
+ } else {
+ socket = NULL;
+ }
+ this->checkPoint.tv_sec = 0;
+ this->checkPoint.tv_usec = 0;
+
+ e->torrentMan->connections++;
+}
+
+PeerAbstractCommand::~PeerAbstractCommand() {
+ setReadCheckSocket(NULL);
+ setWriteCheckSocket(NULL);
+ if(socket != NULL) {
+ delete(socket);
+ }
+ e->torrentMan->connections--;
+}
+
+void PeerAbstractCommand::updateCheckPoint() {
+ gettimeofday(&checkPoint, NULL);
+}
+
+bool PeerAbstractCommand::isTimeoutDetected() {
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ if(checkPoint.tv_sec == 0 && checkPoint.tv_usec == 0) {
+ checkPoint = now;
+ return false;
+ } else {
+ long long int elapsed = Util::difftv(now, checkPoint);
+ if(elapsed >= e->option->getAsInt(PREF_TIMEOUT)*1000000) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
+
+bool PeerAbstractCommand::execute() {
+ try {
+ if(e->torrentMan->downloadComplete()) {
+ return true;
+ }
+ beforeSocketCheck();
+ if(checkSocketIsReadable && !readCheckTarget->isReadable(0)
+ || checkSocketIsWritable && !writeCheckTarget->isWritable(0)) {
+ if(isTimeoutDetected()) {
+ // TODO
+ checkPoint.tv_sec = 0;
+ checkPoint.tv_usec = 0;
+ throw new DlRetryEx(EX_TIME_OUT);
+ }
+ e->commands.push(this);
+ return false;
+ }
+ updateCheckPoint();
+ bool returnValue = executeInternal();
+ //e->torrentMan->updatePeer(peer);
+ return returnValue;
+ } catch(Exception* err) {
+ e->logger->error(MSG_DOWNLOAD_ABORTED, err, cuid);
+ onAbort(err);
+ delete(err);
+ return prepareForNextPeer(0);
+ } catch(DlRetryEx* err) {
+ e->logger->error(MSG_RESTARTING_DOWNLOAD, err, cuid);
+ peer->tryCount++;
+ bool isAbort = e->option->getAsInt(PREF_MAX_TRIES) != 0 &&
+ peer->tryCount >= e->option->getAsInt(PREF_MAX_TRIES);
+ int tryCount = peer->tryCount;
+ if(isAbort) {
+ onAbort(err);
+ }
+ delete(err);
+ if(isAbort) {
+ e->logger->error(MSG_MAX_TRY, cuid, tryCount);
+ return true;
+ } else {
+ return prepareForRetry(e->option->getAsInt(PREF_RETRY_WAIT));
+ }
+ }
+}
+
+// TODO this method removed when PeerBalancerCommand is implemented
+bool PeerAbstractCommand::prepareForNextPeer(int wait) {
+ return true;
+}
+
+bool PeerAbstractCommand::prepareForRetry(int wait) {
+ return true;
+}
+
+void PeerAbstractCommand::onAbort(Exception* ex) {
+ peer->error = 1;
+ peer->tryCount = 0;
+ peer->cuid = 0;
+ peer->amChocking = true;
+ peer->amInterested = false;
+ peer->peerChoking = true;
+ peer->peerInterested = false;
+ e->logger->debug("CUID#%d - peer %s:%d banned.", cuid, peer->ipaddr.c_str(), peer->port);
+}
+
+void PeerAbstractCommand::setReadCheckSocket(Socket* socket) {
+ if(socket == NULL) {
+ if(checkSocketIsReadable) {
+ e->deleteSocketForReadCheck(readCheckTarget);
+ checkSocketIsReadable = false;
+ readCheckTarget = NULL;
+ }
+ } else {
+ if(checkSocketIsReadable) {
+ if(readCheckTarget != socket) {
+ e->deleteSocketForReadCheck(readCheckTarget);
+ e->addSocketForReadCheck(socket);
+ readCheckTarget = socket;
+ }
+ } else {
+ e->addSocketForReadCheck(socket);
+ checkSocketIsReadable = true;
+ readCheckTarget = socket;
+ }
+ }
+}
+
+void PeerAbstractCommand::setWriteCheckSocket(Socket* socket) {
+ if(socket == NULL) {
+ if(checkSocketIsWritable) {
+ e->deleteSocketForWriteCheck(writeCheckTarget);
+ checkSocketIsWritable = false;
+ writeCheckTarget = NULL;
+ }
+ } else {
+ if(checkSocketIsWritable) {
+ if(writeCheckTarget != socket) {
+ e->deleteSocketForWriteCheck(writeCheckTarget);
+ e->addSocketForWriteCheck(socket);
+ writeCheckTarget = socket;
+ }
+ } else {
+ e->addSocketForWriteCheck(socket);
+ checkSocketIsWritable = true;
+ writeCheckTarget = socket;
+ }
+ }
+}
diff --git a/src/PeerAbstractCommand.h b/src/PeerAbstractCommand.h
new file mode 100644
index 00000000..a6250a02
--- /dev/null
+++ b/src/PeerAbstractCommand.h
@@ -0,0 +1,58 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_PEER_ABSTRACT_COMMAND_H_
+#define _D_PEER_ABSTRACT_COMMAND_H_
+
+#include "Command.h"
+#include "Request.h"
+#include "TorrentDownloadEngine.h"
+#include <sys/time.h>
+
+class PeerAbstractCommand : public Command {
+private:
+ void updateCheckPoint();
+ bool isTimeoutDetected();
+ struct timeval checkPoint;
+protected:
+ TorrentDownloadEngine* e;
+ Socket* socket;
+ Peer* peer;
+
+ virtual bool prepareForNextPeer(int wait);
+ virtual bool prepareForRetry(int wait);
+ virtual void onAbort(Exception* ex);
+ virtual bool executeInternal() = 0;
+ virtual void beforeSocketCheck() {}
+ void setReadCheckSocket(Socket* socket);
+ void setWriteCheckSocket(Socket* socket);
+private:
+ bool checkSocketIsReadable;
+ bool checkSocketIsWritable;
+ Socket* readCheckTarget;
+ Socket* writeCheckTarget;
+public:
+ PeerAbstractCommand(int cuid, Peer* peer, TorrentDownloadEngine* e, Socket* s = NULL);
+ virtual ~PeerAbstractCommand();
+ bool execute();
+};
+
+#endif // _D_PEER_ABSTRACT_COMMAND_H_
diff --git a/src/PeerConnection.cc b/src/PeerConnection.cc
new file mode 100644
index 00000000..af2dfb8b
--- /dev/null
+++ b/src/PeerConnection.cc
@@ -0,0 +1,378 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "PeerConnection.h"
+#include "message.h"
+#include "DlAbortEx.h"
+#include "PeerMessageUtil.h"
+#include "Util.h"
+#include <netinet/in.h>
+
+PeerConnection::PeerConnection(int cuid, const Socket* socket,
+ const Option* op, const Logger* logger,
+ Peer* peer, TorrentMan* torrentMan)
+ :cuid(cuid), socket(socket), option(op), logger(logger), peer(peer),
+ torrentMan(torrentMan),
+ resbufLength(0), currentPayloadLength(0), lenbufLength(0) {}
+
+PeerConnection::~PeerConnection() {}
+
+void PeerConnection::sendHandshake() const {
+ /**
+ * pstrlen --- '19', 1byte
+ * pstr --- "BitTorrent protocol", 19bytes
+ * reserved --- \0 * 8, 8bytes
+ * info_hash --- info_hash, 20bytes
+ * peer_id --- peer_id, 20bytes
+ * total: 68bytes
+ */
+ char msg[HANDSHAKE_MESSAGE_LENGTH];
+ memset(msg, 0, sizeof(msg));
+ msg[0] = 19;
+ memcpy(&msg[1], PSTR, strlen(PSTR));
+ memcpy(&msg[28], torrentMan->getInfoHash(), 20);
+ memcpy(&msg[48], torrentMan->peerId.c_str(), 20);
+ writeOutgoingMessageLog("handshake");
+ socket->writeData(msg, sizeof(msg));
+}
+
+void PeerConnection::sendKeepAlive() const {
+ /**
+ * len --- 0, 4bytes
+ * total: 4bytes
+ */
+ char msg[4];
+ memset(msg, 0, sizeof(msg));
+ writeOutgoingMessageLog("keep-alive");
+ socket->writeData(msg, sizeof(msg));
+}
+
+void PeerConnection::createNLengthMessage(char* msg, int msgLen, int payloadLen, int id) const {
+ assert(msgLen >= 5);
+ memset(msg, 0, msgLen);
+ setIntParam(msg, payloadLen);
+ msg[4] = (char)id;
+}
+
+void PeerConnection::setIntParam(char* dest, int param) const {
+ int nParam = htonl(param);
+ memcpy(dest, &nParam, 4);
+}
+
+void PeerConnection::writeOutgoingMessageLog(const char* msg) const {
+ logger->info(MSG_SEND_PEER_MESSAGE, cuid, peer->ipaddr.c_str(), peer->port, msg);
+}
+
+void PeerConnection::writeOutgoingMessageLog(const char* msg, int index) const {
+ logger->info(MSG_SEND_PEER_MESSAGE_WITH_INDEX, cuid, peer->ipaddr.c_str(), peer->port, msg, index);
+}
+
+void PeerConnection::writeOutgoingMessageLog(const char* msg, const unsigned char* bitfield, int bitfieldLength) const {
+ logger->info(MSG_SEND_PEER_MESSAGE_WITH_BITFIELD, cuid, peer->ipaddr.c_str(), peer->port, msg, Util::toHex(bitfield, bitfieldLength).c_str());
+}
+
+void PeerConnection::writeOutgoingMessageLog(const char* msg, int index, int begin, int length) const {
+ logger->info(MSG_SEND_PEER_MESSAGE_WITH_INDEX_BEGIN_LENGTH, cuid, peer->ipaddr.c_str(), peer->port, msg, index, begin, length);
+}
+
+void PeerConnection::sendChoke() const {
+ /**
+ * len --- 1, 4bytes
+ * id --- 0, 1byte
+ * total: 5bytes
+ */
+ char msg[5];
+ createNLengthMessage(msg, sizeof(msg), 1, 0);
+ writeOutgoingMessageLog("choke");
+ socket->writeData(msg, sizeof(msg));
+}
+
+void PeerConnection::sendUnchoke() const {
+ /**
+ * len --- 1, 4bytes
+ * id --- 1, 1byte
+ * total: 5bytes
+ */
+ char msg[5];
+ createNLengthMessage(msg, sizeof(msg), 1, 1);
+ writeOutgoingMessageLog("unchoke");
+ socket->writeData(msg, sizeof(msg));
+}
+
+void PeerConnection::sendInterested() const {
+ /**
+ * len --- 1, 4bytes
+ * id --- 2, 1byte
+ * total: 5bytes
+ */
+ char msg[5];
+ createNLengthMessage(msg, sizeof(msg), 1, 2);
+ writeOutgoingMessageLog("interested");
+ socket->writeData(msg, sizeof(msg));
+}
+
+void PeerConnection::sendNotInterested() const {
+ /**
+ * len --- 1, 4bytes
+ * id --- 3, 1byte
+ * total: 5bytes
+ */
+ char msg[5];
+ createNLengthMessage(msg, sizeof(msg), 1, 3);
+ writeOutgoingMessageLog("not interested");
+ socket->writeData(msg, sizeof(msg));
+}
+
+void PeerConnection::sendHave(int index) const {
+ /**
+ * len --- 5, 4bytes
+ * id --- 4, 1byte
+ * piece index --- index, 4bytes
+ * total: 9bytes
+ */
+ char msg[9];
+ createNLengthMessage(msg, sizeof(msg), 5, 4);
+ setIntParam(&msg[5], index);
+ writeOutgoingMessageLog("have", index);
+ socket->writeData(msg, sizeof(msg));
+}
+
+void PeerConnection::sendBitfield() const {
+ int len = torrentMan->getBitfieldLength();
+ const unsigned char* bitfield = torrentMan->getBitfield();
+ /**
+ * len --- 1+len, 4bytes
+ * id --- 5, 1byte
+ * bitfield --- bitfield, len bytes
+ * total: 5+len bytes
+ */
+ int msgLen = 5+len;
+ char* msg = new char[msgLen];
+ try {
+ createNLengthMessage(msg, msgLen, 1+len, 5);
+ writeOutgoingMessageLog("bitfield", bitfield, len);
+ socket->writeData(msg, msgLen);
+ delete [] msg;
+ } catch(Exception* ex) {
+ delete [] msg;
+ throw;
+ }
+}
+
+void PeerConnection::sendRequest(int index, int begin, int length) const {
+ /**
+ * len --- 13, 4bytes
+ * id --- 6, 1byte
+ * index --- index, 4bytes
+ * begin --- begin, 4bytes
+ * length --- length, 4bytes
+ * total: 17bytes
+ */
+ char msg[17];
+ createNLengthMessage(msg, sizeof(msg), 13, 6);
+ setIntParam(&msg[5], index);
+ setIntParam(&msg[9], begin);
+ setIntParam(&msg[13], length);
+ writeOutgoingMessageLog("request", index, begin, length);
+ socket->writeData(msg, sizeof(msg));
+}
+
+void PeerConnection::sendPiece(int index, int begin, int length) const {
+ /**
+ * len --- 9+length, 4bytes
+ * id --- 7, 1byte
+ * index --- index, 4bytes
+ * begin --- begin, 4bytes
+ * sub total: 13bytes
+ * additionally,
+ * block --- data, X bytes
+ */
+ char msg[13];
+ createNLengthMessage(msg, sizeof(msg), 9+length, 7);
+ setIntParam(&msg[5], index);
+ setIntParam(&msg[9], begin);
+ writeOutgoingMessageLog("piece", index, begin, length);
+ socket->writeData(msg, sizeof(msg));
+ int BUF_SIZE = 4096;
+ char buf[BUF_SIZE];
+ int iteration = length/BUF_SIZE;
+ long long int pieceOffset = ((long long int)index*torrentMan->pieceLength)+begin;
+ for(int i = 0; i < iteration; i++) {
+ if(torrentMan->diskWriter->readData(buf, BUF_SIZE, pieceOffset+i*BUF_SIZE) < BUF_SIZE) {
+ throw new DlAbortEx("piece reading failed.");
+ }
+ socket->writeData(buf, BUF_SIZE);
+ }
+ int rem = length%BUF_SIZE;
+ if(rem > 0) {
+ if(torrentMan->diskWriter->readData(buf, rem, pieceOffset+iteration*BUF_SIZE) < rem) {
+ throw new DlAbortEx("piece reading failed.");
+ }
+ socket->writeData(buf, rem);
+ }
+}
+
+void PeerConnection::sendPieceHeader(int index, int begin, int length) const {
+ /**
+ * len --- 9+length, 4bytes
+ * id --- 7, 1byte
+ * index --- index, 4bytes
+ * begin --- begin, 4bytes
+ * sub total: 13bytes
+ * additionally,
+ * block --- data, X bytes
+ */
+ char msg[13];
+ createNLengthMessage(msg, sizeof(msg), 9+length, 7);
+ setIntParam(&msg[5], index);
+ setIntParam(&msg[9], begin);
+ writeOutgoingMessageLog("piece", index, begin, length);
+ socket->writeData(msg, sizeof(msg));
+}
+
+int PeerConnection::sendPieceData(long long int offset, int length) const {
+ int BUF_SIZE = 256;
+ char buf[BUF_SIZE];
+ int iteration = length/BUF_SIZE;
+ int writtenLength = 0;
+ bool isWritable = true;
+ for(int i = 0; i < iteration; i++) {
+ isWritable = socket->isWritable(0);
+ if(!isWritable) {
+ return writtenLength;
+ }
+ if(torrentMan->diskWriter->readData(buf, BUF_SIZE, offset+i*BUF_SIZE) < BUF_SIZE) {
+ throw new DlAbortEx("piece reading failed.");
+ }
+ socket->writeData(buf, BUF_SIZE);
+ writtenLength += BUF_SIZE;
+ }
+ if(socket->isWritable(0)) {
+ int rem = length%BUF_SIZE;
+ if(rem > 0) {
+ if(torrentMan->diskWriter->readData(buf, rem, offset+iteration*BUF_SIZE) < rem) {
+ throw new DlAbortEx("piece reading failed.");
+ }
+ socket->writeData(buf, rem);
+ writtenLength += rem;
+ }
+ }
+ return writtenLength;
+}
+
+
+void PeerConnection::sendCancel(int index, int begin, int length) const {
+ /**
+ * len --- 13, 4bytes
+ * id --- 8, 1byte
+ * index --- index, 4bytes
+ * begin --- begin, 4bytes
+ * length -- length, 4bytes
+ * total: 17bytes
+ */
+ char msg[17];
+ createNLengthMessage(msg, sizeof(msg), 13, 8);
+ setIntParam(&msg[5], index);
+ setIntParam(&msg[9], begin);
+ setIntParam(&msg[13], length);
+ writeOutgoingMessageLog("cancel", index, begin, length);
+ socket->writeData(msg, sizeof(msg));
+}
+
+PeerMessage* PeerConnection::receiveMessage() {
+ if(!socket->isReadable(0)) {
+ return NULL;
+ }
+ if(resbufLength == 0 && lenbufLength != 4) {
+ // read payload size, 4-byte integer
+ int remain = 4-lenbufLength;
+ int temp = remain;
+ socket->readData(lenbuf+lenbufLength, temp);
+ if(temp == 0) {
+ // we got EOF
+ throw new DlAbortEx(EX_EOF_FROM_PEER);
+ }
+ if(remain != temp) {
+ // still 4-temp bytes to go
+ lenbufLength += temp;
+ return NULL;
+ }
+ //payloadLen = ntohl(nPayloadLen);
+ int payloadLength = ntohl(*((int*)lenbuf));
+ if(payloadLength > MAX_PAYLOAD_LEN) {
+ throw new DlAbortEx("max payload length exceeded. length = %d",
+ payloadLength);
+ }
+ currentPayloadLength = payloadLength;
+ }
+ // we have currentPayloadLen-resbufLen bytes to read
+ int remaining = currentPayloadLength-resbufLength;
+ if(remaining > 0) {
+ socket->readData(resbuf+resbufLength, remaining);
+ if(remaining == 0) {
+ // we got EOF
+ throw new DlAbortEx(EX_EOF_FROM_PEER);
+ }
+ resbufLength += remaining;
+ if(currentPayloadLength != resbufLength) {
+ return NULL;
+ }
+ }
+ // we got whole payload.
+ resbufLength = 0;
+ lenbufLength = 0;
+ PeerMessage* peerMessage = PeerMessageUtil::createPeerMessage(resbuf, currentPayloadLength);
+ try {
+ PeerMessageUtil::checkIntegrity(peerMessage, torrentMan->pieceLength,
+ torrentMan->pieces, torrentMan->totalSize);
+ } catch(Exception* e) {
+ delete peerMessage;
+ throw;
+ }
+ return peerMessage;
+}
+
+HandshakeMessage* PeerConnection::receiveHandshake() {
+ if(!socket->isReadable(0)) {
+ return NULL;
+ }
+ int remain = HANDSHAKE_MESSAGE_LENGTH-resbufLength;
+ int temp = remain;
+ socket->readData(resbuf+resbufLength, temp);
+ if(temp == 0) {
+ // we got EOF
+ throw new DlAbortEx(EX_EOF_FROM_PEER);
+ }
+ if(remain != temp) {
+ resbufLength += temp;
+ return NULL;
+ }
+ // we got whole handshake payload
+ resbufLength = 0;
+ HandshakeMessage* handshakeMessage = PeerMessageUtil::createHandshakeMessage(resbuf);
+ try {
+ PeerMessageUtil::checkHandshake(handshakeMessage, torrentMan->getInfoHash());
+ } catch(Exception* e) {
+ delete handshakeMessage;
+ throw;
+ }
+ return handshakeMessage;
+}
diff --git a/src/PeerConnection.h b/src/PeerConnection.h
new file mode 100644
index 00000000..9c8401e7
--- /dev/null
+++ b/src/PeerConnection.h
@@ -0,0 +1,82 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_PEER_CONNECTION_H_
+#define _D_PEER_CONNECTION_H_
+
+#include "Option.h"
+#include "Socket.h"
+#include "Logger.h"
+#include "TorrentMan.h"
+#include "PeerMessage.h"
+#include "HandshakeMessage.h"
+
+// we assume maximum length of incoming message is "piece" message with 16KB
+// data. Messages beyond that size are dropped.
+#define MAX_PAYLOAD_LEN (9+16*1024)
+
+class PeerConnection {
+private:
+ int cuid;
+ const Socket* socket;
+ const Option* option;
+ const Logger* logger;
+ Peer* peer;
+ TorrentMan* torrentMan;
+
+ char resbuf[MAX_PAYLOAD_LEN];
+ int resbufLength;
+ int currentPayloadLength;
+ char lenbuf[4];
+ int lenbufLength;
+
+ void createNLengthMessage(char* msg, int msgLen, int payloadLen, int id) const;
+ void setIntParam(char* dest, int param) const;
+
+ void writeOutgoingMessageLog(const char* msg) const;
+ void writeOutgoingMessageLog(const char* msg, int index) const;
+ void writeOutgoingMessageLog(const char* msg, const unsigned char* bitfield, int bitfieldLength) const;
+ void writeOutgoingMessageLog(const char* msg, int index, int begin, int length) const;
+public:
+ PeerConnection(int cuid, const Socket* socket, const Option* op,
+ const Logger* logger, Peer* peer, TorrentMan* torrenMan);
+ ~PeerConnection();
+
+ void sendHandshake() const;
+ void sendKeepAlive() const;
+ void sendChoke() const;
+ void sendUnchoke() const;
+ void sendInterested() const;
+ void sendNotInterested() const;
+ void sendHave(int index) const;
+ void sendBitfield() const;
+ void sendRequest(int index, int begin, int length) const;
+ void sendPiece(int index, int begin, int length) const;
+ void sendPieceHeader(int index, int begin, int length) const;
+ int sendPieceData(long long int offset, int length) const;
+ void sendCancel(int index, int begin, int length) const;
+ PeerMessage* receiveMessage();
+ HandshakeMessage* receiveHandshake();
+
+ Peer* getPeer() const { return peer; }
+};
+
+#endif // _D_PEER_CONNECTION_H_
diff --git a/src/PeerInitiateConnectionCommand.cc b/src/PeerInitiateConnectionCommand.cc
new file mode 100644
index 00000000..441d5e27
--- /dev/null
+++ b/src/PeerInitiateConnectionCommand.cc
@@ -0,0 +1,74 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "PeerInitiateConnectionCommand.h"
+#include "PeerInteractionCommand.h"
+#include "Util.h"
+#include "DlAbortEx.h"
+#include "message.h"
+#include "prefs.h"
+
+PeerInitiateConnectionCommand::PeerInitiateConnectionCommand(int cuid,
+ Peer* peer,
+ TorrentDownloadEngine* e)
+ :PeerAbstractCommand(cuid, peer, e) {}
+
+PeerInitiateConnectionCommand::~PeerInitiateConnectionCommand() {}
+
+bool PeerInitiateConnectionCommand::executeInternal() {
+ socket = new Socket();
+ // socket->establishConnection(...);
+
+ Command* command;
+ e->logger->info(MSG_CONNECTING_TO_SERVER, cuid, peer->ipaddr.c_str(),
+ peer->port);
+ socket->establishConnection(peer->ipaddr, peer->port);
+ command = new PeerInteractionCommand(cuid, peer, e, socket, PeerInteractionCommand::INITIATOR_SEND_HANDSHAKE);
+
+ e->commands.push(command);
+ return true;
+}
+
+// TODO this method removed when PeerBalancerCommand is implemented
+bool PeerInitiateConnectionCommand::prepareForNextPeer(int wait) {
+ if(e->torrentMan->isPeerAvailable()) {
+ Peer* peer = e->torrentMan->getPeer();
+ int newCuid = e->torrentMan->getNewCuid();
+ peer->cuid = newCuid;
+ PeerInitiateConnectionCommand* command = new PeerInitiateConnectionCommand(newCuid, peer, e);
+ e->commands.push(command);
+ }
+ return true;
+}
+
+bool PeerInitiateConnectionCommand::prepareForRetry(int wait) {
+ PeerInitiateConnectionCommand* command = new PeerInitiateConnectionCommand(cuid, peer, e);
+ e->commands.push(command);
+ return true;
+}
+
+bool PeerInitiateConnectionCommand::useProxy() {
+ return e->option->get(PREF_HTTP_PROXY_ENABLED) == V_TRUE;
+}
+
+bool PeerInitiateConnectionCommand::useProxyTunnel() {
+ return e->option->get(PREF_HTTP_PROXY_METHOD) == V_TUNNEL;
+}
diff --git a/src/PeerInitiateConnectionCommand.h b/src/PeerInitiateConnectionCommand.h
new file mode 100644
index 00000000..64c2a7d2
--- /dev/null
+++ b/src/PeerInitiateConnectionCommand.h
@@ -0,0 +1,40 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_PEER_INITIATE_CONNECTION_H_
+#define _D_PEER_INITIATE_CONNECTION_H_
+
+#include "PeerAbstractCommand.h"
+
+class PeerInitiateConnectionCommand : public PeerAbstractCommand {
+private:
+ bool useProxy();
+ bool useProxyTunnel();
+protected:
+ bool executeInternal();
+ bool prepareForRetry(int wait);
+ bool prepareForNextPeer(int wait);
+public:
+ PeerInitiateConnectionCommand(int cuid, Peer* peer, TorrentDownloadEngine* e);
+ ~PeerInitiateConnectionCommand();
+};
+
+#endif // _D_PEER_INITIATE_CONNECTION_H_
diff --git a/src/PeerInteractionCommand.cc b/src/PeerInteractionCommand.cc
new file mode 100644
index 00000000..0d81fba7
--- /dev/null
+++ b/src/PeerInteractionCommand.cc
@@ -0,0 +1,477 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "PeerInteractionCommand.h"
+#include "PeerInitiateConnectionCommand.h"
+#include "PeerMessageUtil.h"
+#include "DlAbortEx.h"
+#include "Util.h"
+#include "message.h"
+
+PeerInteractionCommand::PeerInteractionCommand(int cuid, Peer* peer,
+ TorrentDownloadEngine* e,
+ Socket* s, int sequence)
+ :PeerAbstractCommand(cuid, peer, e, s), sequence(sequence) {
+ if(sequence == INITIATOR_SEND_HANDSHAKE) {
+ setReadCheckSocket(NULL);
+ setWriteCheckSocket(socket);
+ }
+ peerConnection = new PeerConnection(cuid, socket, e->option, e->logger,
+ peer, e->torrentMan);
+ requestSlotMan = new RequestSlotMan(cuid, &pendingMessages, peerConnection,
+ e->torrentMan, e->logger);
+ piece = Piece::nullPiece;
+ keepAliveCheckPoint.tv_sec = 0;
+ keepAliveCheckPoint.tv_usec = 0;
+}
+
+PeerInteractionCommand::~PeerInteractionCommand() {
+ delete peerConnection;
+ delete requestSlotMan;
+}
+
+bool PeerInteractionCommand::executeInternal() {
+ if(sequence == INITIATOR_SEND_HANDSHAKE) {
+ socket->setBlockingMode();
+ setReadCheckSocket(socket);
+ }
+ setWriteCheckSocket(NULL);
+
+ switch(sequence) {
+ case INITIATOR_SEND_HANDSHAKE:
+ peerConnection->sendHandshake();
+ sequence = INITIATOR_WAIT_HANDSHAKE;
+ break;
+ case INITIATOR_WAIT_HANDSHAKE: {
+ HandshakeMessage* handshakeMessage = peerConnection->receiveHandshake();
+ if(handshakeMessage == NULL) {
+ break;
+ }
+ peer->setPeerId(handshakeMessage->peerId);
+ e->logger->info(MSG_RECEIVE_PEER_MESSAGE, cuid,
+ peer->ipaddr.c_str(), peer->port,
+ handshakeMessage->toString().c_str());
+ delete handshakeMessage;
+ if(e->torrentMan->getDownloadedSize() > 0) {
+ peerConnection->sendBitfield();
+ }
+ sequence = WIRED;
+ break;
+ }
+ case RECEIVER_WAIT_HANDSHAKE: {
+ HandshakeMessage* handshakeMessage = peerConnection->receiveHandshake();
+ if(handshakeMessage == NULL) {
+ break;
+ }
+ peer->setPeerId(handshakeMessage->peerId);
+ e->logger->info(MSG_RECEIVE_PEER_MESSAGE, cuid,
+ peer->ipaddr.c_str(), peer->port,
+ handshakeMessage->toString().c_str());
+ delete handshakeMessage;
+ peerConnection->sendHandshake();
+ if(e->torrentMan->getDownloadedSize() > 0) {
+ peerConnection->sendBitfield();
+ }
+ sequence = WIRED;
+ break;
+ }
+ case WIRED:
+ syncPiece();
+ decideChoking();
+ for(int i = 0; i < 10; i++) {
+ if(!socket->isReadable(0)) {
+ break;
+ }
+ receiveMessage();
+ }
+ //detectTimeoutAndDuplicateBlock();
+ requestSlotMan->deleteTimedoutRequestSlot(piece);
+ requestSlotMan->deleteCompletedRequestSlot(piece);
+ sendInterest();
+ sendMessages();
+ break;
+ }
+ if(pendingMessages.size() > 0) {
+ setWriteCheckSocket(socket);
+ }
+ e->commands.push(this);
+ return false;
+}
+
+void PeerInteractionCommand::syncPiece() {
+ if(Piece::isNull(piece)) {
+ return;
+ }
+ e->torrentMan->syncPiece(piece);
+}
+
+void PeerInteractionCommand::decideChoking() {
+ if(peer->shouldChoke()) {
+ if(!peer->amChocking) {
+ PendingMessage pendingMessage(PeerMessage::CHOKE, peerConnection);
+ pendingMessages.push_back(pendingMessage);
+ }
+ } else if(peer->amChocking && peer->peerInterested) {
+ PendingMessage pendingMessage(PeerMessage::UNCHOKE, peerConnection);
+ pendingMessages.push_back(pendingMessage);
+ } else if(!peer->peerInterested) {
+ PendingMessage pendingMessage(PeerMessage::CHOKE, peerConnection);
+ pendingMessages.push_back(pendingMessage);
+ }
+}
+
+void PeerInteractionCommand::receiveMessage() {
+ PeerMessage* message = peerConnection->receiveMessage();
+ if(message == NULL) {
+ return;
+ }
+ e->logger->info(MSG_RECEIVE_PEER_MESSAGE, cuid,
+ peer->ipaddr.c_str(), peer->port,
+ message->toString().c_str());
+ try {
+ switch(message->getId()) {
+ case PeerMessage::KEEP_ALIVE:
+ break;
+ case PeerMessage::CHOKE:
+ peer->peerChoking = true;
+ requestSlotMan->deleteAllRequestSlot(piece);
+ break;
+ case PeerMessage::UNCHOKE:
+ peer->peerChoking = false;
+ break;
+ case PeerMessage::INTERESTED:
+ peer->peerInterested = true;
+ break;
+ case PeerMessage::NOT_INTERESTED:
+ peer->peerInterested = false;
+ break;
+ case PeerMessage::HAVE:
+ peer->updateBitfield(message->getIndex(), 1);
+ break;
+ case PeerMessage::BITFIELD:
+ peer->setBitfield(message->getBitfield(), message->getBitfieldLength());
+ break;
+ case PeerMessage::REQUEST:
+ if(e->torrentMan->hasPiece(message->getIndex())) {
+ PendingMessage pendingMessage
+ = PendingMessage::createPieceMessage(message->getIndex(),
+ message->getBegin(),
+ message->getLength(),
+ e->torrentMan->pieceLength,
+ peerConnection);
+ pendingMessages.push_back(pendingMessage);
+ e->torrentMan->addUploadedSize(message->getLength());
+ e->torrentMan->addDeltaUpload(message->getLength());
+ }
+ break;
+ case PeerMessage::CANCEL:
+ deletePendingMessage(message);
+ break;
+ case PeerMessage::PIECE: {
+ RequestSlot slot = requestSlotMan->getCorrespoindingRequestSlot(message);
+ peer->addPeerUpload(message->getBlockLength());
+ if(!Piece::isNull(piece) && !RequestSlot::isNull(slot)) {
+ long long int offset =
+ ((long long int)message->getIndex())*e->torrentMan->pieceLength+message->getBegin();
+ e->logger->debug("CUID#%d - write block length = %d, offset=%lld",
+ cuid, message->getBlockLength(), offset);
+ e->torrentMan->diskWriter->writeData(message->getBlock(),
+ message->getBlockLength(),
+ offset);
+ piece.completeBlock(slot.getBlockIndex());
+ requestSlotMan->deleteRequestSlot(slot);
+ e->torrentMan->updatePiece(piece);
+ e->logger->debug("CUID#%d - setting piece bit index=%d", cuid,
+ slot.getBlockIndex());
+ e->torrentMan->addDeltaDownload(message->getBlockLength());
+ if(piece.pieceComplete()) {
+ if(checkPieceHash(piece)) {
+ onGotNewPiece();
+ } else {
+ onGotWrongPiece();
+ }
+ }
+ }
+ break;
+ }
+ }
+ delete message;
+ } catch(Exception* ex) {
+ delete message;
+ throw;
+ }
+}
+
+void PeerInteractionCommand::deletePendingMessage(PeerMessage* cancelMessage) {
+ for(PendingMessages::iterator itr = pendingMessages.begin();
+ itr != pendingMessages.end();) {
+ PendingMessage& pendingMessage = *itr;
+ if(pendingMessage.getPeerMessageId() == PeerMessage::PIECE &&
+ pendingMessage.getIndex() == cancelMessage->getIndex() &&
+ pendingMessage.getBegin() == cancelMessage->getBegin() &&
+ pendingMessage.getLength() == cancelMessage->getLength() &&
+ !pendingMessage.isInProgress()) {
+ e->logger->debug("CUID#%d - deleting pending piece message because cancel message received. index=%d, begin=%d, length=%d",
+ cuid,
+ pendingMessage.getIndex(),
+ pendingMessage.getBegin(),
+ pendingMessage.getLength());
+ itr = pendingMessages.erase(itr);
+ } else {
+ itr++;
+ }
+ }
+}
+
+void PeerInteractionCommand::onGotNewPiece() {
+ e->logger->info(MSG_GOT_NEW_PIECE, cuid, piece.getIndex());
+ e->torrentMan->completePiece(piece);
+ e->torrentMan->advertisePiece(cuid, piece.getIndex());
+ piece = Piece::nullPiece;
+}
+
+void PeerInteractionCommand::onGotWrongPiece() {
+ e->logger->error(MSG_GOT_WRONG_PIECE, cuid, piece.getIndex());
+ erasePieceOnDisk(piece);
+ piece.clearAllBlock();
+ e->torrentMan->updatePiece(piece);
+}
+
+/*
+const RequestSlot& PeerInteractionCommand::getRequestSlot(int index, int begin, int length) const {
+ for(RequestSlots::const_iterator itr = requestSlots.begin(); itr != requestSlots.end(); itr++) {
+ const RequestSlot& slot = *itr;
+ if(slot.index == index && slot.begin == begin && slot.length == length) {
+ return slot;
+ }
+ }
+ return RequestSlot::nullSlot;
+}
+*/
+/*
+bool PeerInteractionCommand::deleteRequestSlot(const RequestSlot& slot) {
+ for(RequestSlots::iterator itr = requestSlots.begin(); itr != requestSlots.end(); itr++) {
+ if(slot.index == itr->index && slot.begin == itr->begin && slot.length == itr->length) {
+ requestSlots.erase(itr);
+ return true;
+ }
+ }
+ return false;
+}
+*/
+/*
+void PeerInteractionCommand::deleteAllRequestSlot() {
+ if(!Piece::isNull(piece)) {
+ for(RequestSlots::const_iterator itr = requestSlots.begin(); itr != requestSlots.end(); itr++) {
+ if(itr->index == piece.getIndex()) {
+ piece.cancelBlock(itr->blockIndex);
+ }
+ }
+ e->torrentMan->updatePiece(piece);
+ }
+ requestSlots.clear();
+}
+*/
+// TODO this method removed when PeerBalancerCommand is implemented
+bool PeerInteractionCommand::prepareForNextPeer(int wait) {
+ if(e->torrentMan->isPeerAvailable()) {
+ Peer* peer = e->torrentMan->getPeer();
+ int newCuid = e->torrentMan->getNewCuid();
+ peer->cuid = newCuid;
+ PeerInitiateConnectionCommand* command = new PeerInitiateConnectionCommand(newCuid, peer, e);
+ e->commands.push(command);
+ }
+ return true;
+}
+
+bool PeerInteractionCommand::prepareForRetry(int wait) {
+ e->commands.push(this);
+ return false;
+}
+/*
+void PeerInteractionCommand::detectTimeoutAndDuplicateBlock() {
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ for(RequestSlots::iterator itr = requestSlots.begin(); itr != requestSlots.end();) {
+ const RequestSlot& slot = *itr;
+ if(slot.isTimeout(120) || piece.hasBlock(slot.blockIndex)) {
+ e->logger->debug("CUID#%d - deleting requestslot blockIndex %d", cuid, slot.blockIndex);
+ if(slot.isTimeout(120)) {
+ e->logger->debug("CUID#%d - because of timeout", cuid);
+ } else {
+ e->logger->debug("CUID#%d - because of duplicate block", cuid);
+ }
+ piece.cancelBlock(slot.blockIndex);
+ e->torrentMan->updatePiece(piece);
+ // send cancel message
+ PendingMessage pendingMessage =
+ PendingMessage::createCancelMessage(piece.getIndex(),
+ slot.blockIndex*piece.getBlockLength(),
+ piece.getBlockLength(slot.blockIndex),
+ peerConnection);
+ pendingMessages.push_back(pendingMessage);
+ itr = requestSlots.erase(itr);
+ } else {
+ itr++;
+ }
+ }
+}
+*/
+Piece PeerInteractionCommand::getNewPieceAndSendInterest() {
+ Piece piece = e->torrentMan->getMissingPiece(peer->getBitfield(),
+ peer->getBitfieldLength());
+ if(Piece::isNull(piece)) {
+ e->logger->debug("CUID#%d - try to send not-interested", cuid);
+ PendingMessage pendingMessage(PeerMessage::NOT_INTERESTED, peerConnection);
+ pendingMessages.push_back(pendingMessage);
+ } else {
+ e->logger->debug("CUID#%d - try to send interested", cuid);
+ PendingMessage pendingMessage(PeerMessage::INTERESTED, peerConnection);
+ pendingMessages.push_back(pendingMessage);
+ //piecefield = new BitfieldMan(16*1024, piece.length);
+ }
+ return piece;
+}
+
+void PeerInteractionCommand::sendInterest() {
+ if(Piece::isNull(piece)) {
+ // retrive new piece from TorrentMan
+ piece = getNewPieceAndSendInterest();
+ } else if(peer->peerChoking) {
+ // TODO separate method is better
+ requestSlotMan->deleteAllRequestSlot(piece);
+ e->torrentMan->cancelPiece(piece);
+ piece = Piece::nullPiece;
+ } else if(piece.pieceComplete()) {
+ piece = getNewPieceAndSendInterest();
+ }
+}
+
+void PeerInteractionCommand::createRequestPendingMessage(int blockIndex) {
+ PendingMessage pendingMessage =
+ PendingMessage::createRequestMessage(piece.getIndex(),
+ blockIndex*piece.getBlockLength(),
+ piece.getBlockLength(blockIndex),
+ peerConnection);
+ pendingMessages.push_back(pendingMessage);
+ RequestSlot requestSlot(piece.getIndex(),
+ blockIndex*piece.getBlockLength(),
+ piece.getBlockLength(blockIndex),
+ blockIndex);
+ requestSlotMan->addRequestSlot(requestSlot);
+}
+
+void PeerInteractionCommand::sendMessages() {
+ if(!Piece::isNull(piece) && !peer->peerChoking) {
+ if(e->torrentMan->isEndGame()) {
+ vector<int> missingBlockIndexes = piece.getAllMissingBlockIndexes();
+ if(requestSlotMan->isEmpty()) {
+ for(vector<int>::const_iterator itr = missingBlockIndexes.begin();
+ itr != missingBlockIndexes.end(); itr++) {
+ createRequestPendingMessage(*itr);
+ }
+ }
+ } else {
+ for(int i = requestSlotMan->countRequestSlot(); i <= 5; i++) {
+ int blockIndex = piece.getMissingUnusedBlockIndex();
+ if(blockIndex == -1) {
+ if(requestSlotMan->isEmpty()) {
+ piece = Piece::nullPiece;
+ }
+ break;
+ }
+ e->torrentMan->updatePiece(piece);
+ createRequestPendingMessage(blockIndex);
+ }
+ }
+ }
+
+ for(PendingMessages::iterator itr = pendingMessages.begin(); itr != pendingMessages.end();) {
+ if(itr->processMessage()) {
+ itr = pendingMessages.erase(itr);
+ } else {
+ //setWriteCheckSocket(socket);
+ break;
+ }
+ }
+}
+
+void PeerInteractionCommand::onAbort(Exception* ex) {
+ requestSlotMan->deleteAllRequestSlot(piece);
+ e->torrentMan->cancelPiece(piece);
+ PeerAbstractCommand::onAbort(ex);
+}
+
+void PeerInteractionCommand::keepAlive() {
+ if(keepAliveCheckPoint.tv_sec == 0 && keepAliveCheckPoint.tv_usec == 0) {
+ gettimeofday(&keepAliveCheckPoint, NULL);
+ } else {
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ if(Util::difftv(now, keepAliveCheckPoint) >= 120*1000000) {
+ if(pendingMessages.empty()) {
+ peerConnection->sendKeepAlive();
+ }
+ keepAliveCheckPoint = now;
+ }
+ }
+}
+
+void PeerInteractionCommand::beforeSocketCheck() {
+ if(sequence == WIRED) {
+ e->torrentMan->unadvertisePiece(cuid);
+
+ vector<int> indexes = e->torrentMan->getAdvertisedPieceIndexes(cuid);
+ if(indexes.size() >= 20) {
+ PendingMessage pendingMessage(PeerMessage::BITFIELD, peerConnection);
+ pendingMessages.push_back(pendingMessage);
+ } else {
+ for(vector<int>::iterator itr = indexes.begin(); itr != indexes.end(); itr++) {
+ PendingMessage pendingMessage = PendingMessage::createHaveMessage(*itr, peerConnection);
+ pendingMessages.push_back(pendingMessage);
+ }
+ }
+ if(indexes.size() == 0) {
+ keepAlive();
+ }
+ }
+}
+
+bool PeerInteractionCommand::checkPieceHash(const Piece& piece) {
+ long long int offset = ((long long int)piece.getIndex())*e->torrentMan->pieceLength;
+ return e->torrentMan->diskWriter->sha1Sum(offset, piece.getLength()) ==
+ e->torrentMan->getPieceHash(piece.getIndex());
+}
+
+void PeerInteractionCommand::erasePieceOnDisk(const Piece& piece) {
+ int BUFSIZE = 4096;
+ char buf[BUFSIZE];
+ memset(buf, 0, BUFSIZE);
+ long long int offset = ((long long int)piece.getIndex())*e->torrentMan->pieceLength;
+ for(int i = 0; i < piece.getLength()/BUFSIZE; i++) {
+ e->torrentMan->diskWriter->writeData(buf, BUFSIZE, offset);
+ offset += BUFSIZE;
+ }
+ int r = piece.getLength()%BUFSIZE;
+ if(r > 0) {
+ e->torrentMan->diskWriter->writeData(buf, r, offset);
+ }
+}
diff --git a/src/PeerInteractionCommand.h b/src/PeerInteractionCommand.h
new file mode 100644
index 00000000..0bfe7e97
--- /dev/null
+++ b/src/PeerInteractionCommand.h
@@ -0,0 +1,76 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_PEER_INTERACTION_COMMAND_H_
+#define _D_PEER_INTERACTION_COMMAND_H_
+
+#include "PeerAbstractCommand.h"
+#include "PeerConnection.h"
+#include "PendingMessage.h"
+#include "RequestSlotMan.h"
+#include <vector>
+
+using namespace std;
+
+class PeerInteractionCommand : public PeerAbstractCommand {
+private:
+ int sequence;
+ PeerConnection* peerConnection;
+ RequestSlotMan* requestSlotMan;
+ PendingMessages pendingMessages;
+ Piece piece;
+ struct timeval keepAliveCheckPoint;
+ void receiveMessage();
+ void syncPiece();
+ void detectTimeoutAndDuplicateBlock();
+ void decideChoking();
+ void sendInterest();
+ void sendMessages();
+ void createRequestPendingMessage(int blockIndex);
+ void deletePendingMessage(PeerMessage* cancelMessage);
+ const RequestSlot& getRequestSlot(int index, int begin, int length) const;
+ bool deleteRequestSlot(const RequestSlot& slot);
+ void deleteAllRequestSlot();
+ bool checkPieceHash(const Piece& piece);
+ void erasePieceOnDisk(const Piece& piece);
+ void keepAlive();
+ Piece getNewPieceAndSendInterest();
+ void onGotNewPiece();
+ void onGotWrongPiece();
+protected:
+ bool executeInternal();
+ bool prepareForRetry(int wait);
+ bool prepareForNextPeer(int wait);
+ void onAbort(Exception* ex);
+ void beforeSocketCheck();
+public:
+ PeerInteractionCommand(int cuid, Peer* peer, TorrentDownloadEngine* e, Socket* s, int sequence);
+ ~PeerInteractionCommand();
+
+ enum Seq {
+ INITIATOR_SEND_HANDSHAKE,
+ INITIATOR_WAIT_HANDSHAKE,
+ RECEIVER_SEND_HANDSHAKE,
+ RECEIVER_WAIT_HANDSHAKE,
+ WIRED};
+};
+
+#endif // _D_PEER_INTERACTION_COMMAND_H_
diff --git a/src/PeerListenCommand.cc b/src/PeerListenCommand.cc
new file mode 100644
index 00000000..bf8efe67
--- /dev/null
+++ b/src/PeerListenCommand.cc
@@ -0,0 +1,91 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "PeerListenCommand.h"
+#include "PeerInteractionCommand.h"
+
+PeerListenCommand::PeerListenCommand(int cuid, TorrentDownloadEngine* e)
+ :Command(cuid), e(e), socket(NULL) {
+}
+
+PeerListenCommand::~PeerListenCommand() {
+ if(socket != NULL) {
+ delete socket;
+ }
+}
+
+int PeerListenCommand::bindPort(int portRangeStart, int portRangeEnd) {
+ if(portRangeStart > portRangeEnd) {
+ return -1;
+ }
+ for(int port = portRangeStart; port <= portRangeEnd; port++) {
+ try {
+ socket = new Socket();
+ socket->beginListen(port);
+ return port;
+ } catch(Exception* ex) {
+ e->logger->error("CUID#%d - an error occurred while binding port=%d",
+ cuid, port);
+ delete socket;
+ socket = NULL;
+ }
+ }
+ return -1;
+}
+
+bool PeerListenCommand::execute() {
+ if(e->torrentMan->downloadComplete()) {
+ return true;
+ }
+ for(int i = 0; i < 3 && socket->isReadable(0); i++) {
+ Socket* peerSocket = NULL;
+ try {
+ peerSocket = socket->acceptConnection();
+ if(e->torrentMan->connections < MAX_PEERS) {
+ pair<string, int> peerInfo;
+ peerSocket->getPeerInfo(peerInfo);
+ Peer* peer = new Peer(peerInfo.first, peerInfo.second,
+ e->torrentMan->pieceLength,
+ e->torrentMan->totalSize);
+ if(e->torrentMan->addPeer(peer, true)) {
+ int newCuid = e->torrentMan->getNewCuid();
+ peer->cuid = newCuid;
+ PeerInteractionCommand* command =
+ new PeerInteractionCommand(newCuid, peer, e, peerSocket,
+ PeerInteractionCommand::RECEIVER_WAIT_HANDSHAKE);
+ e->commands.push(command);
+ e->logger->debug("CUID#%d - incoming connection, adding new command CUID#%d", cuid, newCuid);
+ } else {
+ delete peer;
+ }
+ }
+ delete peerSocket;
+ } catch(Exception* ex) {
+ e->logger->error("CUID#%d - error in accepting connection", cuid, ex);
+ delete ex;
+ if(peerSocket != NULL) {
+ delete peerSocket;
+ }
+ }
+ }
+ e->commands.push(this);
+ return false;
+}
diff --git a/src/PeerListenCommand.h b/src/PeerListenCommand.h
new file mode 100644
index 00000000..e2162234
--- /dev/null
+++ b/src/PeerListenCommand.h
@@ -0,0 +1,42 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_PEER_LISTEN_COMMAND_H_
+#define _D_PEER_LISTEN_COMMAND_H_
+
+#include "Command.h"
+#include "TorrentDownloadEngine.h"
+
+class PeerListenCommand : public Command {
+private:
+ TorrentDownloadEngine* e;
+ Socket* socket;
+
+public:
+ PeerListenCommand(int cuid, TorrentDownloadEngine* e);
+ ~PeerListenCommand();
+
+ bool execute();
+
+ int bindPort(int portRangeStart, int portRangeEnd);
+};
+
+#endif // _D_PEER_LISTEN_COMMAND_H_
diff --git a/src/PeerMessage.cc b/src/PeerMessage.cc
new file mode 100644
index 00000000..ddaa3066
--- /dev/null
+++ b/src/PeerMessage.cc
@@ -0,0 +1,72 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "PeerMessage.h"
+#include "Util.h"
+
+void PeerMessage::setBitfield(const unsigned char* bitfield, int bitfieldLength) {
+ if(this->bitfield != NULL) {
+ delete [] bitfield;
+ }
+ this->bitfieldLength = bitfieldLength;
+ this->bitfield = new unsigned char[this->bitfieldLength];
+ memcpy(this->bitfield, bitfield, this->bitfieldLength);
+}
+
+void PeerMessage::setBlock(const char* block, int blockLength) {
+ if(this->block != NULL) {
+ delete [] block;
+ }
+ this->blockLength = blockLength;
+ this->block = new char[this->blockLength];
+ memcpy(this->block, block, this->blockLength);
+}
+
+string PeerMessage::toString() const {
+ switch(id) {
+ case CHOKE:
+ return "choke";
+ case UNCHOKE:
+ return "unchoke";
+ case INTERESTED:
+ return "interested";
+ case NOT_INTERESTED:
+ return "not interested";
+ case HAVE:
+ return "have index="+Util::itos(index);
+ case BITFIELD:
+ return "bitfield "+Util::toHex(bitfield, bitfieldLength);
+ case REQUEST:
+ return "request index="+Util::itos(index)+", begin="+Util::itos(begin)+
+ ", length="+Util::itos(length);
+ case PIECE:
+ return "piece index="+Util::itos(index)+", begin="+Util::itos(begin)+
+ ", length="+Util::itos(blockLength);
+ case CANCEL:
+ return "calcel index="+Util::itos(index)+", begin="+Util::itos(begin)+
+ ", length="+Util::itos(length);
+ case KEEP_ALIVE:
+ return "keep alive";
+ default:
+ return "unknown";
+ }
+}
+
diff --git a/src/PeerMessage.h b/src/PeerMessage.h
new file mode 100644
index 00000000..559a48a2
--- /dev/null
+++ b/src/PeerMessage.h
@@ -0,0 +1,83 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_PEER_MESSAGE_H_
+#define _D_PEER_MESSAGE_H_
+
+#include "common.h"
+#include <string>
+
+class PeerMessage {
+private:
+ int id;
+ int index;
+ int begin;
+ int length;
+ unsigned char* bitfield;
+ int bitfieldLength;
+ char* block;
+ int blockLength;
+public:
+ PeerMessage():bitfield(NULL), bitfieldLength(0),
+ block(NULL), blockLength(0) {}
+ ~PeerMessage() {
+ if(bitfield != NULL) {
+ delete [] bitfield;
+ }
+ if(block != NULL) {
+ delete [] block;
+ }
+ }
+
+ void setBitfield(const unsigned char* bitfield, int bitfieldLength);
+ const unsigned char* getBitfield() const { return bitfield; }
+
+ void setBlock(const char* block, int blockLength);
+ const char* getBlock() const { return block; }
+
+ int getBitfieldLength() const { return bitfieldLength; }
+ int getBlockLength() const { return blockLength; }
+
+ string toString() const;
+
+ int getId() const { return id; }
+ void setId(int id) { this->id = id; }
+ int getIndex() const { return index; }
+ void setIndex(int index) { this->index = index; }
+ int getBegin() const { return begin; }
+ void setBegin(int begin) { this->begin = begin; }
+ int getLength() const { return length; }
+ void setLength(int length) { this->length = length; }
+
+ enum ID {
+ CHOKE = 0,
+ UNCHOKE = 1,
+ INTERESTED = 2,
+ NOT_INTERESTED = 3,
+ HAVE = 4,
+ BITFIELD = 5,
+ REQUEST = 6,
+ PIECE = 7,
+ CANCEL = 8,
+ KEEP_ALIVE = 99};
+};
+
+#endif // _D_PEER_MESSAGE_H_
diff --git a/src/PeerMessageUtil.cc b/src/PeerMessageUtil.cc
new file mode 100644
index 00000000..4f0f67e0
--- /dev/null
+++ b/src/PeerMessageUtil.cc
@@ -0,0 +1,231 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "PeerMessageUtil.h"
+#include "DlAbortEx.h"
+#include "Util.h"
+#include <netinet/in.h>
+
+PeerMessage* PeerMessageUtil::createPeerMessage(const char* msg, int len) {
+ PeerMessage* peerMessage;
+ if(len == 0) {
+ // keep-alive
+ peerMessage = new PeerMessage();
+ peerMessage->setId(PeerMessage::KEEP_ALIVE);
+ return peerMessage;
+ }
+ int id = getId(msg);
+ switch(id) {
+ case PeerMessage::CHOKE:
+ case PeerMessage::UNCHOKE:
+ case PeerMessage::INTERESTED:
+ case PeerMessage::NOT_INTERESTED:
+ peerMessage = createBasicMessage(id, msg, len);
+ break;
+ case PeerMessage::HAVE:
+ peerMessage = createHaveMessage(id, msg, len);
+ break;
+ case PeerMessage::BITFIELD:
+ peerMessage = createBitfieldMessage(id, msg, len);
+ break;
+ case PeerMessage::REQUEST:
+ case PeerMessage::CANCEL:
+ peerMessage = createRequestCancelMessage(id, msg, len);
+ break;
+ case PeerMessage::PIECE:
+ peerMessage = createPieceMessage(id, msg, len);
+ break;
+ default:
+ throw new DlAbortEx("invalid message id. id = %d", id);
+ }
+ return peerMessage;
+}
+
+PeerMessage* PeerMessageUtil::createBasicMessage(int id, const char* msg, int len) {
+ if(len != 1) {
+ throw new DlAbortEx("invalid payload size for ID%d, size = %d. It should be %d", id, len, 1);
+ }
+ PeerMessage* peerMessage = new PeerMessage();
+ peerMessage->setId(id);
+ return peerMessage;
+}
+
+PeerMessage* PeerMessageUtil::createHaveMessage(int id, const char* msg, int len) {
+ if(len != 5) {
+ throw new DlAbortEx("invalid payload size for ID%d, size = %d. It should be %d", id, len, 5);
+ }
+ PeerMessage* peerMessage = new PeerMessage();
+ peerMessage->setId(id);
+ peerMessage->setIndex(getIntParam(msg, 1));
+ return peerMessage;
+}
+
+PeerMessage* PeerMessageUtil::createBitfieldMessage(int id, const char* msg, int len) {
+ if(len <= 1) {
+ throw new DlAbortEx("invalid payload size for ID%d, size = %d. It should be greater than %d", id, len, 1);
+ }
+ PeerMessage* peerMessage = new PeerMessage();
+ peerMessage->setId(id);
+ peerMessage->setBitfield((unsigned char*)msg+1, len-1);
+ return peerMessage;
+}
+
+PeerMessage* PeerMessageUtil::createRequestCancelMessage(int id, const char* msg, int len) {
+ if(len != 13) {
+ throw new DlAbortEx("invalid payload size for ID%d, size = %d. It should be %d", id, len, 13);
+ }
+ PeerMessage* peerMessage = new PeerMessage();
+ peerMessage->setId(id);
+ peerMessage->setIndex(getIntParam(msg, 1));
+ peerMessage->setBegin(getIntParam(msg, 5));
+ peerMessage->setLength(getIntParam(msg, 9));
+ return peerMessage;
+}
+
+PeerMessage* PeerMessageUtil::createPieceMessage(int id, const char* msg, int len) {
+ if(len <= 9) {
+ throw new DlAbortEx("invalid payload size for ID%d, size = %d. It should be greater than %d", id, len, 9);
+ }
+ PeerMessage* peerMessage = new PeerMessage();
+ peerMessage->setId(id);
+ peerMessage->setIndex(getIntParam(msg, 1));
+ peerMessage->setBegin(getIntParam(msg, 5));
+ peerMessage->setBlock(msg+9, len-9);
+ return peerMessage;
+}
+
+int PeerMessageUtil::getId(const char* msg) {
+ return (int)msg[0];
+}
+
+int PeerMessageUtil::getIntParam(const char* msg, int offset) {
+ int nParam;
+ memcpy(&nParam, msg+offset, 4);
+ return ntohl(nParam);
+}
+
+void PeerMessageUtil::checkIndex(const PeerMessage* message, int pieces) {
+ if(!(0 <= message->getIndex() && message->getIndex() < pieces)) {
+ throw new DlAbortEx("invalid index = %d", message->getIndex());
+ }
+}
+
+void PeerMessageUtil::checkBegin(const PeerMessage* message, int pieceLength) {
+ if(!(0 <= message->getBegin() && message->getBegin() < pieceLength)) {
+ throw new DlAbortEx("invalid begin = %d", message->getBegin());
+ }
+}
+
+void PeerMessageUtil::checkPieceOffset(const PeerMessage* message, int pieceLength, int pieces, long long int totalSize) {
+ if(!(0 <= message->getBegin() && 0 < message->getLength())) {
+ throw new DlAbortEx("invalid offset, begin = %d, length = %d", message->getBegin(), message->getLength());
+ }
+ int offset = message->getBegin()+message->getLength();
+ int currentPieceLength;
+ if(message->getIndex()+1 == pieces) {
+ currentPieceLength = pieceLength-(pieces*pieceLength-totalSize);
+ } else {
+ currentPieceLength = pieceLength;
+ }
+ if(!(0 < offset && offset <= currentPieceLength)) {
+ throw new DlAbortEx("invalid offset, begin = %d, length = %d", message->getBegin(), message->getLength());
+ }
+}
+
+void PeerMessageUtil::checkLength(const PeerMessage* message) {
+ if(message->getLength() > 128*1024) {
+ throw new DlAbortEx("too large length %d > 128KB", message->getLength());
+ }
+}
+
+void PeerMessageUtil::checkBitfield(const PeerMessage* message, int pieces) {
+ if(!(message->getBitfieldLength() == BITFIELD_LEN_FROM_PIECES(pieces))) {
+ throw new DlAbortEx("invalid bitfield length = %d", message->getBitfieldLength());
+ }
+ char lastbyte = message->getBitfield()[message->getBitfieldLength()-1];
+ for(int i = 0; i < 8-pieces%8 && pieces%8 != 0; i++) {
+ if(!(((lastbyte >> i) & 1) == 0)) {
+ throw new DlAbortEx("invalid bitfield");
+ }
+ }
+}
+
+void PeerMessageUtil::checkIntegrity(const PeerMessage* message, int pieceLength, int pieces, long long int totalSize) {
+ // 0 <= index < pieces
+ // 0 <= begin < pieceLength
+ // 0 < begin+length <= pieceLength
+ // len of bitfield == pieces/8+(pieces%8 ? 1 : 0)
+ // for(int i = 0; i < 8-pieces%8; i++) { ((lastbyteofbitfield >> i) & 1) == 0 }
+ switch(message->getId()) {
+ case PeerMessage::KEEP_ALIVE:
+ case PeerMessage::CHOKE:
+ case PeerMessage::UNCHOKE:
+ case PeerMessage::INTERESTED:
+ case PeerMessage::NOT_INTERESTED:
+ break;
+ case PeerMessage::HAVE:
+ checkIndex(message, pieces);
+ break;
+ case PeerMessage::BITFIELD:
+ checkBitfield(message, pieces);
+ break;
+ case PeerMessage::REQUEST:
+ case PeerMessage::CANCEL:
+ checkIndex(message, pieces);
+ checkBegin(message, pieceLength);
+ checkLength(message);
+ checkPieceOffset(message, pieceLength, pieces, totalSize);
+ break;
+ case PeerMessage::PIECE:
+ checkIndex(message, pieces);
+ checkBegin(message, pieceLength);
+ break;
+ default:
+ throw new DlAbortEx("invalid message id. id = %d", message->getId());
+ }
+}
+
+HandshakeMessage* PeerMessageUtil::createHandshakeMessage(const char* msg) {
+ HandshakeMessage* message = new HandshakeMessage();
+ message->pstrlen = msg[0];
+ char pstr[20];
+ memcpy(pstr, &msg[1], sizeof(pstr)-1);
+ pstr[sizeof(pstr)-1] = '\0';
+ message->pstr = pstr;
+ memcpy(message->infoHash, &msg[28], 20);
+ memcpy(message->peerId, &msg[48], 20);
+ return message;
+}
+
+void PeerMessageUtil::checkHandshake(const HandshakeMessage* message, const unsigned char* infoHash) {
+ if(message->pstrlen != 19) {
+ throw new DlAbortEx("invalid handshake pstrlen = %d", (int)message->pstrlen);
+ }
+ if(message->pstr != PSTR) {
+ throw new DlAbortEx("invalid handshake pstr");
+ }
+ string myInfoHash = Util::toHex(infoHash, 20);
+ string peerInfoHash = Util::toHex(message->infoHash, 20);
+ if(myInfoHash != peerInfoHash) {
+ throw new DlAbortEx("invalid handshake info hash: expected:%s, actual:%s",
+ myInfoHash.c_str(), peerInfoHash.c_str());
+ }
+}
diff --git a/src/PeerMessageUtil.h b/src/PeerMessageUtil.h
new file mode 100644
index 00000000..23e07358
--- /dev/null
+++ b/src/PeerMessageUtil.h
@@ -0,0 +1,51 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_PEER_MESSAGE_UTIL_H_
+#define _D_PEER_MESSAGE_UTIL_H_
+
+#include "PeerConnection.h"
+
+class PeerMessageUtil {
+private:
+ PeerMessageUtil() {}
+
+ static PeerMessage* createBasicMessage(int id, const char* msg, int len);
+ static PeerMessage* createHaveMessage(int id, const char* msg, int len);
+ static PeerMessage* createBitfieldMessage(int id, const char* msg, int len);
+ static PeerMessage* createRequestCancelMessage(int id, const char* msg, int len);
+ static PeerMessage* createPieceMessage(int id, const char* msg, int len);
+ static int getId(const char* msg);
+ static int getIntParam(const char* msg, int offset);
+
+ static void checkIndex(const PeerMessage* message, int pieces);
+ static void checkBegin(const PeerMessage* message, int pieceLength);
+ static void checkLength(const PeerMessage* message);
+ static void checkPieceOffset(const PeerMessage* message, int pieceLength, int pieces, long long int totalSize);
+ static void checkBitfield(const PeerMessage* message, int pieces);
+public:
+ static PeerMessage* createPeerMessage(const char* msg, int len);
+ static void checkIntegrity(const PeerMessage* message, int pieceLength, int pieces, long long int totalSize);
+ static HandshakeMessage* createHandshakeMessage(const char* msg);
+ static void checkHandshake(const HandshakeMessage* message, const unsigned char* infoHash);
+};
+
+#endif // _D_PEER_MESSAGE_UTIL_H_
diff --git a/src/PendingMessage.cc b/src/PendingMessage.cc
new file mode 100644
index 00000000..27df5a99
--- /dev/null
+++ b/src/PendingMessage.cc
@@ -0,0 +1,115 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "PendingMessage.h"
+
+bool PendingMessage::processMessage() {
+ bool retval = true;
+ switch(peerMessageId) {
+ case PeerMessage::HAVE:
+ peerConnection->sendHave(index);
+ break;
+ case PeerMessage::BITFIELD:
+ peerConnection->sendBitfield();
+ break;
+ case PeerMessage::UNCHOKE:
+ if(peerConnection->getPeer()->amChocking) {
+ peerConnection->sendUnchoke();
+ peerConnection->getPeer()->amChocking = false;
+ }
+ break;
+ case PeerMessage::CHOKE:
+ if(!peerConnection->getPeer()->amChocking) {
+ peerConnection->sendChoke();
+ peerConnection->getPeer()->amChocking = true;
+ }
+ break;
+ case PeerMessage::NOT_INTERESTED:
+ if(peerConnection->getPeer()->amInterested) {
+ peerConnection->sendNotInterested();
+ peerConnection->getPeer()->amInterested = false;
+ }
+ break;
+ case PeerMessage::INTERESTED:
+ if(!peerConnection->getPeer()->amInterested) {
+ peerConnection->sendInterested();
+ peerConnection->getPeer()->amInterested = true;
+ }
+ break;
+ case PeerMessage::PIECE:
+ if(!peerConnection->getPeer()->amChocking) {
+ if(!inProgress) {
+ peerConnection->sendPieceHeader(index, begin, length);
+ peerConnection->getPeer()->addPeerDownload(length);
+ }
+ int writtenLength = peerConnection->sendPieceData(pieceDataOffset, leftPieceDataLength);
+ if(writtenLength != leftPieceDataLength) {
+ inProgress = true;
+ leftPieceDataLength -= writtenLength;
+ pieceDataOffset += writtenLength;
+ retval = false;
+ }
+ }
+ break;
+ case PeerMessage::REQUEST:
+ peerConnection->sendRequest(index, begin, length);
+ break;
+ case PeerMessage::CANCEL:
+ peerConnection->sendCancel(index, begin, length);
+ break;
+ default:
+ break;
+ }
+ return retval;
+}
+
+PendingMessage PendingMessage::createRequestMessage(int index, int begin, int length, PeerConnection* peerConnection) {
+ PendingMessage pendingMessage(PeerMessage::REQUEST, peerConnection);
+ pendingMessage.setIndex(index);
+ pendingMessage.setBegin(begin);
+ pendingMessage.setLength(length);
+ return pendingMessage;
+}
+
+PendingMessage PendingMessage::createCancelMessage(int index, int begin, int length, PeerConnection* peerConnection) {
+ PendingMessage pendingMessage(PeerMessage::CANCEL, peerConnection);
+ pendingMessage.setIndex(index);
+ pendingMessage.setBegin(begin);
+ pendingMessage.setLength(length);
+ return pendingMessage;
+}
+
+PendingMessage PendingMessage::createPieceMessage(int index, int begin, int length, int pieceLength, PeerConnection* peerConnection) {
+ PendingMessage pendingMessage(PeerMessage::PIECE, peerConnection);
+ pendingMessage.setIndex(index);
+ pendingMessage.setBegin(begin);
+ pendingMessage.setLength(length);
+ pendingMessage.setPieceDataOffset(((long long int)index)*pieceLength+begin);
+ pendingMessage.setLeftPieceDataLength(length);
+ return pendingMessage;
+}
+
+PendingMessage PendingMessage::createHaveMessage(int index, PeerConnection* peerConnection) {
+ PendingMessage pendingMessage(PeerMessage::HAVE, peerConnection);
+ pendingMessage.setIndex(index);
+ return pendingMessage;
+}
+
diff --git a/src/PendingMessage.h b/src/PendingMessage.h
new file mode 100644
index 00000000..da877748
--- /dev/null
+++ b/src/PendingMessage.h
@@ -0,0 +1,71 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_PENDING_MESSAGE_H_
+#define _D_PENDING_MESSAGE_H_
+
+#include "common.h"
+#include "PeerConnection.h"
+#include <vector>
+
+class PendingMessage {
+private:
+ int peerMessageId;
+ int index;
+ int begin;
+ int length;
+ long long int pieceDataOffset;
+ int leftPieceDataLength;
+ bool inProgress;
+ PeerConnection* peerConnection;
+public:
+ PendingMessage(int peerMessageId, PeerConnection* peerConnection):peerMessageId(peerMessageId), inProgress(false), peerConnection(peerConnection) {}
+ ~PendingMessage() {}
+
+ void setPeerMessageId(int peerMessageId) { this->peerMessageId = peerMessageId; }
+ int getPeerMessageId() const { return peerMessageId; }
+
+ void setPieceDataOffset(long long int offset) { this->pieceDataOffset = offset; }
+ long long int getPieceDataOffset() const { return pieceDataOffset; }
+
+ void setLeftPieceDataLength(int length) { this->leftPieceDataLength = length; }
+ int getLeftPieceDataLength() const { return leftPieceDataLength; }
+
+ void setInProgress(bool inprogress) { this->inProgress = inProgress; }
+ bool isInProgress() const { return inProgress; }
+
+ void setIndex(int index) { this->index = index; }
+ int getIndex() const { return index; }
+ void setBegin(int begin) { this->begin = begin; }
+ int getBegin() const { return begin; }
+ void setLength(int length) { this->length = length; }
+ int getLength() const { return length; }
+ bool processMessage();
+
+ static PendingMessage createRequestMessage(int index, int begin, int length, PeerConnection* peerConnection);
+ static PendingMessage createCancelMessage(int index, int begin, int length, PeerConnection* peerConnection);
+ static PendingMessage createPieceMessage(int index, int begin, int length, int pieceLength, PeerConnection* peerConnection);
+ static PendingMessage createHaveMessage(int index, PeerConnection* peerConnectioin);
+};
+
+typedef vector<PendingMessage> PendingMessages;
+
+#endif // _D_PENDING_MESSAGE_H_
diff --git a/src/Piece.cc b/src/Piece.cc
new file mode 100644
index 00000000..b27cc621
--- /dev/null
+++ b/src/Piece.cc
@@ -0,0 +1,84 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "Piece.h"
+
+Piece Piece::nullPiece;
+
+Piece::Piece(const Piece& piece) {
+ index = piece.index;
+ length = piece.length;
+ if(piece.bitfield == NULL) {
+ bitfield = NULL;
+ } else {
+ bitfield = new BitfieldMan(*piece.bitfield);
+ }
+}
+
+Piece& Piece::operator=(const Piece& piece) {
+ if(this != &piece) {
+ index = piece.index;
+ length = piece.length;
+ if(bitfield != NULL) {
+ delete bitfield;
+ }
+ if(piece.bitfield == NULL) {
+ bitfield = NULL;
+ } else {
+ bitfield = new BitfieldMan(*piece.bitfield);
+ }
+ }
+ return *this;
+}
+
+void Piece::completeBlock(int blockIndex) {
+ bitfield->setBit(blockIndex);
+ bitfield->unsetUseBit(blockIndex);
+}
+
+void Piece::clearAllBlock() {
+ bitfield->clearAllBit();
+}
+
+void Piece::setAllBlock() {
+ bitfield->setAllBit();
+}
+
+bool Piece::pieceComplete() const {
+ return bitfield->isAllBitSet();
+}
+
+void Piece::cancelBlock(int blockIndex) {
+ bitfield->unsetUseBit(blockIndex);
+}
+
+int Piece::getMissingUnusedBlockIndex() const {
+ int blockIndex = bitfield->getFirstMissingUnusedIndex();
+ if(blockIndex == -1) {
+ return blockIndex;
+ }
+ bitfield->setUseBit(blockIndex);
+ return blockIndex;
+}
+
+vector<int> Piece::getAllMissingBlockIndexes() const {
+ return bitfield->getAllMissingIndexes();
+}
diff --git a/src/Piece.h b/src/Piece.h
new file mode 100644
index 00000000..f12dcf15
--- /dev/null
+++ b/src/Piece.h
@@ -0,0 +1,81 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_PIECE_H_
+#define _D_PIECE_H_
+
+#include "BitfieldMan.h"
+#include "common.h"
+
+#define BLOCK_LENGTH 16*1024
+
+class Piece {
+private:
+ int index;
+ int length;
+ BitfieldMan* bitfield;
+public:
+ Piece():index(0), length(0), bitfield(NULL) {}
+ Piece(int index, int length):index(index), length(length) {
+ bitfield = new BitfieldMan(BLOCK_LENGTH, length);
+ }
+ Piece(const Piece& piece);
+ ~Piece() {
+ delete bitfield;
+ }
+
+ Piece& operator=(const Piece& piece);
+
+ int getMissingUnusedBlockIndex() const;
+ vector<int> getAllMissingBlockIndexes() const;
+ void completeBlock(int blockIndex);
+ void cancelBlock(int blockIndex);
+ int countCompleteBlock() const {
+ return bitfield->countBlock()-bitfield->countMissingBlock();
+ }
+ bool hasBlock(int blockIndex) const {
+ return bitfield->isBitSet(blockIndex);
+ }
+
+ bool pieceComplete() const;
+ int countBlock() const { return bitfield->countBlock(); }
+ int getBlockLength(int index) const {
+ return bitfield->getBlockLength(index);
+ }
+ int getBlockLength() const { return bitfield->getBlockLength(); }
+ int getIndex() const { return index; }
+ void setIndex(int index) { this->index = index; }
+ int getLength() const { return length; }
+ void setLength(int index) { this->length = length; }
+
+ const unsigned char* getBitfield() const { return bitfield->getBitfield(); }
+ void setBitfield(const unsigned char* bitfield, int len);
+
+ void clearAllBlock();
+ void setAllBlock();
+
+ static Piece nullPiece;
+ static bool isNull(const Piece& piece) {
+ return piece.index == 0 && piece.length == 0;
+ }
+};
+
+#endif // _D_PIECE_H_
diff --git a/src/PreAllocationDiskWriter.cc b/src/PreAllocationDiskWriter.cc
index abf87777..9fef82f8 100644
--- a/src/PreAllocationDiskWriter.cc
+++ b/src/PreAllocationDiskWriter.cc
@@ -20,15 +20,16 @@
*/
/* copyright --> */
#include "PreAllocationDiskWriter.h"
+#include "DlAbortEx.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
-#include "DlAbortEx.h"
-PreAllocationDiskWriter::PreAllocationDiskWriter(unsigned long int size):AbstractDiskWriter(),size(size) {}
+PreAllocationDiskWriter::PreAllocationDiskWriter(long long int totalLength)
+ :AbstractDiskWriter(),totalLength(totalLength) {}
PreAllocationDiskWriter::~PreAllocationDiskWriter() {}
@@ -36,34 +37,32 @@ void PreAllocationDiskWriter::initAndOpenFile(string filename) {
createFile(filename, O_DIRECT);
int pageSize = getpagesize();
+ int bufSize = pageSize*4;
char* buf;
- int size = pageSize*4;
- int rt = posix_memalign((void**)&buf, pageSize, size);
+ int rt = posix_memalign((void**)&buf, pageSize, bufSize);
if(rt != 0) {
throw new DlAbortEx(strerror(rt));
}
- memset(buf, 0, size);
- int x = size/4096;
- int r = size%4096;
- for(int i = 0; i < x; i++) {
- if(write(fd, buf, size) < 0) {
- free(buf);
- throw new DlAbortEx(strerror(errno));
+ try {
+ memset(buf, 0, bufSize);
+ long long int x = totalLength/bufSize;
+ int r = totalLength%bufSize;
+ for(long long int i = 0; i < x; i++) {
+ if(write(fd, buf, bufSize) < 0) {
+ throw new DlAbortEx(strerror(errno));
+ }
}
- }
- free(buf);
- closeFile();
- openExistingFile(filename);
- char cbuf[4096];
- memset(cbuf, 0, sizeof(cbuf));
- if(write(fd, cbuf, r) < 0) {
- throw new DlAbortEx(strerror(errno));
+ closeFile();
+ openExistingFile(filename);
+ if(r > 0) {
+ seek(totalLength-r);
+ if(write(fd, buf, r) < 0) {
+ throw new DlAbortEx(strerror(errno));
+ }
+ }
+ free(buf);
+ } catch(Exception* ex) {
+ free(buf);
+ throw;
}
}
-
-void PreAllocationDiskWriter::writeData(const char* data, int len, unsigned long int offset) {
- int x = lseek(fd, offset, SEEK_SET);
- // TODO check the return value of write
- writeDataInternal(data, len);
-}
-
diff --git a/src/PreAllocationDiskWriter.h b/src/PreAllocationDiskWriter.h
index eca8b996..c56cf717 100644
--- a/src/PreAllocationDiskWriter.h
+++ b/src/PreAllocationDiskWriter.h
@@ -26,14 +26,12 @@
class PreAllocationDiskWriter:public AbstractDiskWriter {
private:
- unsigned long int size;
+ long long int totalLength;
public:
- PreAllocationDiskWriter(unsigned long int size);
+ PreAllocationDiskWriter(long long int totalLength);
~PreAllocationDiskWriter();
void initAndOpenFile(string filename);
-
- void writeData(const char* data, int len, unsigned long int position);
};
#endif // _D_PRE_ALLOCATION_DISK_WRITER_H_
diff --git a/src/Request.cc b/src/Request.cc
index 9d183cd4..91bd6d12 100644
--- a/src/Request.cc
+++ b/src/Request.cc
@@ -22,7 +22,7 @@
#include "Request.h"
#include "Util.h"
-Request::Request():port(0), tryCount(0) {
+Request::Request():port(0), tryCount(0), isTorrent(false) {
defaultPorts["http"] = 80;
#ifdef HAVE_LIBSSL
// for SSL
diff --git a/src/Request.h b/src/Request.h
index 8d8676ef..9bd55948 100644
--- a/src/Request.h
+++ b/src/Request.h
@@ -56,10 +56,12 @@ private:
string file;
map<string, int> defaultPorts;
int tryCount;
+ int trackerEvent;
bool parseUrl(string url);
public:
Segment seg;
CookieBox* cookieBox;
+ bool isTorrent;
public:
Request();
virtual ~Request();
@@ -87,6 +89,17 @@ public:
int getPort() const { return port; }
string getDir() const { return dir; }
string getFile() const { return file;}
+
+ void setTrackerEvent(int event) { trackerEvent = event; }
+ int getTrackerEvent() const { return trackerEvent; }
+
+ enum TRACKER_EVENT {
+ AUTO,
+ STARTED,
+ STOPPED,
+ COMPLETED
+ };
+
};
#endif // _D_REQUEST_H_
diff --git a/src/RequestSlot.cc b/src/RequestSlot.cc
new file mode 100644
index 00000000..3729f47d
--- /dev/null
+++ b/src/RequestSlot.cc
@@ -0,0 +1,70 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "RequestSlot.h"
+#include "Util.h"
+
+RequestSlot::RequestSlot(int index, int begin, int length, int blockIndex)
+ :index(index), begin(begin), length(length), blockIndex(blockIndex) {
+ setDispatchedTime();
+}
+
+RequestSlot::RequestSlot(const RequestSlot& requestSlot) {
+ copy(requestSlot);
+}
+
+RequestSlot& RequestSlot::operator=(const RequestSlot& requestSlot) {
+ if(this != &requestSlot) {
+ copy(requestSlot);
+ }
+ return *this;
+}
+
+void RequestSlot::copy(const RequestSlot& requestSlot) {
+ index = requestSlot.index;
+ begin = requestSlot.begin;
+ length = requestSlot.length;
+ blockIndex = requestSlot.blockIndex;
+ dispatchedTime = requestSlot.dispatchedTime;
+}
+
+RequestSlot RequestSlot::nullSlot(0, 0, 0, 0);
+
+void RequestSlot::setDispatchedTime() {
+ gettimeofday(&dispatchedTime, NULL);
+}
+
+bool RequestSlot::isTimeout(int timeoutSec) const {
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ return Util::difftv(now, dispatchedTime) > timeoutSec*1000000;
+}
+
+bool RequestSlot::isNull(const RequestSlot& requestSlot) {
+ return requestSlot.index == 0 && requestSlot.begin == 0&&
+ requestSlot.length == 0;
+}
+
+bool RequestSlot::operator==(const RequestSlot& requestSlot) const {
+ return index == requestSlot.index &&
+ begin == requestSlot.begin &&
+ length == requestSlot.length;
+}
diff --git a/src/RequestSlot.h b/src/RequestSlot.h
new file mode 100644
index 00000000..f4c36d9b
--- /dev/null
+++ b/src/RequestSlot.h
@@ -0,0 +1,63 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_REQUEST_SLOT_H_
+#define _D_REQUEST_SLOT_H_
+
+#include "common.h"
+#include <sys/time.h>
+
+class RequestSlot {
+private:
+ struct timeval dispatchedTime;
+ int index;
+ int begin;
+ int length;
+ int blockIndex;
+ void copy(const RequestSlot& requestSlot);
+public:
+ RequestSlot(int index, int begin, int legnth, int blockIndex);
+ RequestSlot(const RequestSlot& requestSlot);
+ ~RequestSlot() {}
+
+ RequestSlot& operator=(const RequestSlot& requestSlot);
+
+ void setDispatchedTime();
+
+ bool isTimeout(int timeoutSec) const;
+
+ bool operator==(const RequestSlot& requestSlot) const;
+
+ int getIndex() const { return index; }
+ void setIndex(int index) { this->index = index; }
+ int getBegin() const { return begin; }
+ void setBegin(int begin) { this->begin = begin; }
+ int getLength() const { return length; }
+ void setLength(int length) { this->length = length; }
+ int getBlockIndex() const { return blockIndex; }
+ void setBlockIndex(int blockIndex) { this->blockIndex = blockIndex; }
+
+ static RequestSlot nullSlot;
+
+ static bool isNull(const RequestSlot& requestSlot);
+};
+
+#endif // _D_REQUEST_SLOT_H_
diff --git a/src/RequestSlotMan.cc b/src/RequestSlotMan.cc
new file mode 100644
index 00000000..378371a6
--- /dev/null
+++ b/src/RequestSlotMan.cc
@@ -0,0 +1,98 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "RequestSlotMan.h"
+
+void RequestSlotMan::addRequestSlot(const RequestSlot& requestSlot) {
+ requestSlots.push_back(requestSlot);
+}
+
+void RequestSlotMan::deleteRequestSlot(const RequestSlot& requestSlot) {
+ for(RequestSlots::iterator itr = requestSlots.begin();
+ itr != requestSlots.end(); itr++) {
+ if(*itr == requestSlot) {
+ requestSlots.erase(itr);
+ break;
+ }
+ }
+}
+
+void RequestSlotMan::deleteAllRequestSlot(Piece& piece) {
+ if(!Piece::isNull(piece)) {
+ for(RequestSlots::const_iterator itr = requestSlots.begin();
+ itr != requestSlots.end(); itr++) {
+ if(itr->getIndex() == piece.getIndex()) {
+ piece.cancelBlock(itr->getBlockIndex());
+ }
+ }
+ torrentMan->updatePiece(piece);
+ }
+ requestSlots.clear();
+}
+
+void RequestSlotMan::deleteTimedoutRequestSlot(Piece& piece) {
+ for(RequestSlots::iterator itr = requestSlots.begin();
+ itr != requestSlots.end();) {
+ if(itr->isTimeout(timeout)) {
+ logger->debug("CUID#%d - deleting requestslot blockIndex %d because of time out", cuid,
+ itr->getBlockIndex());
+ if(!Piece::isNull(piece)) {
+ piece.cancelBlock(itr->getBlockIndex());
+ }
+ itr = requestSlots.erase(itr);
+ } else {
+ itr++;
+ }
+ }
+ torrentMan->updatePiece(piece);
+}
+
+void RequestSlotMan::deleteCompletedRequestSlot(const Piece& piece) {
+ for(RequestSlots::iterator itr = requestSlots.begin();
+ itr != requestSlots.end();) {
+ if(Piece::isNull(piece) || piece.hasBlock(itr->getBlockIndex())) {
+ logger->debug("CUID#%d - deleting requestslot blockIndex %d because the block is already acquired.", cuid,
+ itr->getBlockIndex());
+ PendingMessage pendingMessage =
+ PendingMessage::createCancelMessage(itr->getIndex(),
+ itr->getBegin(),
+ itr->getLength(),
+ peerConnection);
+ pendingMessages->push_back(pendingMessage);
+ itr = requestSlots.erase(itr);
+ } else {
+ itr++;
+ }
+ }
+}
+
+RequestSlot RequestSlotMan::getCorrespoindingRequestSlot(const PeerMessage* pieceMessage) const {
+ for(RequestSlots::const_iterator itr = requestSlots.begin();
+ itr != requestSlots.end(); itr++) {
+ const RequestSlot& slot = *itr;
+ if(slot.getIndex() == pieceMessage->getIndex() &&
+ slot.getBegin() == pieceMessage->getBegin() &&
+ slot.getLength() == pieceMessage->getBlockLength()) {
+ return slot;
+ }
+ }
+ return RequestSlot::nullSlot;
+}
diff --git a/src/RequestSlotMan.h b/src/RequestSlotMan.h
new file mode 100644
index 00000000..f0c1f008
--- /dev/null
+++ b/src/RequestSlotMan.h
@@ -0,0 +1,72 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_REQUEST_SLOT_MAN_H_
+#define _D_REQUEST_SLOT_MAN_H_
+
+#include "RequestSlot.h"
+#include "common.h"
+#include "PeerMessage.h"
+#include "Logger.h"
+#include "PeerConnection.h"
+#include "PendingMessage.h"
+#include "TorrentMan.h"
+#include <vector>
+
+#define DEFAULT_TIME_OUT 120
+
+typedef vector<RequestSlot> RequestSlots;
+
+class RequestSlotMan {
+private:
+ int cuid;
+ RequestSlots requestSlots;
+ int timeout;
+ PendingMessages* pendingMessages;
+ PeerConnection* peerConnection;
+ TorrentMan* torrentMan;
+ const Logger* logger;
+public:
+ RequestSlotMan(int cuid,
+ PendingMessages* pendingMessages,
+ PeerConnection* peerConnection,
+ TorrentMan* torrentMan,
+ const Logger* logger):cuid(cuid), timeout(DEFAULT_TIME_OUT),
+ pendingMessages(pendingMessages), peerConnection(peerConnection),
+ torrentMan(torrentMan), logger(logger) {}
+ ~RequestSlotMan() {}
+
+ void addRequestSlot(const RequestSlot& requestSlot);
+ void deleteRequestSlot(const RequestSlot& requestSlot);
+ void deleteAllRequestSlot(Piece& piece);
+
+ void deleteTimedoutRequestSlot(Piece& piece);
+ void deleteCompletedRequestSlot(const Piece& piece);
+
+ RequestSlot getCorrespoindingRequestSlot(const PeerMessage* pieceMessage) const;
+ bool isEmpty() { return requestSlots.empty(); }
+ int countRequestSlot() const { return requestSlots.size(); }
+
+ void setTimeout(int timeout) { this->timeout = timeout; }
+ int getTimeout() const { return timeout; }
+};
+
+#endif // _D_REQUEST_SLOT_MAN_H_
diff --git a/src/ShaVisitor.cc b/src/ShaVisitor.cc
new file mode 100644
index 00000000..0c6eef81
--- /dev/null
+++ b/src/ShaVisitor.cc
@@ -0,0 +1,82 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "ShaVisitor.h"
+#include "Util.h"
+
+ShaVisitor::ShaVisitor() {
+ EVP_MD_CTX_init(&ctx);
+ EVP_DigestInit_ex(&ctx, EVP_sha1(), NULL);
+}
+
+ShaVisitor::~ShaVisitor() {
+ EVP_MD_CTX_cleanup(&ctx);
+}
+
+void ShaVisitor::visit(const Data* d) {
+ if(d->isNumber()) {
+ EVP_DigestUpdate(&ctx, "i", 1);
+ } else {
+ string lenStr = Util::llitos(d->getLen());
+ EVP_DigestUpdate(&ctx, lenStr.c_str(), lenStr.size());
+ EVP_DigestUpdate(&ctx, ":", 1);
+ }
+ EVP_DigestUpdate(&ctx, d->getData(), d->getLen());
+ if(d->isNumber()) {
+ EVP_DigestUpdate(&ctx, "e", 1);
+ }
+}
+
+void ShaVisitor::visit(const Dictionary* d) {
+ EVP_DigestUpdate(&ctx, "d", 1);
+ const vector<string>& v = d->getOrder();
+ for(vector<string>::const_iterator itr = v.begin(); itr != v.end(); itr++) {
+ string lenStr = Util::llitos(itr->size());
+ EVP_DigestUpdate(&ctx, lenStr.c_str(), lenStr.size());
+ EVP_DigestUpdate(&ctx, ":", 1);
+ EVP_DigestUpdate(&ctx, itr->c_str(), itr->size());
+ const MetaEntry* e = d->get(*itr);
+ this->visit(e);
+ }
+ EVP_DigestUpdate(&ctx, "e", 1);
+}
+
+void ShaVisitor::visit(const List* l) {
+ EVP_DigestUpdate(&ctx, "l", 1);
+ for(MetaList::const_iterator itr = l->getList().begin(); itr != l->getList().end(); itr++) {
+ this->visit(*itr);
+ }
+ EVP_DigestUpdate(&ctx, "e", 1);
+}
+
+void ShaVisitor::visit(const MetaEntry* e) {
+ if(dynamic_cast<const Data*>(e) != NULL) {
+ visit((const Data*)e);
+ } else if(dynamic_cast<const Dictionary*>(e) != NULL) {
+ visit((const Dictionary*)e);
+ } else if(dynamic_cast<const List*>(e) != NULL) {
+ visit((const List*)e);
+ }
+}
+
+void ShaVisitor::getHash(unsigned char* hashValue, int& len) {
+ EVP_DigestFinal_ex(&ctx, hashValue, (unsigned int*)&len);
+}
diff --git a/src/ShaVisitor.h b/src/ShaVisitor.h
new file mode 100644
index 00000000..59b5e19a
--- /dev/null
+++ b/src/ShaVisitor.h
@@ -0,0 +1,47 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_SHA_VISITOR_H_
+#define _D_SHA_VISITOR_H_
+
+#include "MetaEntryVisitor.h"
+#include "Data.h"
+#include "Dictionary.h"
+#include "List.h"
+#include "common.h"
+#include <openssl/evp.h>
+
+class ShaVisitor : public MetaEntryVisitor {
+private:
+ EVP_MD_CTX ctx;
+public:
+ ShaVisitor();
+ ~ShaVisitor();
+
+ void visit(const Data* d);
+ void visit(const Dictionary* d);
+ void visit(const List* l);
+ void visit(const MetaEntry* e);
+
+ void getHash(unsigned char* md, int& s);
+};
+
+#endif // _D_SHA_VISITOR_H_
diff --git a/src/Socket.cc b/src/Socket.cc
index f4e0862d..973aafe6 100644
--- a/src/Socket.cc
+++ b/src/Socket.cc
@@ -53,14 +53,18 @@ Socket& Socket::operator=(const Socket& s) {
return *this;
}
-void Socket::beginListen() const {
- core->beginListen();
+void Socket::beginListen(int port) const {
+ core->beginListen(port);
}
void Socket::getAddrInfo(pair<string, int>& addrinfo) const {
core->getAddrInfo(addrinfo);
}
+void Socket::getPeerInfo(pair<string, int>& peerinfo) const {
+ core->getPeerInfo(peerinfo);
+}
+
Socket* Socket::acceptConnection() const {
return new Socket(core->acceptConnection());
}
diff --git a/src/Socket.h b/src/Socket.h
index d49ef953..d07a5eb9 100644
--- a/src/Socket.h
+++ b/src/Socket.h
@@ -51,7 +51,7 @@ public:
/**
* @see SocketCore::beginListen()
*/
- void beginListen() const;
+ void beginListen(int port = 0) const;
/**
* @see SocketCore::getAddrInfo()
@@ -59,6 +59,11 @@ public:
void getAddrInfo(pair<string, int>& addrinfo) const;
/**
+ * @see SocketCore::getPeerInfo();
+ */
+ void getPeerInfo(pair<string, int>& peerinfo) const;
+
+ /**
* @see SocketCore::acceptConnection()
*/
Socket* acceptConnection() const;
diff --git a/src/SocketCore.cc b/src/SocketCore.cc
index f4d02dce..83c2c95f 100644
--- a/src/SocketCore.cc
+++ b/src/SocketCore.cc
@@ -56,7 +56,7 @@ SocketCore::~SocketCore() {
closeConnection();
}
-void SocketCore::beginListen() {
+void SocketCore::beginListen(int port) {
closeConnection();
//sockfd = socket(AF_UNSPEC, SOCK_STREAM, PF_UNSPEC);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
@@ -74,7 +74,7 @@ void SocketCore::beginListen() {
memset((char*)&sockaddr, 0, sizeof(sockaddr));
sockaddr.sin_family = AF_INET;
sockaddr.sin_addr.s_addr = INADDR_ANY;
- sockaddr.sin_port = htons(0);
+ sockaddr.sin_port = htons(port);
if(bind(sockfd, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == -1) {
throw new DlAbortEx(strerror(errno));
@@ -93,6 +93,7 @@ SocketCore* SocketCore::acceptConnection() const {
if((fd = accept(sockfd, (struct sockaddr*)&sockaddr, &len)) == -1) {
throw new DlAbortEx(strerror(errno));
}
+
SocketCore* s = new SocketCore(fd);
return s;
}
@@ -108,6 +109,17 @@ void SocketCore::getAddrInfo(pair<string, int>& addrinfo) const {
addrinfo.second = ntohs(listenaddr.sin_port);
}
+void SocketCore::getPeerInfo(pair<string, int>& peerinfo) const {
+ struct sockaddr_in peerin;
+ memset(&peerin, 0, sizeof(peerin));
+ int len = sizeof(peerin);
+ if(getpeername(sockfd, (struct sockaddr*)&peerin, (socklen_t*)&len) < 0) {
+ throw new DlAbortEx(strerror(errno));
+ }
+ peerinfo.first = inet_ntoa(peerin.sin_addr);
+ peerinfo.second = ntohs(peerin.sin_port);
+}
+
void SocketCore::establishConnection(string host, int port) {
closeConnection();
sockfd = socket(AF_INET, SOCK_STREAM, 0);
@@ -134,7 +146,6 @@ void SocketCore::establishConnection(string host, int port) {
ai.ai_family = PF_INET;
ai.ai_socktype = SOCK_STREAM;
ai.ai_protocol = 0;
- ai.ai_addr = (struct sockaddr*)&sockaddr;
struct addrinfo* res;
int ec;
if((ec = getaddrinfo(host.c_str(), NULL, &ai, &res)) != 0) {
@@ -227,8 +238,7 @@ bool SocketCore::isReadable(int timeout) const {
}
void SocketCore::writeData(const char* data, int len, int timeout) const {
- if(!isWritable(timeout) ||
- !secure && send(sockfd, data, (size_t)len, 0) != len
+ if(!secure && send(sockfd, data, (size_t)len, 0) != len
#ifdef HAVE_LIBSSL
// for SSL
// TODO handling len == 0 case required
@@ -240,8 +250,7 @@ void SocketCore::writeData(const char* data, int len, int timeout) const {
}
void SocketCore::readData(char* data, int& len, int timeout) const {
- if(!isReadable(timeout) ||
- !secure && (len = recv(sockfd, data, (size_t)len, 0)) < 0
+ if(!secure && (len = recv(sockfd, data, (size_t)len, 0)) < 0
#ifdef HAVE_LIBSSL
// for SSL
// TODO handling len == 0 case required
@@ -253,8 +262,7 @@ void SocketCore::readData(char* data, int& len, int timeout) const {
}
void SocketCore::peekData(char* data, int& len, int timeout) const {
- if(!isReadable(timeout) ||
- !secure && (len = recv(sockfd, data, (size_t)len, MSG_PEEK)) < 0
+ if(!secure && (len = recv(sockfd, data, (size_t)len, MSG_PEEK)) < 0
#ifdef HAVE_LIBSSL
// for SSL
// TODO handling len == 0 case required
diff --git a/src/SocketCore.h b/src/SocketCore.h
index 3c09da60..01ec3e85 100644
--- a/src/SocketCore.h
+++ b/src/SocketCore.h
@@ -54,14 +54,22 @@ public:
/**
* Creates a socket and listens form connection on it.
+ * @param port port to listen. If 0 is specified, os automaticaly
+ * choose avaiable port.
*/
- void beginListen();
+ void beginListen(int port = 0);
/**
* Stores host address and port of this socket to addrinfo.
* @param addrinfo placeholder to store host address and port.
*/
void getAddrInfo(pair<string, int>& addrinfo) const;
+
+ /**
+ * Stores peer's address and port to peerinfo.
+ * @param peerinfo placeholder to store peer's address and port.
+ */
+ void getPeerInfo(pair<string, int>& peerinfo) const;
/**
* Accepts incoming connection on this socket.
@@ -118,7 +126,7 @@ public:
* @param timeout the amount of time elapsed before isWritable()
* are timed out.
*/
- void writeData(const char* data, int len, int timeout = 5) const;
+ void writeData(const char* data, int len, int timeout = 0) const;
/**
* Reads up to len bytes from this socket.
@@ -134,7 +142,7 @@ public:
* @param timeout the amount of time elapsed before isReadable() are timed
* out.
*/
- void readData(char* data, int& len, int timeout = 5) const;
+ void readData(char* data, int& len, int timeout = 0) const;
/**
* Reads up to len bytes from this socket, but bytes are not removed from
@@ -147,7 +155,7 @@ public:
* @param timeout the amount of time elapsed before isReadable() are timed
* out.
*/
- void peekData(char* data, int& len, int timeout = 5) const;
+ void peekData(char* data, int& len, int timeout = 0) const;
/**
* Makes this socket secure.
diff --git a/src/TorrentAutoSaveCommand.cc b/src/TorrentAutoSaveCommand.cc
new file mode 100644
index 00000000..994ee4af
--- /dev/null
+++ b/src/TorrentAutoSaveCommand.cc
@@ -0,0 +1,37 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "TorrentAutoSaveCommand.h"
+#include "SleepCommand.h"
+
+TorrentAutoSaveCommand::TorrentAutoSaveCommand(int cuid, TorrentDownloadEngine* e, int interval):Command(cuid), e(e), interval(interval) {}
+
+TorrentAutoSaveCommand::~TorrentAutoSaveCommand() {}
+
+bool TorrentAutoSaveCommand::execute() {
+ if(e->torrentMan->downloadComplete()) {
+ return true;
+ }
+ e->torrentMan->save();
+ SleepCommand* sleepCommand = new SleepCommand(cuid, e, this, interval);
+ e->commands.push(sleepCommand);
+ return false;
+}
diff --git a/src/TorrentAutoSaveCommand.h b/src/TorrentAutoSaveCommand.h
new file mode 100644
index 00000000..562fdf0d
--- /dev/null
+++ b/src/TorrentAutoSaveCommand.h
@@ -0,0 +1,40 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_TORRENT_AUTO_SAVE_COMMAND_H_
+#define _D_TORRENT_AUTO_SAVE_COMMAND_H_
+
+#include "Command.h"
+#include "TorrentDownloadEngine.h"
+
+class TorrentAutoSaveCommand : public Command {
+private:
+ int cuid;
+ TorrentDownloadEngine* e;
+ int interval;
+public:
+ TorrentAutoSaveCommand(int cuid, TorrentDownloadEngine* e, int interval);
+ ~TorrentAutoSaveCommand();
+
+ bool execute();
+};
+
+#endif // _D_TORRENT_AUTO_SAVE_COMMAND_H_
diff --git a/src/TorrentConsoleDownloadEngine.cc b/src/TorrentConsoleDownloadEngine.cc
new file mode 100644
index 00000000..8a793e91
--- /dev/null
+++ b/src/TorrentConsoleDownloadEngine.cc
@@ -0,0 +1,132 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "TorrentConsoleDownloadEngine.h"
+#include "Util.h"
+
+TorrentConsoleDownloadEngine::TorrentConsoleDownloadEngine() {}
+
+TorrentConsoleDownloadEngine::~TorrentConsoleDownloadEngine() {}
+
+void TorrentConsoleDownloadEngine::printStatistics() {
+ printf("\r ");
+ printf("\r");
+ printf("%s/%sB %d%% DW:%.2f UP:%.2f(%s) %dpeers",
+ Util::llitos(torrentMan->getDownloadedSize(), true).c_str(),
+ Util::llitos(torrentMan->totalSize, true).c_str(),
+ (torrentMan->totalSize == 0 ?
+ 0 : (int)((torrentMan->getDownloadedSize()*100)/torrentMan->totalSize)),
+ downloadSpeed/1000.0,
+ uploadSpeed/1000.0,
+ Util::llitos(torrentMan->getUploadedSize(), true).c_str(),
+ torrentMan->connections);
+ fflush(stdout);
+}
+
+void TorrentConsoleDownloadEngine::initStatistics() {
+ /*
+ gettimeofday(&cp, NULL);
+ */
+ downloadSpeed = 0;
+ uploadSpeed = 0;
+ /*
+ sessionDownloadSize = 0;
+ sessionUploadSize = 0;
+ */
+ lastElapsed = 0;
+ gettimeofday(&cp[0], NULL);
+ gettimeofday(&cp[1], NULL);
+ sessionDownloadSize[0] = 0;
+ sessionDownloadSize[1] = 0;
+ sessionUploadSize[0] = 0;
+ sessionUploadSize[1] = 0;
+ currentCp = 0;
+}
+
+/*
+int TorrentConsoleDownloadEngine::calculateSpeed(int deltaSize, long long int elapsed, int prevSpeed) {
+ int nowSpeed = (int)(deltaSize/(elapsed/1000000.0));
+ return (nowSpeed+prevSpeed)/2;
+}
+*/
+int TorrentConsoleDownloadEngine::calculateSpeed(long long int sessionSize, long long int elapsed) {
+ int nowSpeed = (int)(sessionSize/(elapsed/1000000.0));
+ return nowSpeed;
+}
+
+void TorrentConsoleDownloadEngine::calculateStatistics() {
+ /*
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ long long int elapsed = Util::difftv(now, cp);
+ sessionDownloadSize += torrentMan->getDeltaDownload();
+ sessionUploadSize += torrentMan->getDeltaUpload();
+
+ downloadSpeed = calculateSpeed(sessionDownloadSize, elapsed);
+ uploadSpeed = calculateSpeed(sessionUploadSize, elapsed);
+ torrentMan->resetDeltaDownload();
+ torrentMan->resetDeltaUpload();
+ if(elapsed-lastElapsed >= 1000000) {
+ printStatistics();
+ lastElapsed = elapsed;
+ }
+ */
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ long long int elapsed = Util::difftv(now, cp[currentCp]);
+
+ sessionDownloadSize[0] += torrentMan->getDeltaDownload();
+ sessionUploadSize[0] += torrentMan->getDeltaUpload();
+ sessionDownloadSize[1] += torrentMan->getDeltaDownload();
+ sessionUploadSize[1] += torrentMan->getDeltaUpload();
+
+ downloadSpeed = calculateSpeed(sessionDownloadSize[currentCp], elapsed);
+ uploadSpeed = calculateSpeed(sessionUploadSize[currentCp], elapsed);
+
+ torrentMan->resetDeltaDownload();
+ torrentMan->resetDeltaUpload();
+
+ if(elapsed-lastElapsed >= 1000000) {
+ printStatistics();
+ lastElapsed = elapsed;
+ }
+
+ if(elapsed > 15*1000000) {
+ sessionDownloadSize[currentCp] = 0;
+ sessionUploadSize[currentCp] = 0;
+ cp[currentCp] = now;
+ lastElapsed = 0;
+ currentCp = currentCp ? 0 : 1;
+ }
+
+ /*
+ if(elapsed >= 1000000) {
+ downloadSpeed = calculateSpeed(torrentMan->getDeltaDownload(),
+ elapsed, downloadSpeed);
+ uploadSpeed = calculateSpeed(torrentMan->getDeltaUpload(),
+ elapsed, uploadSpeed);
+ torrentMan->resetDeltaDownload();
+ torrentMan->resetDeltaUpload();
+ cp = now;
+ printStatistics();
+ }
+ */
+}
diff --git a/src/TorrentConsoleDownloadEngine.h b/src/TorrentConsoleDownloadEngine.h
new file mode 100644
index 00000000..da3a67b0
--- /dev/null
+++ b/src/TorrentConsoleDownloadEngine.h
@@ -0,0 +1,52 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_TORRENT_CONSOLE_DOWNLOAD_ENGINE_H_
+#define _D_TORRENT_CONSOLE_DOWNLOAD_ENGINE_H_
+
+#include "TorrentDownloadEngine.h"
+
+class TorrentConsoleDownloadEngine : public TorrentDownloadEngine {
+private:
+ /*
+ struct timeval cp;
+ long long int sessionDownloadSize;
+ long long int sessionUploadSize;
+ */
+ struct timeval cp[2];
+ long long int sessionDownloadSize[2];
+ long long int sessionUploadSize[2];
+ int currentCp;
+
+ int downloadSpeed;
+ int uploadSpeed;
+ long long int lastElapsed;
+ void printStatistics();
+ int calculateSpeed(long long int sessionSize, long long int elapsed);
+protected:
+ void initStatistics();
+ void calculateStatistics();
+public:
+ TorrentConsoleDownloadEngine();
+ ~TorrentConsoleDownloadEngine();
+};
+
+#endif // _D_TORRENT_CONSOLE_DOWNLOAD_ENGINE_H_
diff --git a/src/TorrentDownloadEngine.cc b/src/TorrentDownloadEngine.cc
new file mode 100644
index 00000000..17f2f301
--- /dev/null
+++ b/src/TorrentDownloadEngine.cc
@@ -0,0 +1,32 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "TorrentDownloadEngine.h"
+
+void TorrentDownloadEngine::onEndOfRun() {
+ torrentMan->diskWriter->closeFile();
+ if(torrentMan->downloadComplete()) {
+ torrentMan->remove();
+ torrentMan->fixFilename();
+ } else {
+ torrentMan->save();
+ }
+}
diff --git a/src/TorrentDownloadEngine.h b/src/TorrentDownloadEngine.h
new file mode 100644
index 00000000..fca3daa5
--- /dev/null
+++ b/src/TorrentDownloadEngine.h
@@ -0,0 +1,38 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_TORRENT_DOWNLOAD_ENGINE_H_
+#define _D_TORRENT_DOWNLOAD_ENGINE_H_
+
+#include "DownloadEngine.h"
+#include "TorrentMan.h"
+
+class TorrentDownloadEngine : public DownloadEngine {
+protected:
+ void onEndOfRun();
+public:
+ TorrentDownloadEngine() {}
+ virtual ~TorrentDownloadEngine() {}
+
+ TorrentMan* torrentMan;
+};
+
+#endif // _D_TORRENT_DOWNLOAD_ENGINE_H_
diff --git a/src/TorrentMan.cc b/src/TorrentMan.cc
new file mode 100644
index 00000000..2bd95b5f
--- /dev/null
+++ b/src/TorrentMan.cc
@@ -0,0 +1,505 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "TorrentMan.h"
+#include "Dictionary.h"
+#include "List.h"
+#include "ShaVisitor.h"
+#include "Util.h"
+#include "MetaFileUtil.h"
+#include "DlAbortEx.h"
+#include "File.h"
+#include "message.h"
+#include "PreAllocationDiskWriter.h"
+#include <errno.h>
+#include <libgen.h>
+#include <string.h>
+
+TorrentMan::TorrentMan():bitfield(NULL),
+ peerEntryIdCounter(0), cuidCounter(0),
+ downloadedSize(0), uploadedSize(0),
+ deltaDownload(0), deltaUpload(0),
+ multiFileTopDir(NULL),
+ interval(DEFAULT_ANNOUNCE_INTERVAL),
+ minInterval(DEFAULT_ANNOUNCE_MIN_INTERVAL),
+ complete(0), incomplete(0),
+ connections(0) {}
+
+TorrentMan::~TorrentMan() {
+ if(bitfield != NULL) {
+ delete bitfield;
+ }
+ if(multiFileTopDir != NULL) {
+ delete multiFileTopDir;
+ }
+ for(Peers::iterator itr = peers.begin(); itr != peers.end(); itr++) {
+ delete *itr;
+ }
+}
+
+// TODO do not use this method in application code
+void TorrentMan::updatePeers(const Peers& peers) {
+ this->peers = peers;
+}
+
+bool TorrentMan::addPeer(Peer* peer, bool duplicate) {
+ if(duplicate) {
+ for(Peers::iterator itr = peers.begin(); itr != peers.end(); itr++) {
+ Peer* p = *itr;
+ if(p->ipaddr == peer->ipaddr && p->port == peer->port && p->error > 0) {
+ return false;
+ }
+ }
+ } else {
+ for(Peers::iterator itr = peers.begin(); itr != peers.end(); itr++) {
+ Peer* p = *itr;
+ if(p->ipaddr == peer->ipaddr && p->port == peer->port) {
+ return false;
+ }
+ }
+ }
+ ++peerEntryIdCounter;
+ peer->entryId = peerEntryIdCounter;
+ peers.push_back(peer);
+ return true;
+}
+
+/*
+void TorrentMan::updatePeer(const Peer& peer) {
+ for(Peers::iterator itr = peers.begin(); itr != peers.end(); itr++) {
+ Peer& p = *itr;
+ if(p.eid == peer.eid) {
+ p = peer;
+ break;
+ }
+ }
+}
+*/
+
+bool TorrentMan::isPeerAvailable() const {
+ return getPeer() != Peer::nullPeer;
+}
+
+int TorrentMan::deleteOldErrorPeers(int maxNum) {
+ int counter = 0;
+ for(Peers::iterator itr = peers.begin(); itr != peers.end();) {
+ Peer* p = *itr;
+ if(p->error != 0 && p->cuid == 0) {
+ delete p;
+ itr = peers.erase(itr);
+ counter++;
+ if(maxNum <= counter) {
+ break;
+ }
+ } else {
+ itr++;
+ }
+ }
+ return counter;
+}
+
+Peer* TorrentMan::getPeer() const {
+ for(Peers::const_iterator itr = peers.begin(); itr != peers.end(); itr++) {
+ Peer* p = *itr;
+ if(p->cuid == 0 && p->error == 0) {
+ return p;
+ }
+ }
+ return Peer::nullPeer;
+}
+
+bool TorrentMan::isEndGame() const {
+ return bitfield->countMissingBlock() <= END_GAME_PIECE_NUM;
+}
+
+Piece TorrentMan::getMissingPiece(const unsigned char* peerBitfield, int length) {
+ int index = -1;
+ if(isEndGame()) {
+ index = bitfield->getMissingIndex(peerBitfield, length);
+ } else {
+ index = bitfield->getMissingUnusedIndex(peerBitfield, length);
+ }
+ if(index == -1) {
+ return Piece::nullPiece;
+ }
+ bitfield->setUseBit(index);
+
+ Piece piece = findUsedPiece(index);
+ if(Piece::isNull(piece)) {
+ Piece piece(index, bitfield->getBlockLength(index));
+ addUsedPiece(piece);
+ return piece;
+ } else {
+ return piece;
+ }
+}
+
+int TorrentMan::deleteUsedPiecesByFillRate(int fillRate, int toDelete) {
+ int deleted = 0;
+ for(UsedPieces::iterator itr = usedPieces.begin();
+ itr != usedPieces.end() && deleted < toDelete;) {
+ Piece& piece = *itr;
+ if(!bitfield->isUseBitSet(piece.getIndex()) &&
+ piece.countCompleteBlock() <= piece.countBlock()*(fillRate/100.0)) {
+ logger->debug("deleting used piece index=%d, fillRate(%%)=%d<=%d",
+ piece.getIndex(),
+ (piece.countCompleteBlock()*100)/piece.countBlock(),
+ fillRate);
+ itr = usedPieces.erase(itr);
+ deleted++;
+ } else {
+ itr++;
+ }
+ }
+ return deleted;
+}
+
+void TorrentMan::reduceUsedPieces(int max) {
+ int toDelete = usedPieces.size()-max;
+ if(toDelete <= 0) {
+ return;
+ }
+ int fillRate = 10;
+ while(fillRate < 50) {
+ int deleted = deleteUsedPiecesByFillRate(fillRate, toDelete);
+ if(deleted == 0) {
+ break;
+ }
+ toDelete -= deleted;
+ fillRate += 10;
+ }
+}
+
+void TorrentMan::addUsedPiece(const Piece& piece) {
+ usedPieces.push_back(piece);
+}
+
+Piece TorrentMan::findUsedPiece(int index) const {
+ for(UsedPieces::const_iterator itr = usedPieces.begin(); itr != usedPieces.end(); itr++) {
+ const Piece& piece = *itr;
+ if(piece.getIndex() == index) {
+ return piece;
+ }
+ }
+ return Piece::nullPiece;
+}
+
+void TorrentMan::deleteUsedPiece(const Piece& piece) {
+ if(Piece::isNull(piece)) {
+ return;
+ }
+ for(UsedPieces::iterator itr = usedPieces.begin(); itr != usedPieces.end(); itr++) {
+ if(itr->getIndex() == piece.getIndex()) {
+ usedPieces.erase(itr);
+ break;
+ }
+ }
+}
+
+void TorrentMan::completePiece(const Piece& piece) {
+ if(Piece::isNull(piece)) {
+ return;
+ }
+ bitfield->setBit(piece.getIndex());
+ bitfield->unsetUseBit(piece.getIndex());
+ addDownloadedSize(piece.getLength());
+ deleteUsedPiece(piece);
+ if(!isEndGame()) {
+ reduceUsedPieces(100);
+ }
+}
+
+void TorrentMan::cancelPiece(const Piece& piece) {
+ if(Piece::isNull(piece)) {
+ return;
+ }
+ bitfield->unsetUseBit(piece.getIndex());
+ if(!isEndGame()) {
+ if(piece.countCompleteBlock() == 0) {
+ deleteUsedPiece(piece);
+ }
+ }
+}
+
+void TorrentMan::updatePiece(const Piece& piece) {
+ if(Piece::isNull(piece)) {
+ return;
+ }
+ for(UsedPieces::iterator itr = usedPieces.begin(); itr != usedPieces.end(); itr++) {
+ if(itr->getIndex() == piece.getIndex()) {
+ *itr = piece;
+ break;
+ }
+ }
+}
+
+void TorrentMan::syncPiece(Piece& piece) {
+ if(Piece::isNull(piece)) {
+ return;
+ }
+ for(UsedPieces::iterator itr = usedPieces.begin(); itr != usedPieces.end(); itr++) {
+ if(itr->getIndex() == piece.getIndex()) {
+ piece = *itr;
+ return;
+ }
+ }
+ // hasPiece(piece.getIndex()) is true, then set all bit of
+ // piece.bitfield to 1
+ if(hasPiece(piece.getIndex())) {
+ piece.setAllBlock();
+ }
+}
+
+void TorrentMan::initBitfield() {
+ if(bitfield != NULL) {
+ delete bitfield;
+ }
+ bitfield = new BitfieldMan(pieceLength, totalSize);
+}
+
+void TorrentMan::setBitfield(unsigned char* bitfield, int bitfieldLength) {
+ if(this->bitfield == NULL) {
+ initBitfield();
+ }
+ this->bitfield->setBitfield(bitfield, bitfieldLength);
+}
+
+bool TorrentMan::downloadComplete() const {
+ return bitfield->isAllBitSet();
+}
+
+void TorrentMan::setup(string metaInfoFile) {
+ peerId = "-A2****-";
+ for(int i = 0; i < 12; i++) {
+ peerId += Util::itos((int)(((double)10)*random()/(RAND_MAX+1.0)));
+ }
+
+ uploadedSize = 0;
+ downloadedSize = 0;
+ Dictionary* topDic = (Dictionary*)MetaFileUtil::parseMetaFile(metaInfoFile);
+ const Dictionary* infoDic = (const Dictionary*)topDic->get("info");
+ ShaVisitor v;
+ infoDic->accept(&v);
+ unsigned char md[20];
+ int len;
+ v.getHash(md, len);
+ setInfoHash(md);
+
+ Data* topName = (Data*)infoDic->get("name");
+ if(topName != NULL) {
+ name = topName->toString();
+ } else {
+ char* basec = strdup(metaInfoFile.c_str());
+ name = string(basename(basec));
+ free(basec);
+ }
+
+ List* files = (List*)infoDic->get("files");
+ if(files == NULL) {
+ // single-file mode;
+ setFileMode(SINGLE);
+ Data* length = (Data*)infoDic->get("length");
+ totalSize = length->toLLInt();
+ } else {
+ long long int length = 0;
+ // multi-file mode
+ setFileMode(MULTI);
+ multiFileTopDir = new Directory(name);
+ const MetaList& metaList = files->getList();
+ for(MetaList::const_iterator itr = metaList.begin(); itr != metaList.end();
+ itr++) {
+ Dictionary* fileDic = (Dictionary*)(*itr);
+ Data* lengthData = (Data*)fileDic->get("length");
+ //length += strtoll(data->toString().c_str(), NULL, 10);
+ length += lengthData->toLLInt();
+ List* path = (List*)fileDic->get("path");
+ const MetaList& paths = path->getList();
+ Directory* parentDir = multiFileTopDir;
+ string filePath = name;
+ for(int i = 0; i < (int)paths.size()-1; i++) {
+ Data* subpath = (Data*)paths.at(i);
+ Directory* dir = new Directory(subpath->toString());
+ parentDir->addFile(dir);
+ parentDir = dir;
+ filePath.append("/").append(subpath->toString());
+ }
+ Data* lastpath = (Data*)paths.back();
+ filePath.append("/").append(lastpath->toString());
+ FileEntry fileEntry(filePath, lengthData->toLLInt());
+ multiFileEntries.push_back(fileEntry);
+ }
+ totalSize = length;
+ }
+ announce = ((Data*)topDic->get("announce"))->toString();
+ pieceLength = ((Data*)infoDic->get("piece length"))->toInt();
+ pieces = totalSize/pieceLength+(totalSize%pieceLength ? 1 : 0);
+
+ Data* piecesHashData = (Data*)infoDic->get("pieces");
+ if(piecesHashData->getLen() != pieces*20) {
+ throw new DlAbortEx("the number of pieces is wrong.");
+ }
+ for(int index = 0; index < pieces; index++) {
+ string hex = Util::toHex((unsigned char*)&piecesHashData->getData()[index*20], 20);
+ pieceHashes.push_back(hex);
+ logger->debug("piece #%d, hash:%s", index, hex.c_str());
+ }
+
+ initBitfield();
+ delete topDic;
+
+ diskWriter = new PreAllocationDiskWriter(totalSize);
+ if(segmentFileExists()) {
+ load();
+ diskWriter->openExistingFile(getTempFilePath());
+ } else {
+ diskWriter->initAndOpenFile(getTempFilePath());
+ }
+}
+
+bool TorrentMan::hasPiece(int index) const {
+ return bitfield->isBitSet(index);
+}
+
+string TorrentMan::getPieceHash(int index) const {
+ return pieceHashes.at(index);
+}
+
+string TorrentMan::getFilePath() const {
+ return (storeDir == "" ? "." : storeDir)+"/"+name;
+}
+
+string TorrentMan::getTempFilePath() const {
+ return getFilePath()+".a2tmp";
+}
+
+string TorrentMan::getSegmentFilePath() const {
+ return getFilePath()+".aria2";
+}
+
+bool TorrentMan::segmentFileExists() const {
+ string segFilename = getSegmentFilePath();
+ File f(segFilename);
+ if(f.isFile()) {
+ logger->info(MSG_SEGMENT_FILE_EXISTS, segFilename.c_str());
+ return true;
+ } else {
+ logger->info(MSG_SEGMENT_FILE_DOES_NOT_EXIST, segFilename.c_str());
+ return false;
+ }
+}
+
+FILE* TorrentMan::openSegFile(string segFilename, string mode) const {
+ FILE* segFile = fopen(segFilename.c_str(), mode.c_str());
+ if(segFile == NULL) {
+ throw new DlAbortEx(strerror(errno));
+ }
+ return segFile;
+}
+
+void TorrentMan::load() {
+ string segFilename = getSegmentFilePath();
+ logger->info(MSG_LOADING_SEGMENT_FILE, segFilename.c_str());
+ FILE* segFile = openSegFile(segFilename, "r+");
+ read(segFile);
+ fclose(segFile);
+ logger->info(MSG_LOADED_SEGMENT_FILE);
+}
+
+void TorrentMan::read(FILE* file) {
+ assert(file != NULL);
+ unsigned char savedInfoHash[INFO_HASH_LENGTH];
+ if(fread(savedInfoHash, INFO_HASH_LENGTH, 1, file) < 1) {
+ throw new DlAbortEx(strerror(errno));
+ }
+ if(Util::toHex(savedInfoHash, INFO_HASH_LENGTH) != Util::toHex(infoHash, INFO_HASH_LENGTH)) {
+ throw new DlAbortEx("info hash mismatch");
+ }
+ unsigned char* savedBitfield = new unsigned char[bitfield->getBitfieldLength()];
+ try {
+ if(fread(savedBitfield, bitfield->getBitfieldLength(), 1, file) < 1) {
+ throw new DlAbortEx(strerror(errno));
+ }
+ setBitfield(savedBitfield, bitfield->getBitfieldLength());
+ if(fread(&downloadedSize, sizeof(downloadedSize), 1, file) < 1) {
+ throw new DlAbortEx(strerror(errno));
+ }
+ if(fread(&uploadedSize, sizeof(uploadedSize), 1, file) < 1) {
+ throw new DlAbortEx(strerror(errno));
+ }
+ delete savedBitfield;
+ } catch(Exception* ex) {
+ delete savedBitfield;
+ throw;
+ }
+}
+
+void TorrentMan::save() const {
+ if(downloadedSize == 0) {
+ return;
+ }
+ string segFilename = getSegmentFilePath();
+ logger->info(MSG_SAVING_SEGMENT_FILE, segFilename.c_str());
+ FILE* file = openSegFile(segFilename, "w");
+ if(fwrite(infoHash, INFO_HASH_LENGTH, 1, file) < 1) {
+ throw new DlAbortEx(strerror(errno));
+ }
+ if(fwrite(bitfield->getBitfield(), bitfield->getBitfieldLength(), 1, file) < 1) {
+ throw new DlAbortEx(strerror(errno));
+ }
+ if(fwrite(&downloadedSize, sizeof(downloadedSize), 1, file) < 1) {
+ throw new DlAbortEx(strerror(errno));
+ }
+ if(fwrite(&uploadedSize, sizeof(uploadedSize), 1, file) < 1) {
+ throw new DlAbortEx(strerror(errno));
+ }
+ fclose(file);
+ logger->info(MSG_SAVED_SEGMENT_FILE);
+}
+
+void TorrentMan::remove() const {
+ if(segmentFileExists()) {
+ File f(getSegmentFilePath());
+ f.remove();
+ }
+}
+
+void TorrentMan::fixFilename() const {
+ if(fileMode == SINGLE) {
+ renameSingleFile();
+ } else {
+ splitMultiFile();
+ }
+}
+
+void TorrentMan::renameSingleFile() const {
+ rename(getTempFilePath().c_str(), getFilePath().c_str());
+}
+
+void TorrentMan::splitMultiFile() const {
+ multiFileTopDir->createDir((storeDir == "" ? "." : storeDir), true);
+ long long int offset = 0;
+ for(MultiFileEntries::const_iterator itr = multiFileEntries.begin();
+ itr != multiFileEntries.end(); itr++) {
+ Util::rangedFileCopy(itr->path, getTempFilePath(), offset, itr->length);
+ offset += itr->length;
+ }
+ unlink(getTempFilePath().c_str());
+}
diff --git a/src/TorrentMan.h b/src/TorrentMan.h
new file mode 100644
index 00000000..3041f3f8
--- /dev/null
+++ b/src/TorrentMan.h
@@ -0,0 +1,217 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_TORRENT_MAN_H_
+#define _D_TORRENT_MAN_H_
+
+#include "Peer.h"
+#include "common.h"
+#include "Logger.h"
+#include "BitfieldMan.h"
+#include "DiskWriter.h"
+#include "Piece.h"
+#include "Directory.h"
+#include <vector>
+#include <map>
+#include <string>
+
+using namespace std;
+
+#define DEFAULT_BLOCK_LEN 16*1024;
+#define MAX_BLOCK_LEN 128*1024;
+
+#define INFO_HASH_LENGTH 20
+
+#define IS_NULL_PIECE(X) (X.index == 0 && X.length == 0)
+
+#define DEFAULT_ANNOUNCE_INTERVAL 1800
+#define DEFAULT_ANNOUNCE_MIN_INTERVAL 120
+#define MAX_PEERS 55
+#define END_GAME_PIECE_NUM 20
+
+class FileEntry {
+public:
+ string path;
+ long long int length;
+ FileEntry(string path, long long int length):path(path), length(length) {}
+ ~FileEntry() {}
+};
+
+typedef vector<Peer*> Peers;
+typedef multimap<int, int> Haves;
+typedef vector<FileEntry> MultiFileEntries;
+typedef vector<Piece> UsedPieces;
+
+class TorrentMan {
+private:
+ Peers peers;
+ BitfieldMan* bitfield;
+ unsigned char infoHash[INFO_HASH_LENGTH];
+ vector<string> pieceHashes;
+ int peerEntryIdCounter;
+ int cuidCounter;
+ long long int downloadedSize;
+ long long int uploadedSize;
+ int deltaDownload;
+ int deltaUpload;
+ int fileMode;
+ string storeDir;
+ int port;
+ Haves haves;
+ UsedPieces usedPieces;
+ Directory* multiFileTopDir;
+ MultiFileEntries multiFileEntries;
+
+ FILE* openSegFile(string segFilename, string mode) const;
+ void read(FILE* file);
+
+ Piece findUsedPiece(int index) const;
+ void addUsedPiece(const Piece& piece);
+ void deleteUsedPiece(const Piece& piece);
+ int deleteUsedPiecesByFillRate(int fillRate, int toDelete);
+ void reduceUsedPieces(int max);
+public:
+ int pieceLength;
+ int pieces;
+ long long int totalSize;
+ string peerId;
+ string announce;
+ string trackerId;
+ string name;
+ int interval;
+ int minInterval;
+ int complete;
+ int incomplete;
+ int connections;
+public:
+ TorrentMan();
+ ~TorrentMan();
+
+ const Logger* logger;
+ DiskWriter* diskWriter;
+
+ int getNewCuid() { return ++cuidCounter; }
+
+ // TODO do not use this method
+ void updatePeers(const Peers& peers);
+ bool addPeer(Peer* peer, bool duplicate = false);
+ //void updatePeer(const Peer* peer);
+ const Peers& getPeers() const { return peers; }
+ Peer* getPeer() const;
+ bool isPeerAvailable() const;
+ int deleteOldErrorPeers(int maxNum);
+
+ Piece getMissingPiece(const unsigned char* peerBitfield, int len);
+ void completePiece(const Piece& piece);
+ void cancelPiece(const Piece& piece);
+ void updatePiece(const Piece& piece);
+ void syncPiece(Piece& piece);
+ bool hasPiece(int index) const;
+ void initBitfield();
+ bool isEndGame() const;
+ bool downloadComplete() const;
+ void setBitfield(unsigned char* bitfield, int len);
+ const unsigned char* getBitfield() const {
+ return bitfield->getBitfield();
+ }
+ int getBitfieldLength() const { return bitfield->getBitfieldLength(); }
+ void setInfoHash(const unsigned char* infoHash) {
+ memcpy(this->infoHash, infoHash, INFO_HASH_LENGTH);
+ }
+ const unsigned char* getInfoHash() const {
+ return infoHash;
+ }
+
+ void setup(string metaInfoFile);
+
+ string getPieceHash(int index) const;
+
+ void advertisePiece(int cuid, int index) {
+ Haves::value_type vt(cuid, index);
+ haves.insert(vt);
+ }
+
+ vector<int> getAdvertisedPieceIndexes(int myCuid) const {
+ vector<int> indexes;
+ for(Haves::const_iterator itr = haves.begin(); itr != haves.end(); itr++) {
+ const Haves::value_type& have = *itr;
+ if(have.first == myCuid) {
+ continue;
+ }
+ indexes.push_back(have.second);
+ }
+ return indexes;
+ }
+
+ void unadvertisePiece(int cuid) {
+ haves.erase(cuid);
+ }
+
+ void addDeltaDownload(int size) { deltaDownload += size; }
+ int getDeltaDownload() const { return deltaDownload; }
+ void resetDeltaDownload() { deltaDownload = 0; }
+
+ void addDeltaUpload(int size) { deltaUpload += size; }
+ int getDeltaUpload() const { return deltaUpload; }
+ void resetDeltaUpload() { deltaUpload = 0; }
+
+ void addDownloadedSize(int size) { downloadedSize += size; }
+ long long int getDownloadedSize() const { return downloadedSize; }
+ void setDownloadedSize(long long int size) { downloadedSize = size; }
+
+ void addUploadedSize(int size) { uploadedSize += size; }
+ long long int getUploadedSize() const { return uploadedSize; }
+ void setUploadedSize(long long int size) { uploadedSize = size; }
+
+ void setFileMode(int mode) {
+ fileMode = mode;
+ }
+
+ int getFileMode() const {
+ return fileMode;
+ }
+
+ string getStoreDir() const { return storeDir; }
+ void setStoreDir(string dir) { storeDir = dir; }
+
+ string getFilePath() const;
+ string getTempFilePath() const;
+ string getSegmentFilePath() const;
+
+ bool segmentFileExists() const;
+ void load();
+ void save() const;
+ void remove() const;
+
+ void renameSingleFile() const;
+ void splitMultiFile() const;
+ void fixFilename() const;
+
+ void setPort(int port) { this->port = port; }
+ int getPort() const { return port; }
+
+ enum FILE_MODE {
+ SINGLE,
+ MULTI
+ };
+};
+
+#endif // _D_TORRENT_MAN_H_
diff --git a/src/TrackerDownloadCommand.cc b/src/TrackerDownloadCommand.cc
new file mode 100644
index 00000000..85780f7e
--- /dev/null
+++ b/src/TrackerDownloadCommand.cc
@@ -0,0 +1,99 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "TrackerDownloadCommand.h"
+#include "TrackerUpdateCommand.h"
+#include "ChunkedEncoding.h"
+#include "DlRetryEx.h"
+#include "message.h"
+#include "MetaFileUtil.h"
+#include "DlAbortEx.h"
+
+TrackerDownloadCommand::TrackerDownloadCommand(int cuid, Request* req,
+ TorrentDownloadEngine* e,
+ Socket* s)
+ :AbstractCommand(cuid, req, e, s), len(0) {
+ resSize = 256;
+ res = new char[resSize];
+ ChunkedEncoding* ce = new ChunkedEncoding();
+ transferEncodings["chunked"] = ce;
+}
+
+TrackerDownloadCommand::~TrackerDownloadCommand() {
+ delete [] res;
+ for(map<string, TransferEncoding*>::iterator itr = transferEncodings.begin(); itr != transferEncodings.end(); itr++) {
+ delete((*itr).second);
+ }
+}
+
+bool TrackerDownloadCommand::executeInternal(Segment seg) {
+ TransferEncoding* te = NULL;
+ if(transferEncoding.size()) {
+ te = getTransferEncoding(transferEncoding);
+ assert(te != NULL);
+ }
+ int bufSize = 4096;
+ char buf[bufSize];
+ socket->readData(buf, bufSize);
+ if(te != NULL) {
+ int infbufSize = 4096;
+ char infbuf[infbufSize];
+ te->inflate(infbuf, infbufSize, buf, bufSize);
+ if(len+infbufSize >= resSize) {
+ expandBuffer(len+infbufSize);
+ }
+ memcpy(res+len, infbuf, infbufSize);
+ len += infbufSize;
+ } else {
+ if(len+bufSize >= resSize) {
+ expandBuffer(len+bufSize);
+ }
+ memcpy(res+len, buf, bufSize);
+ len += bufSize;
+ }
+ if(e->segmentMan->totalSize != 0 && bufSize == 0) {
+ throw new DlRetryEx(EX_GOT_EOF);
+ }
+ if(te != NULL && te->finished()
+ || te == NULL && len == e->segmentMan->totalSize
+ || bufSize == 0) {
+ if(te != NULL) te->end();
+ e->logger->info(MSG_DOWNLOAD_COMPLETED, cuid);
+ MetaEntry* entry = MetaFileUtil::bdecoding(res, len);
+ e->commands.push(new TrackerUpdateCommand(cuid, req, (TorrentDownloadEngine*)e, entry));
+ return true;
+ } else {
+ e->commands.push(this);
+ return false;
+ }
+}
+
+TransferEncoding* TrackerDownloadCommand::getTransferEncoding(string name) {
+ return transferEncodings[name];
+}
+
+void TrackerDownloadCommand::expandBuffer(int newSize) {
+ char* newbuf = new char[newSize];
+ memcpy(newbuf, res, len);
+ delete [] res;
+ res = newbuf;
+ resSize = newSize;
+}
diff --git a/src/TrackerDownloadCommand.h b/src/TrackerDownloadCommand.h
new file mode 100644
index 00000000..7fed8bf5
--- /dev/null
+++ b/src/TrackerDownloadCommand.h
@@ -0,0 +1,50 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_TRACKER_DOWNLOAD_COMMAND_H_
+#define _D_TRACKER_DOWNLOAD_COMMAND_H_
+
+#include "AbstractCommand.h"
+#include "TorrentDownloadEngine.h"
+#include "TransferEncoding.h"
+#include "Segment.h"
+#include <map>
+
+class TrackerDownloadCommand : public AbstractCommand {
+private:
+ char* res;
+ int resSize;
+ int len;
+ map<string, TransferEncoding*> transferEncodings;
+ void expandBuffer(int newSize);
+protected:
+ bool executeInternal(Segment segment);
+public:
+ TrackerDownloadCommand(int cuid, Request* req, TorrentDownloadEngine* e, Socket* s);
+ ~TrackerDownloadCommand();
+
+ TransferEncoding* getTransferEncoding(string transferEncoding);
+
+ string transferEncoding;
+};
+
+#endif // _D_TRACKER_DOWNLOAD_COMMAND_H_
+
diff --git a/src/TrackerInitCommand.cc b/src/TrackerInitCommand.cc
new file mode 100644
index 00000000..66d01b3d
--- /dev/null
+++ b/src/TrackerInitCommand.cc
@@ -0,0 +1,67 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "TrackerInitCommand.h"
+#include "Request.h"
+#include "InitiateConnectionCommandFactory.h"
+#include "TorrentMan.h"
+#include "Util.h"
+
+TrackerInitCommand::TrackerInitCommand(int cuid, Request* req, TorrentDownloadEngine* e):Command(cuid), req(req), e(e) {}
+
+TrackerInitCommand::~TrackerInitCommand() {}
+
+bool TrackerInitCommand::execute() {
+ if(e->torrentMan->downloadComplete()) {
+ req->setTrackerEvent(Request::COMPLETED);
+ }
+ string event;
+ switch(req->getTrackerEvent()) {
+ case Request::STARTED:
+ event = "started";
+ break;
+ case Request::STOPPED:
+ event = "stopped";
+ break;
+ case Request::COMPLETED:
+ event = "completed";
+ break;
+ }
+ string url = e->torrentMan->announce+"?"+
+ "info_hash="+Util::urlencode(e->torrentMan->getInfoHash(), 20)+"&"+
+ "peer_id="+e->torrentMan->peerId+"&"+
+ "port="+Util::itos(e->torrentMan->getPort())+"&"+
+ "uploaded="+Util::llitos(e->torrentMan->getUploadedSize())+"&"+
+ "downloaded="+Util::llitos(e->torrentMan->getDownloadedSize())+"&"+
+ "left="+Util::llitos(e->torrentMan->totalSize-e->torrentMan->getDownloadedSize())+"&"+
+ "compact=1";
+ if(!event.empty()) {
+ url += string("&")+"event="+event;
+ }
+ if(!e->torrentMan->trackerId.empty()) {
+ url += string("&")+"trackerid="+e->torrentMan->trackerId;
+ }
+ req->setUrl(url);
+ Command* command = InitiateConnectionCommandFactory::createInitiateConnectionCommand(cuid, req, e);
+ e->commands.push(command);
+ return true;
+}
+
diff --git a/src/TrackerInitCommand.h b/src/TrackerInitCommand.h
new file mode 100644
index 00000000..cf08c58e
--- /dev/null
+++ b/src/TrackerInitCommand.h
@@ -0,0 +1,40 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_TRACKER_INIT_COMMAND_H_
+#define _D_TRACKER_INIT_COMMAND_H_
+
+#include "TorrentDownloadEngine.h"
+#include "Request.h"
+#include "Command.h"
+
+class TrackerInitCommand : public Command {
+private:
+ Request* req;
+ TorrentDownloadEngine* e;
+public:
+ TrackerInitCommand(int cuid, Request* req, TorrentDownloadEngine* e);
+ ~TrackerInitCommand();
+
+ bool execute();
+};
+
+#endif // _D_TRACKER_INIT_COMMAND_H_
diff --git a/src/TrackerUpdateCommand.cc b/src/TrackerUpdateCommand.cc
new file mode 100644
index 00000000..8ef3e0ae
--- /dev/null
+++ b/src/TrackerUpdateCommand.cc
@@ -0,0 +1,126 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "TrackerUpdateCommand.h"
+#include "TrackerInitCommand.h"
+#include "PeerInitiateConnectionCommand.h"
+#include "PeerListenCommand.h"
+#include "SleepCommand.h"
+#include "Dictionary.h"
+#include "Data.h"
+#include "DlAbortEx.h"
+#include "message.h"
+#include <netinet/in.h>
+
+TrackerUpdateCommand::TrackerUpdateCommand(int cuid, Request* req,
+ TorrentDownloadEngine* e,
+ MetaEntry* trackerResponse)
+ :Command(cuid), req(req), e(e), trackerResponse(trackerResponse) {}
+
+TrackerUpdateCommand::~TrackerUpdateCommand() {
+ delete trackerResponse;
+}
+
+bool TrackerUpdateCommand::execute() {
+ if(req->getTrackerEvent() == Request::COMPLETED) {
+ return true;
+ }
+ e->torrentMan->deleteOldErrorPeers(25);
+
+ Dictionary* response = (Dictionary*)trackerResponse;
+ Data* failureReason = (Data*)response->get("failure reason");
+ if(failureReason != NULL) {
+ throw new DlAbortEx("Tracker returned failure reason: %s", failureReason->toString().c_str());
+ }
+ Data* warningMessage = (Data*)response->get("warning message");
+ if(warningMessage != NULL) {
+ e->logger->info(MSG_TRACKER_WARNING_MESSAGE, cuid, warningMessage->toString().c_str());
+ }
+ Data* trackerId = (Data*)response->get("tracker id");
+ if(trackerId != NULL) {
+ e->torrentMan->trackerId = trackerId->toString();
+ e->logger->debug("CUID#%d - Tracker ID:%s", cuid, e->torrentMan->trackerId.c_str());
+ }
+ Data* interval = (Data*)response->get("interval");
+ if(interval != NULL) {
+ e->torrentMan->interval = interval->toInt();
+ e->logger->debug("CUID#%d - interval:%d", cuid, e->torrentMan->interval);
+ }
+ Data* minInterval = (Data*)response->get("min interval");
+ if(minInterval != NULL) {
+ e->torrentMan->minInterval = minInterval->toInt();
+ e->logger->debug("CUID#%d - min interval:%d", cuid, e->torrentMan->minInterval);
+ }
+ Data* complete = (Data*)response->get("complete");
+ if(complete != NULL) {
+ e->torrentMan->complete = complete->toInt();
+ e->logger->debug("CUID#%d - complete:%d", cuid, e->torrentMan->complete);
+ }
+ Data* incomplete = (Data*)response->get("incomplete");
+ if(incomplete != NULL) {
+ e->torrentMan->incomplete = incomplete->toInt();
+ e->logger->debug("CUID#%d - incomplete:%d", cuid, e->torrentMan->incomplete);
+ }
+ Data* peers = (Data*)response->get("peers");
+ for(int i = 0; i < peers->getLen(); i += 6) {
+ unsigned int ipaddr1 = (unsigned char)*(peers->getData()+i);
+ unsigned int ipaddr2 = (unsigned char)*(peers->getData()+i+1);
+ unsigned int ipaddr3 = (unsigned char)*(peers->getData()+i+2);
+ unsigned int ipaddr4 = (unsigned char)*(peers->getData()+i+3);
+ //unsigned short int nPort = 0;
+ //memcpy(&nPort, peers->getData()+i+4, 2);
+ unsigned int port = ntohs(*(unsigned short int*)(peers->getData()+i+4));
+ //unsigned int port = ntohs(nPort);
+ char ipaddr[16];
+
+ snprintf(ipaddr, sizeof(ipaddr), "%d.%d.%d.%d",
+ ipaddr1, ipaddr2, ipaddr3, ipaddr4);
+ Peer* peer = new Peer(ipaddr, port, e->torrentMan->pieceLength,
+ e->torrentMan->totalSize);
+ if(e->torrentMan->addPeer(peer)) {
+ e->logger->debug("CUID#%d - adding peer %s:%d", cuid,
+ peer->ipaddr.c_str(), peer->port);
+ } else {
+ delete peer;
+ }
+ }
+ /*
+ if(req->getTrackerEvent() == Request::STARTED) {
+ PeerListenCommand* command = new PeerListenCommand(e->torrentMan->getNewCuid(), e);
+ e->commands.push(command);
+ e->logger->debug("CUID#%d - adding listen command", cuid);
+ }
+ */
+ while(e->torrentMan->isPeerAvailable() &&
+ e->torrentMan->connections < MAX_PEERS) {
+ Peer* peer = e->torrentMan->getPeer();
+ int newCuid = e->torrentMan->getNewCuid();
+ peer->cuid = newCuid;
+ PeerInitiateConnectionCommand* command = new PeerInitiateConnectionCommand(newCuid, peer, e);
+ e->commands.push(command);
+ e->logger->debug("CUID#%d - adding new command CUID#%d", cuid, newCuid);
+ }
+ req->setTrackerEvent(Request::AUTO);
+ TrackerInitCommand* command = new TrackerInitCommand(cuid, req, e);
+ SleepCommand* slpCommand = new SleepCommand(cuid, e, command, e->torrentMan->minInterval);
+ e->commands.push(slpCommand);
+ return true;
+}
diff --git a/src/TrackerUpdateCommand.h b/src/TrackerUpdateCommand.h
new file mode 100644
index 00000000..7d68a222
--- /dev/null
+++ b/src/TrackerUpdateCommand.h
@@ -0,0 +1,42 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_TRACKER_UPDATE_COMMAND_H_
+#define _D_TRACKER_UPDATE_COMMAND_H_
+
+#include "Command.h"
+#include "Request.h"
+#include "TorrentDownloadEngine.h"
+#include "MetaEntry.h"
+
+class TrackerUpdateCommand : public Command {
+private:
+ Request* req;
+ TorrentDownloadEngine* e;
+ MetaEntry* trackerResponse;
+public:
+ TrackerUpdateCommand(int cuid, Request* req, TorrentDownloadEngine* e, MetaEntry* trackerResponse);
+ ~TrackerUpdateCommand();
+
+ bool execute();
+};
+
+#endif // _D_TRACKER_UPDATE_COMMAND_H_
diff --git a/src/Util.cc b/src/Util.cc
index 5db1bcec..91c89532 100644
--- a/src/Util.cc
+++ b/src/Util.cc
@@ -20,6 +20,11 @@
*/
/* copyright --> */
#include "Util.h"
+#include "DlAbortEx.h"
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
string Util::itos(int value, bool comma) {
string str = llitos(value, comma);
@@ -146,3 +151,70 @@ string Util::replace(string target, string oldstr, string newstr) {
return result;
}
+string Util::urlencode(const unsigned char* target, int len) {
+ string dest;
+ for(int i = 0; i < len; i++) {
+ if(!('0' <= target[i] && target[i] <= '9' ||
+ 'A' <= target[i] && target[i] <= 'Z' ||
+ 'a' <= target[i] && target[i] <= 'z' ||
+ '$' == target[i] || '-' == target[i] ||
+ '_' == target[i] || '.' == target[i] ||
+ '+' == target[i] || '!' == target[i] ||
+ '*' == target[i] || '\'' == target[i] ||
+ '(' == target[i] || ')' == target[i] ||
+ ',' == target[i])) {
+ char temp[4];
+ sprintf(temp, "%%%02x", target[i]);
+ temp[sizeof(temp)-1] = '\0';
+ dest.append(temp);
+ } else {
+ dest += target[i];
+ }
+ }
+ return dest;
+}
+
+string Util::toHex(const unsigned char* src, int len) {
+ char* temp = new char[len*2+1];
+ for(int i = 0; i < len; i++) {
+ sprintf(temp+i*2, "%02x", src[i]);
+ }
+ temp[len*2] = '\0';
+ string hex = temp;
+ delete [] temp;
+ return hex;
+}
+
+FILE* Util::openFile(string filename, string mode) {
+ FILE* file = fopen(filename.c_str(), mode.c_str());
+ return file;
+}
+
+void Util::rangedFileCopy(string dest, string src, long long int srcOffset, long long int length) {
+ int destFd;
+ if((destFd = open(dest.c_str(), O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR|S_IWUSR)) < 0) {
+ throw new DlAbortEx(strerror(errno));
+ }
+ int srcFd;
+ if((srcFd = open(src.c_str(), O_RDONLY, S_IRUSR|S_IWUSR)) < 0) {
+ throw new DlAbortEx(strerror(errno));
+ }
+ if(lseek(srcFd, srcOffset, SEEK_SET) != srcOffset) {
+ throw new DlAbortEx(strerror(errno));
+ }
+ int BUF_SIZE = 16*1024;
+ char buf[BUF_SIZE];
+ int x = length/BUF_SIZE+(length%BUF_SIZE ? 1 : 0);
+ for(int i = 0; i < x; i++) {
+ int readLength;
+ if((readLength = read(srcFd, buf, BUF_SIZE)) == -1) {
+ throw new DlAbortEx(strerror(errno));
+ }
+ if(write(destFd, buf, readLength) == -1) {
+ throw new DlAbortEx(strerror(errno));
+ }
+ }
+ close(srcFd);
+ close(destFd);
+}
+
diff --git a/src/Util.h b/src/Util.h
index a208e802..f8e50932 100644
--- a/src/Util.h
+++ b/src/Util.h
@@ -56,6 +56,15 @@ public:
static bool endsWith(string target, string part);
static string replace(string target, string oldstr, string newstr);
+
+ static string urlencode(const unsigned char* target, int len);
+
+ static string toHex(const unsigned char* src, int len);
+
+ static FILE* openFile(string filename, string mode);
+
+ static void rangedFileCopy(string destFile, string src, long long int srcOffset, long long int length);
+
};
#endif // _D_UTIL_H_
diff --git a/src/common.h b/src/common.h
index 6b3672ad..1260edf5 100644
--- a/src/common.h
+++ b/src/common.h
@@ -41,6 +41,8 @@
#define USER_AGENT "aria2"
+#define BITFIELD_LEN_FROM_PIECES(X) (X/8+(X%8? 1 : 0))
+
using namespace std;
#endif // _D_COMMON_H_
diff --git a/src/main.cc b/src/main.cc
index c1b280d2..b7ed6347 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -21,7 +21,9 @@
/* copyright --> */
#include "HttpInitiateConnectionCommand.h"
#include "ConsoleDownloadEngine.h"
+#include "TorrentConsoleDownloadEngine.h"
#include "SegmentMan.h"
+#include "TorrentMan.h"
#include "SplitSlowestSegmentSplitter.h"
#include "SimpleLogger.h"
#include "common.h"
@@ -29,8 +31,13 @@
#include "Util.h"
#include "InitiateConnectionCommandFactory.h"
#include "prefs.h"
+#include "TrackerInitCommand.h"
+#include "PeerListenCommand.h"
+#include "TorrentAutoSaveCommand.h"
+#include "SleepCommand.h"
#include <vector>
#include <algorithm>
+#include <time.h>
#include <signal.h>
#include <unistd.h>
#include <libgen.h>
@@ -47,11 +54,20 @@ extern int optind, opterr, optopt;
using namespace std;
+void printDownloadCompeleteMessage(string filename) {
+ printf(_("\nThe download was complete. <%s>\n"), filename.c_str());
+}
+
+void printDownloadAbortMessage() {
+ printf(_("\nThe download was not complete because of errors. Check the log.\n"));
+}
+
void clearRequest(Request* req) {
delete(req);
}
DownloadEngine* e;
+TorrentDownloadEngine* te;
void handler(int signal) {
cout << _("\nSIGINT signal received.") << endl;
@@ -62,6 +78,22 @@ void handler(int signal) {
exit(0);
}
+void torrentHandler(int signal) {
+ cout << _("\nSIGINT signal received.") << endl;
+ if(te->torrentMan->diskWriter != NULL) {
+ te->torrentMan->diskWriter->closeFile();
+ }
+ if(te->torrentMan->downloadComplete()) {
+ te->torrentMan->remove();
+ te->torrentMan->fixFilename();
+ printDownloadCompeleteMessage(te->torrentMan->getFilePath());
+ } else {
+ te->torrentMan->save();
+ }
+
+ exit(0);
+}
+
void addCommand(int cuid, const char* url, string referer, vector<Request*> requests) {
Request* req = new Request();
req->setReferer(referer);
@@ -146,6 +178,11 @@ void showUsage() {
cout << _(" --ftp-via-http-proxy=METHOD Use HTTP proxy in FTP. METHOD is either 'get' or\n"
" 'tunnel'.\n"
" Default: tunnel") << endl;
+ cout << _(" --torrent-file=TORRENT_FILE The file path to .torrent file.") << endl;
+ cout << _(" --follow-torrent=true|false Setting this option to false prevents aria2 to\n"
+ " enter BitTorrent mode even if the filename of\n"
+ " downloaded file ends with .torrent.\n"
+ " Default: true") << endl;
cout << _(" -v, --version Print the version number and exit.") << endl;
cout << _(" -h, --help Print this message and exit.") << endl;
cout << endl;
@@ -162,6 +199,8 @@ void showUsage() {
cout << " aria2c http://AAA.BBB.CCC/file.zip http://DDD.EEE.FFF/GGG/file.zip" << endl;
cout << _(" You can mix up different protocols:") << endl;
cout << " aria2c http://AAA.BBB.CCC/file.zip ftp://DDD.EEE.FFF/GGG/file.zip" << endl;
+ cout << _(" Download a torrent") << endl;
+ cout << " aria2c -o test.torret http://AAA.BBB.CCC/file.torrent" << endl;
cout << endl;
printf(_("Reports bugs to %s"), "<tujikawa at users dot sourceforge dot net>");
cout << endl;
@@ -181,6 +220,8 @@ int main(int argc, char* argv[]) {
int split = 1;
bool daemonMode = false;
string referer;
+ string torrentFile;
+ bool followTorrent = true;
int c;
Option* op = new Option();
@@ -193,6 +234,7 @@ int main(int argc, char* argv[]) {
op->put(PREF_FTP_PASSWD, "ARIA2USER@");
op->put(PREF_FTP_TYPE, V_BINARY);
op->put(PREF_FTP_VIA_HTTP_PROXY, V_TUNNEL);
+ op->put(PREF_AUTO_SAVE_INTERVAL, "60");
while(1) {
int optIndex = 0;
@@ -220,6 +262,8 @@ int main(int argc, char* argv[]) {
{ "ftp-via-http-proxy", required_argument, &lopt, 12 },
{ "min-segment-size", required_argument, &lopt, 13 },
{ "http-proxy-method", required_argument, &lopt, 14 },
+ { "torrent-file", required_argument, &lopt, 15 },
+ { "follow-torrent", required_argument, &lopt, 16 },
{ "version", no_argument, NULL, 'v' },
{ "help", no_argument, NULL, 'h' },
{ 0, 0, 0, 0 }
@@ -332,6 +376,19 @@ int main(int argc, char* argv[]) {
exit(1);
}
break;
+ case 15:
+ torrentFile = string(optarg);
+ break;
+ case 16:
+ if(string(optarg) == "on") {
+ followTorrent = true;
+ } else if(string(optarg) == "off") {
+ followTorrent = false;
+ } else {
+ cerr << _("follow-torrent must be either 'true' or 'false'.") << endl;
+ showUsage();
+ exit(1);
+ }
}
break;
}
@@ -394,10 +451,12 @@ int main(int argc, char* argv[]) {
exit(1);
}
}
- if(optind == argc) {
- cerr << _("specify at least one URL") << endl;
- showUsage();
- exit(1);
+ if(torrentFile.empty()) {
+ if(optind == argc) {
+ cerr << _("specify at least one URL") << endl;
+ showUsage();
+ exit(1);
+ }
}
if(daemonMode) {
if(daemon(1, 1) < 0) {
@@ -410,6 +469,7 @@ int main(int argc, char* argv[]) {
SSL_load_error_strings();
SSL_library_init();
#endif // HAVE_LIBSSL
+ srandom(time(NULL));
SimpleLogger* logger;
if(stdoutLog) {
logger = new SimpleLogger(stdout);
@@ -420,43 +480,120 @@ int main(int argc, char* argv[]) {
}
SegmentSplitter* splitter = new SplitSlowestSegmentSplitter();
splitter->setMinSegmentSize(op->getAsLLInt(PREF_MIN_SEGMENT_SIZE));
- splitter->logger = logger;
- e = new ConsoleDownloadEngine();
- e->logger = logger;
- e->option = op;
- e->diskWriter = new DefaultDiskWriter();
- e->segmentMan = new SegmentMan();
- e->segmentMan->dir = dir;
- e->segmentMan->ufilename = ufilename;
- e->segmentMan->logger = logger;
- e->segmentMan->option = op;
- e->segmentMan->splitter = splitter;
- vector<Request*> requests;
- for(int i = 1; optind+i-1 < argc; i++) {
- for(int s = 1; s <= split; s++) {
+
+ struct sigaction sigactIgn;
+ sigactIgn.sa_handler = SIG_IGN;
+ sigactIgn.sa_flags = 0;
+ sigemptyset(&sigactIgn.sa_mask);
+ sigaction(SIGPIPE, &sigactIgn, NULL);
+
+ bool readyToTorrentMode = false;
+ string downloadedTorrentFile;
+ if(torrentFile.empty()) {
+ struct sigaction sigact;
+ sigact.sa_handler = handler;
+ sigact.sa_flags = 0;
+ sigemptyset(&sigact.sa_mask);
+ sigaction(SIGINT, &sigact, NULL);
+
+ splitter->logger = logger;
+ e = new ConsoleDownloadEngine();
+ e->logger = logger;
+ e->option = op;
+ e->diskWriter = new DefaultDiskWriter();
+ e->segmentMan = new SegmentMan();
+ e->segmentMan->dir = dir;
+ e->segmentMan->ufilename = ufilename;
+ e->segmentMan->logger = logger;
+ e->segmentMan->option = op;
+ e->segmentMan->splitter = splitter;
+
+ vector<Request*> requests;
+ for(int i = 1; optind+i-1 < argc; i++) {
+ for(int s = 1; s <= split; s++) {
addCommand(split*(i-1)+s, argv[optind+i-1], referer, requests);
+ }
}
- }
- struct sigaction sigact;
- sigact.sa_handler = handler;
- sigact.sa_flags = 0;
- sigemptyset(&sigact.sa_mask);
- sigaction(SIGINT, &sigact, NULL);
+ e->run();
+
+ if(e->segmentMan->finished()) {
+ printDownloadCompeleteMessage(e->segmentMan->getFilePath());
+ if(Util::endsWith(e->segmentMan->getFilePath(), ".torrent")) {
+ downloadedTorrentFile = e->segmentMan->getFilePath();
+ readyToTorrentMode = true;
+ }
+ } else {
+ printDownloadAbortMessage();
+ }
+
+ for_each(requests.begin(), requests.end(), clearRequest);
+ requests.clear();
- e->run();
+ delete(e->segmentMan);
+ delete(e->diskWriter);
+ delete(e);
+ }
+ if(!torrentFile.empty() || followTorrent && readyToTorrentMode) {
+ try {
+ op->put(PREF_MAX_TRIES, "0");
+ struct sigaction sigact;
+ sigact.sa_handler = torrentHandler;
+ sigact.sa_flags = 0;
+ sigemptyset(&sigact.sa_mask);
+ sigaction(SIGINT, &sigact, NULL);
+ Request* req = new Request();
+ req->isTorrent = true;
+ req->setTrackerEvent(Request::STARTED);
+ te = new TorrentConsoleDownloadEngine();
+ te->logger = logger;
+ te->option = op;
+ te->diskWriter = new DefaultDiskWriter();
+ te->segmentMan = new SegmentMan();
+ te->segmentMan->logger = logger;
+ te->segmentMan->option = op;
+ te->segmentMan->splitter = splitter;
+ te->torrentMan = new TorrentMan();
+ te->torrentMan->setStoreDir(dir);
+ te->torrentMan->logger = logger;
+ te->torrentMan->setup(torrentFile.empty() ?
+ downloadedTorrentFile : torrentFile);
- if(e->segmentMan->finished()) {
- printf(_("\nThe download was complete. <%s>\n"), e->segmentMan->getFilePath().c_str());
- } else {
- printf(_("\nThe download was not complete because of errors. Check the log.\n"));
+ PeerListenCommand* listenCommand =
+ new PeerListenCommand(te->torrentMan->getNewCuid(), te);
+ int port = listenCommand->bindPort(6881, 6999);
+ if(port == -1) {
+ printf("an error occurred while binding port.\n");
+ exit(1);
+ }
+ te->torrentMan->setPort(port);
+ te->commands.push(listenCommand);
+ te->commands.push(new TrackerInitCommand(te->torrentMan->getNewCuid(),
+ req, te));
+ int autoSaveCommandCuid = te->torrentMan->getNewCuid();
+ te->commands.push(new SleepCommand(autoSaveCommandCuid, te,
+ new TorrentAutoSaveCommand(autoSaveCommandCuid, te, op->getAsInt(PREF_AUTO_SAVE_INTERVAL)),
+ op->getAsInt(PREF_AUTO_SAVE_INTERVAL)));
+ te->run();
+
+ if(te->torrentMan->downloadComplete()) {
+ printDownloadCompeleteMessage(te->torrentMan->getFilePath());
+ } else {
+ printDownloadAbortMessage();
+ }
+
+ delete(te->segmentMan);
+ delete(te->torrentMan);
+ delete(te);
+ } catch(Exception* ex) {
+ cerr << ex->getMsg() << endl;
+ delete ex;
+ exit(1);
+ }
}
-
- for_each(requests.begin(), requests.end(), clearRequest);
- requests.clear();
+
delete(logger);
- delete(e->segmentMan);
- delete(e->option);
- delete(e->diskWriter);
- delete(e);
+ delete(op);
+ delete(splitter);
+
return 0;
}
diff --git a/src/message.h b/src/message.h
index 16596b0b..c38b2adc 100644
--- a/src/message.h
+++ b/src/message.h
@@ -35,6 +35,15 @@
#define MSG_RESTARTING_DOWNLOAD _("CUID#%d - Restarting the download.")
#define MSG_MAX_TRY _("CUID#%d - %d times attempted, but no success. Download aborted.")
#define MSG_UNREGISTER_CUID _("CUID#%d - Unregistering cuid from segmentManager.")
+#define MSG_SEND_PEER_MESSAGE "CUID#%d - To: %s:%d %s"
+#define MSG_SEND_PEER_MESSAGE_WITH_INDEX "CUID#%d - To: %s:%d %s index=%d"
+#define MSG_SEND_PEER_MESSAGE_WITH_BITFIELD "CUID#%d - To: %s:%d %s %s"
+#define MSG_SEND_PEER_MESSAGE_WITH_INDEX_BEGIN_LENGTH "CUID#%d - To: %s:%d %s index=%d, begin=%d, length=%d"
+#define MSG_RECEIVE_PEER_MESSAGE "CUID#%d - From: %s:%d %s"
+#define MSG_GOT_NEW_PIECE "CUID#%d - we got new piece. index=%d"
+#define MSG_GOT_WRONG_PIECE "CUID#%d - we got wrong piece. index=%d"
+
+#define MSG_TRACKER_WARNING_MESSAGE "CUID#%d - Tracker returned warning message: %s"
#define MSG_SEGMENT_FILE_EXISTS _("The segment file %s exists.")
#define MSG_SEGMENT_FILE_DOES_NOT_EXIST _("The segment file %s does not exist.")
@@ -59,5 +68,6 @@
#define EX_SSL_INIT_FAILURE _("SSL initialization failed.")
#define EX_SIZE_MISMATCH _("Size mismatch %lld != %lld")
#define EX_GOT_EOF _("Got EOF from the server.")
-
+#define EX_EOF_FROM_PEER "Got EOF from peer."
+#define EX_MULFORMED_META_INFO "Mulformed meta info."
#endif // _D_MESSAGE_H_
diff --git a/src/prefs.h b/src/prefs.h
index 8127bb09..140661c9 100644
--- a/src/prefs.h
+++ b/src/prefs.h
@@ -41,6 +41,8 @@
#define PREF_MAX_TRIES "max_try"
// values: 1*digit
#define PREF_MIN_SEGMENT_SIZE "min_segment_size"
+// values: 1*digit
+#define PREF_AUTO_SAVE_INTERVAL "auto_save_interval"
/**
* FTP related preferences
diff --git a/test/BitfieldManTest.cc b/test/BitfieldManTest.cc
new file mode 100644
index 00000000..018b4e83
--- /dev/null
+++ b/test/BitfieldManTest.cc
@@ -0,0 +1,76 @@
+#include "BitfieldMan.h"
+#include <string>
+#include <cppunit/extensions/HelperMacros.h>
+
+using namespace std;
+
+class BitfieldManTest:public CppUnit::TestFixture {
+
+ CPPUNIT_TEST_SUITE(BitfieldManTest);
+ CPPUNIT_TEST(testGetBlockSize);
+ CPPUNIT_TEST(testGetFirstMissingUnusedIndex);
+ CPPUNIT_TEST(testIsAllBitSet);
+ CPPUNIT_TEST_SUITE_END();
+private:
+
+public:
+ void setUp() {
+ }
+
+ void testGetBlockSize();
+ void testGetFirstMissingUnusedIndex();
+ void testIsAllBitSet();
+};
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION( BitfieldManTest );
+
+void BitfieldManTest::testGetBlockSize() {
+ BitfieldMan bt1(1024, 1024*10);
+ CPPUNIT_ASSERT_EQUAL(1024, bt1.getBlockSize(9));
+
+ BitfieldMan bt2(1024, 1024*10+1);
+ CPPUNIT_ASSERT_EQUAL(1024, bt2.getBlockSize(9));
+ CPPUNIT_ASSERT_EQUAL(1, bt2.getBlockSize(10));
+ CPPUNIT_ASSERT_EQUAL(0, bt2.getBlockSize(11));
+}
+
+void BitfieldManTest::testGetFirstMissingUnusedIndex() {
+ BitfieldMan bt1(1024, 1024*10);
+ unsigned char bitfield[2];
+ memset(bitfield, 0xff, sizeof(bitfield));
+
+ CPPUNIT_ASSERT_EQUAL(0, bt1.getFirstMissingUnusedIndex(bitfield, sizeof(bitfield)));
+ CPPUNIT_ASSERT(bt1.setUseBit(0));
+ CPPUNIT_ASSERT_EQUAL(1, bt1.getFirstMissingUnusedIndex(bitfield, sizeof(bitfield)));
+ CPPUNIT_ASSERT(bt1.unsetUseBit(0));
+ CPPUNIT_ASSERT_EQUAL(0, bt1.getFirstMissingUnusedIndex(bitfield, sizeof(bitfield)));
+ CPPUNIT_ASSERT(bt1.setBit(0));
+ CPPUNIT_ASSERT_EQUAL(1, bt1.getFirstMissingUnusedIndex(bitfield, sizeof(bitfield)));
+
+ for(int i = 0; i < 8; i++) {
+ CPPUNIT_ASSERT(bt1.setBit(i));
+ }
+ CPPUNIT_ASSERT_EQUAL(8, bt1.getFirstMissingUnusedIndex(bitfield, sizeof(bitfield)));
+
+ CPPUNIT_ASSERT_EQUAL(8, bt1.getFirstMissingUnusedIndex());
+ CPPUNIT_ASSERT(bt1.setUseBit(8));
+ CPPUNIT_ASSERT_EQUAL(9, bt1.getFirstMissingUnusedIndex());
+}
+
+void BitfieldManTest::testIsAllBitSet() {
+ BitfieldMan bt1(1024, 1024*10);
+ CPPUNIT_ASSERT(!bt1.isAllBitSet());
+ bt1.setBit(1);
+ CPPUNIT_ASSERT(!bt1.isAllBitSet());
+
+ for(int i = 0; i < 8; i++) {
+ CPPUNIT_ASSERT(bt1.setBit(i));
+ }
+ CPPUNIT_ASSERT(!bt1.isAllBitSet());
+
+ for(int i = 0; i < bt1.getBlocks(); i++) {
+ CPPUNIT_ASSERT(bt1.setBit(i));
+ }
+ CPPUNIT_ASSERT(bt1.isAllBitSet());
+}
diff --git a/test/DataTest.cc b/test/DataTest.cc
new file mode 100644
index 00000000..da678977
--- /dev/null
+++ b/test/DataTest.cc
@@ -0,0 +1,70 @@
+#include "Data.h"
+#include <string>
+#include <cppunit/extensions/HelperMacros.h>
+
+using namespace std;
+
+class DataTest:public CppUnit::TestFixture {
+
+ CPPUNIT_TEST_SUITE(DataTest);
+ CPPUNIT_TEST(testToString);
+ CPPUNIT_TEST(testGetData);
+ CPPUNIT_TEST(testToInt);
+ CPPUNIT_TEST(testToLLInt);
+ CPPUNIT_TEST_SUITE_END();
+private:
+
+public:
+ void setUp() {
+ }
+
+ void testToString();
+ void testGetData();
+ void testToInt();
+ void testToLLInt();
+};
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION( DataTest );
+
+void DataTest::testToString() {
+ Data data("aria2", 5);
+ CPPUNIT_ASSERT_EQUAL(string("aria2"), data.toString());
+
+ Data null(NULL, 0);
+ CPPUNIT_ASSERT_EQUAL(string(""), null.toString());
+}
+
+void DataTest::testGetData() {
+ Data data("aria2", 5);
+ int len;
+ CPPUNIT_ASSERT_EQUAL(0, memcmp("aria2", data.getData(), 5));
+ CPPUNIT_ASSERT_EQUAL(5, data.getLen());
+
+ Data null(NULL, 0);
+ CPPUNIT_ASSERT_EQUAL((const char*)NULL, null.getData());
+ CPPUNIT_ASSERT_EQUAL(0, null.getLen());
+
+}
+
+void DataTest::testToInt() {
+ Data data("1000", 4);
+ CPPUNIT_ASSERT_EQUAL(1000, data.toInt());
+
+ Data null(NULL, 0);
+ CPPUNIT_ASSERT_EQUAL(0, null.toInt());
+
+ Data alpha("abc", 3);
+ CPPUNIT_ASSERT_EQUAL(0, alpha.toInt());
+}
+
+void DataTest::testToLLInt() {
+ Data data("1000", 4);
+ CPPUNIT_ASSERT_EQUAL(1000, (int)data.toLLInt());
+
+ Data null(NULL, 0);
+ CPPUNIT_ASSERT_EQUAL(0, (int)null.toLLInt());
+
+ Data alpha("abc", 3);
+ CPPUNIT_ASSERT_EQUAL(0, (int)alpha.toLLInt());
+}
diff --git a/test/DefaultDiskWriterTest.cc b/test/DefaultDiskWriterTest.cc
new file mode 100644
index 00000000..dc939918
--- /dev/null
+++ b/test/DefaultDiskWriterTest.cc
@@ -0,0 +1,35 @@
+#include "DefaultDiskWriter.h"
+#include <string>
+#include <cppunit/extensions/HelperMacros.h>
+
+using namespace std;
+
+class DefaultDiskWriterTest:public CppUnit::TestFixture {
+
+ CPPUNIT_TEST_SUITE(DefaultDiskWriterTest);
+ CPPUNIT_TEST(testSha1Sum);
+ CPPUNIT_TEST_SUITE_END();
+private:
+
+public:
+ void setUp() {
+ }
+
+ void testSha1Sum();
+};
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION( DefaultDiskWriterTest );
+
+void DefaultDiskWriterTest::testSha1Sum() {
+ DefaultDiskWriter dw;
+ dw.openExistingFile("4096chunk.txt");
+
+ CPPUNIT_ASSERT_EQUAL(string("608cabc0f2fa18c260cafd974516865c772363d5"),
+ dw.sha1Sum(0, 4096));
+
+ CPPUNIT_ASSERT_EQUAL(string("7a4a9ae537ebbbb826b1060e704490ad0f365ead"),
+ dw.sha1Sum(5, 100));
+
+ dw.closeFile();
+}
diff --git a/test/DictionaryTest.cc b/test/DictionaryTest.cc
new file mode 100644
index 00000000..95c5b418
--- /dev/null
+++ b/test/DictionaryTest.cc
@@ -0,0 +1,35 @@
+#include "Dictionary.h"
+#include "Data.h"
+#include <string>
+#include <cppunit/extensions/HelperMacros.h>
+
+using namespace std;
+
+class DictionaryTest:public CppUnit::TestFixture {
+
+ CPPUNIT_TEST_SUITE(DictionaryTest);
+ CPPUNIT_TEST(testGet);
+ CPPUNIT_TEST_SUITE_END();
+private:
+
+public:
+ void setUp() {
+ }
+
+ void testGet();
+};
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION( DictionaryTest );
+
+void DictionaryTest::testGet() {
+ Dictionary d;
+ Data* data1 = new Data("aria2", 5);
+ d.put("app_name", data1);
+ Data* data2 = new Data("linux", 5);
+ d.put("platform", data2);
+ Data* dataGot = (Data*)d.get("app_name");
+ CPPUNIT_ASSERT(dataGot != NULL);
+ CPPUNIT_ASSERT_EQUAL(string("aria2"), dataGot->toString());
+}
+
diff --git a/test/FileTest.cc b/test/FileTest.cc
index 71576e2e..a31f824a 100644
--- a/test/FileTest.cc
+++ b/test/FileTest.cc
@@ -14,6 +14,7 @@ class FileTest:public CppUnit::TestFixture {
CPPUNIT_TEST(testIsFile);
CPPUNIT_TEST(testIsDir);
CPPUNIT_TEST(testRemove);
+ CPPUNIT_TEST(testSize);
CPPUNIT_TEST_SUITE_END();
private:
@@ -25,6 +26,7 @@ public:
void testIsFile();
void testIsDir();
void testRemove();
+ void testSize();
};
@@ -86,3 +88,8 @@ void FileTest::testRemove() {
// delete the directory again
CPPUNIT_ASSERT(!d.remove());
}
+
+void FileTest::testSize() {
+ File f("4096chunk.txt");
+ CPPUNIT_ASSERT_EQUAL(4096, (int)f.size());
+}
diff --git a/test/ListTest.cc b/test/ListTest.cc
new file mode 100644
index 00000000..8652c383
--- /dev/null
+++ b/test/ListTest.cc
@@ -0,0 +1,33 @@
+#include "List.h"
+#include "Data.h"
+#include <string>
+#include <cppunit/extensions/HelperMacros.h>
+
+using namespace std;
+
+class ListTest:public CppUnit::TestFixture {
+
+ CPPUNIT_TEST_SUITE(ListTest);
+ CPPUNIT_TEST(testAdd);
+ CPPUNIT_TEST_SUITE_END();
+private:
+
+public:
+ void setUp() {
+ }
+
+ void testAdd();
+};
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION( ListTest );
+
+void ListTest::testAdd() {
+ List l;
+ Data* data1 = new Data("usr", 3);
+ l.add(data1);
+ Data* data2 = new Data("local", 5);
+ l.add(data2);
+ CPPUNIT_ASSERT_EQUAL(2, (int)l.getList().size());
+}
+
diff --git a/test/Makefile.am b/test/Makefile.am
index 72bbd507..60b7a83a 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -7,7 +7,16 @@ aria2c_SOURCES = AllTest.cc\
OptionTest.cc\
Base64Test.cc\
UtilTest.cc\
- CookieBoxTest.cc
+ CookieBoxTest.cc\
+ DataTest.cc\
+ DictionaryTest.cc\
+ ListTest.cc\
+ MetaFileUtilTest.cc\
+ ShaVisitorTest.cc\
+ TorrentManTest.cc\
+ PeerMessageUtilTest.cc\
+ BitfieldManTest.cc\
+ DefaultDiskWriterTest.cc
aria2c_CXXFLAGS = ${CPPUNIT_CFLAGS} -I../src -I../lib -Wall -D_FILE_OFFSET_BITS=64
aria2c_LDFLAGS = ${CPPUNIT_LIBS}
aria2c_LDADD = ../src/libaria2c.a \ No newline at end of file
diff --git a/test/Makefile.in b/test/Makefile.in
index 9b2cfe3b..25bebb08 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -59,7 +59,14 @@ am_aria2c_OBJECTS = aria2c-AllTest.$(OBJEXT) \
aria2c-RequestTest.$(OBJEXT) \
aria2c-ChunkedEncodingTest.$(OBJEXT) aria2c-FileTest.$(OBJEXT) \
aria2c-OptionTest.$(OBJEXT) aria2c-Base64Test.$(OBJEXT) \
- aria2c-UtilTest.$(OBJEXT) aria2c-CookieBoxTest.$(OBJEXT)
+ aria2c-UtilTest.$(OBJEXT) aria2c-CookieBoxTest.$(OBJEXT) \
+ aria2c-DataTest.$(OBJEXT) aria2c-DictionaryTest.$(OBJEXT) \
+ aria2c-ListTest.$(OBJEXT) aria2c-MetaFileUtilTest.$(OBJEXT) \
+ aria2c-ShaVisitorTest.$(OBJEXT) \
+ aria2c-TorrentManTest.$(OBJEXT) \
+ aria2c-PeerMessageUtilTest.$(OBJEXT) \
+ aria2c-BitfieldManTest.$(OBJEXT) \
+ aria2c-DefaultDiskWriterTest.$(OBJEXT)
aria2c_OBJECTS = $(am_aria2c_OBJECTS)
aria2c_DEPENDENCIES = ../src/libaria2c.a
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
@@ -197,7 +204,16 @@ aria2c_SOURCES = AllTest.cc\
OptionTest.cc\
Base64Test.cc\
UtilTest.cc\
- CookieBoxTest.cc
+ CookieBoxTest.cc\
+ DataTest.cc\
+ DictionaryTest.cc\
+ ListTest.cc\
+ MetaFileUtilTest.cc\
+ ShaVisitorTest.cc\
+ TorrentManTest.cc\
+ PeerMessageUtilTest.cc\
+ BitfieldManTest.cc\
+ DefaultDiskWriterTest.cc
aria2c_CXXFLAGS = ${CPPUNIT_CFLAGS} -I../src -I../lib -Wall -D_FILE_OFFSET_BITS=64
aria2c_LDFLAGS = ${CPPUNIT_LIBS}
@@ -250,11 +266,20 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aria2c-AllTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aria2c-Base64Test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aria2c-BitfieldManTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aria2c-ChunkedEncodingTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aria2c-CookieBoxTest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aria2c-DataTest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aria2c-DefaultDiskWriterTest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aria2c-DictionaryTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aria2c-FileTest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aria2c-ListTest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aria2c-MetaFileUtilTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aria2c-OptionTest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aria2c-PeerMessageUtilTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aria2c-RequestTest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aria2c-ShaVisitorTest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aria2c-TorrentManTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aria2c-UtilTest.Po@am__quote@
.cc.o:
@@ -382,6 +407,132 @@ aria2c-CookieBoxTest.obj: CookieBoxTest.cc
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='CookieBoxTest.cc' object='aria2c-CookieBoxTest.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -c -o aria2c-CookieBoxTest.obj `if test -f 'CookieBoxTest.cc'; then $(CYGPATH_W) 'CookieBoxTest.cc'; else $(CYGPATH_W) '$(srcdir)/CookieBoxTest.cc'; fi`
+
+aria2c-DataTest.o: DataTest.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -MT aria2c-DataTest.o -MD -MP -MF "$(DEPDIR)/aria2c-DataTest.Tpo" -c -o aria2c-DataTest.o `test -f 'DataTest.cc' || echo '$(srcdir)/'`DataTest.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/aria2c-DataTest.Tpo" "$(DEPDIR)/aria2c-DataTest.Po"; else rm -f "$(DEPDIR)/aria2c-DataTest.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='DataTest.cc' object='aria2c-DataTest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -c -o aria2c-DataTest.o `test -f 'DataTest.cc' || echo '$(srcdir)/'`DataTest.cc
+
+aria2c-DataTest.obj: DataTest.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -MT aria2c-DataTest.obj -MD -MP -MF "$(DEPDIR)/aria2c-DataTest.Tpo" -c -o aria2c-DataTest.obj `if test -f 'DataTest.cc'; then $(CYGPATH_W) 'DataTest.cc'; else $(CYGPATH_W) '$(srcdir)/DataTest.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/aria2c-DataTest.Tpo" "$(DEPDIR)/aria2c-DataTest.Po"; else rm -f "$(DEPDIR)/aria2c-DataTest.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='DataTest.cc' object='aria2c-DataTest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -c -o aria2c-DataTest.obj `if test -f 'DataTest.cc'; then $(CYGPATH_W) 'DataTest.cc'; else $(CYGPATH_W) '$(srcdir)/DataTest.cc'; fi`
+
+aria2c-DictionaryTest.o: DictionaryTest.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -MT aria2c-DictionaryTest.o -MD -MP -MF "$(DEPDIR)/aria2c-DictionaryTest.Tpo" -c -o aria2c-DictionaryTest.o `test -f 'DictionaryTest.cc' || echo '$(srcdir)/'`DictionaryTest.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/aria2c-DictionaryTest.Tpo" "$(DEPDIR)/aria2c-DictionaryTest.Po"; else rm -f "$(DEPDIR)/aria2c-DictionaryTest.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='DictionaryTest.cc' object='aria2c-DictionaryTest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -c -o aria2c-DictionaryTest.o `test -f 'DictionaryTest.cc' || echo '$(srcdir)/'`DictionaryTest.cc
+
+aria2c-DictionaryTest.obj: DictionaryTest.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -MT aria2c-DictionaryTest.obj -MD -MP -MF "$(DEPDIR)/aria2c-DictionaryTest.Tpo" -c -o aria2c-DictionaryTest.obj `if test -f 'DictionaryTest.cc'; then $(CYGPATH_W) 'DictionaryTest.cc'; else $(CYGPATH_W) '$(srcdir)/DictionaryTest.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/aria2c-DictionaryTest.Tpo" "$(DEPDIR)/aria2c-DictionaryTest.Po"; else rm -f "$(DEPDIR)/aria2c-DictionaryTest.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='DictionaryTest.cc' object='aria2c-DictionaryTest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -c -o aria2c-DictionaryTest.obj `if test -f 'DictionaryTest.cc'; then $(CYGPATH_W) 'DictionaryTest.cc'; else $(CYGPATH_W) '$(srcdir)/DictionaryTest.cc'; fi`
+
+aria2c-ListTest.o: ListTest.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -MT aria2c-ListTest.o -MD -MP -MF "$(DEPDIR)/aria2c-ListTest.Tpo" -c -o aria2c-ListTest.o `test -f 'ListTest.cc' || echo '$(srcdir)/'`ListTest.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/aria2c-ListTest.Tpo" "$(DEPDIR)/aria2c-ListTest.Po"; else rm -f "$(DEPDIR)/aria2c-ListTest.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='ListTest.cc' object='aria2c-ListTest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -c -o aria2c-ListTest.o `test -f 'ListTest.cc' || echo '$(srcdir)/'`ListTest.cc
+
+aria2c-ListTest.obj: ListTest.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -MT aria2c-ListTest.obj -MD -MP -MF "$(DEPDIR)/aria2c-ListTest.Tpo" -c -o aria2c-ListTest.obj `if test -f 'ListTest.cc'; then $(CYGPATH_W) 'ListTest.cc'; else $(CYGPATH_W) '$(srcdir)/ListTest.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/aria2c-ListTest.Tpo" "$(DEPDIR)/aria2c-ListTest.Po"; else rm -f "$(DEPDIR)/aria2c-ListTest.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='ListTest.cc' object='aria2c-ListTest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -c -o aria2c-ListTest.obj `if test -f 'ListTest.cc'; then $(CYGPATH_W) 'ListTest.cc'; else $(CYGPATH_W) '$(srcdir)/ListTest.cc'; fi`
+
+aria2c-MetaFileUtilTest.o: MetaFileUtilTest.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -MT aria2c-MetaFileUtilTest.o -MD -MP -MF "$(DEPDIR)/aria2c-MetaFileUtilTest.Tpo" -c -o aria2c-MetaFileUtilTest.o `test -f 'MetaFileUtilTest.cc' || echo '$(srcdir)/'`MetaFileUtilTest.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/aria2c-MetaFileUtilTest.Tpo" "$(DEPDIR)/aria2c-MetaFileUtilTest.Po"; else rm -f "$(DEPDIR)/aria2c-MetaFileUtilTest.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='MetaFileUtilTest.cc' object='aria2c-MetaFileUtilTest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -c -o aria2c-MetaFileUtilTest.o `test -f 'MetaFileUtilTest.cc' || echo '$(srcdir)/'`MetaFileUtilTest.cc
+
+aria2c-MetaFileUtilTest.obj: MetaFileUtilTest.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -MT aria2c-MetaFileUtilTest.obj -MD -MP -MF "$(DEPDIR)/aria2c-MetaFileUtilTest.Tpo" -c -o aria2c-MetaFileUtilTest.obj `if test -f 'MetaFileUtilTest.cc'; then $(CYGPATH_W) 'MetaFileUtilTest.cc'; else $(CYGPATH_W) '$(srcdir)/MetaFileUtilTest.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/aria2c-MetaFileUtilTest.Tpo" "$(DEPDIR)/aria2c-MetaFileUtilTest.Po"; else rm -f "$(DEPDIR)/aria2c-MetaFileUtilTest.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='MetaFileUtilTest.cc' object='aria2c-MetaFileUtilTest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -c -o aria2c-MetaFileUtilTest.obj `if test -f 'MetaFileUtilTest.cc'; then $(CYGPATH_W) 'MetaFileUtilTest.cc'; else $(CYGPATH_W) '$(srcdir)/MetaFileUtilTest.cc'; fi`
+
+aria2c-ShaVisitorTest.o: ShaVisitorTest.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -MT aria2c-ShaVisitorTest.o -MD -MP -MF "$(DEPDIR)/aria2c-ShaVisitorTest.Tpo" -c -o aria2c-ShaVisitorTest.o `test -f 'ShaVisitorTest.cc' || echo '$(srcdir)/'`ShaVisitorTest.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/aria2c-ShaVisitorTest.Tpo" "$(DEPDIR)/aria2c-ShaVisitorTest.Po"; else rm -f "$(DEPDIR)/aria2c-ShaVisitorTest.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='ShaVisitorTest.cc' object='aria2c-ShaVisitorTest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -c -o aria2c-ShaVisitorTest.o `test -f 'ShaVisitorTest.cc' || echo '$(srcdir)/'`ShaVisitorTest.cc
+
+aria2c-ShaVisitorTest.obj: ShaVisitorTest.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -MT aria2c-ShaVisitorTest.obj -MD -MP -MF "$(DEPDIR)/aria2c-ShaVisitorTest.Tpo" -c -o aria2c-ShaVisitorTest.obj `if test -f 'ShaVisitorTest.cc'; then $(CYGPATH_W) 'ShaVisitorTest.cc'; else $(CYGPATH_W) '$(srcdir)/ShaVisitorTest.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/aria2c-ShaVisitorTest.Tpo" "$(DEPDIR)/aria2c-ShaVisitorTest.Po"; else rm -f "$(DEPDIR)/aria2c-ShaVisitorTest.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='ShaVisitorTest.cc' object='aria2c-ShaVisitorTest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -c -o aria2c-ShaVisitorTest.obj `if test -f 'ShaVisitorTest.cc'; then $(CYGPATH_W) 'ShaVisitorTest.cc'; else $(CYGPATH_W) '$(srcdir)/ShaVisitorTest.cc'; fi`
+
+aria2c-TorrentManTest.o: TorrentManTest.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -MT aria2c-TorrentManTest.o -MD -MP -MF "$(DEPDIR)/aria2c-TorrentManTest.Tpo" -c -o aria2c-TorrentManTest.o `test -f 'TorrentManTest.cc' || echo '$(srcdir)/'`TorrentManTest.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/aria2c-TorrentManTest.Tpo" "$(DEPDIR)/aria2c-TorrentManTest.Po"; else rm -f "$(DEPDIR)/aria2c-TorrentManTest.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='TorrentManTest.cc' object='aria2c-TorrentManTest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -c -o aria2c-TorrentManTest.o `test -f 'TorrentManTest.cc' || echo '$(srcdir)/'`TorrentManTest.cc
+
+aria2c-TorrentManTest.obj: TorrentManTest.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -MT aria2c-TorrentManTest.obj -MD -MP -MF "$(DEPDIR)/aria2c-TorrentManTest.Tpo" -c -o aria2c-TorrentManTest.obj `if test -f 'TorrentManTest.cc'; then $(CYGPATH_W) 'TorrentManTest.cc'; else $(CYGPATH_W) '$(srcdir)/TorrentManTest.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/aria2c-TorrentManTest.Tpo" "$(DEPDIR)/aria2c-TorrentManTest.Po"; else rm -f "$(DEPDIR)/aria2c-TorrentManTest.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='TorrentManTest.cc' object='aria2c-TorrentManTest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -c -o aria2c-TorrentManTest.obj `if test -f 'TorrentManTest.cc'; then $(CYGPATH_W) 'TorrentManTest.cc'; else $(CYGPATH_W) '$(srcdir)/TorrentManTest.cc'; fi`
+
+aria2c-PeerMessageUtilTest.o: PeerMessageUtilTest.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -MT aria2c-PeerMessageUtilTest.o -MD -MP -MF "$(DEPDIR)/aria2c-PeerMessageUtilTest.Tpo" -c -o aria2c-PeerMessageUtilTest.o `test -f 'PeerMessageUtilTest.cc' || echo '$(srcdir)/'`PeerMessageUtilTest.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/aria2c-PeerMessageUtilTest.Tpo" "$(DEPDIR)/aria2c-PeerMessageUtilTest.Po"; else rm -f "$(DEPDIR)/aria2c-PeerMessageUtilTest.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='PeerMessageUtilTest.cc' object='aria2c-PeerMessageUtilTest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -c -o aria2c-PeerMessageUtilTest.o `test -f 'PeerMessageUtilTest.cc' || echo '$(srcdir)/'`PeerMessageUtilTest.cc
+
+aria2c-PeerMessageUtilTest.obj: PeerMessageUtilTest.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -MT aria2c-PeerMessageUtilTest.obj -MD -MP -MF "$(DEPDIR)/aria2c-PeerMessageUtilTest.Tpo" -c -o aria2c-PeerMessageUtilTest.obj `if test -f 'PeerMessageUtilTest.cc'; then $(CYGPATH_W) 'PeerMessageUtilTest.cc'; else $(CYGPATH_W) '$(srcdir)/PeerMessageUtilTest.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/aria2c-PeerMessageUtilTest.Tpo" "$(DEPDIR)/aria2c-PeerMessageUtilTest.Po"; else rm -f "$(DEPDIR)/aria2c-PeerMessageUtilTest.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='PeerMessageUtilTest.cc' object='aria2c-PeerMessageUtilTest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -c -o aria2c-PeerMessageUtilTest.obj `if test -f 'PeerMessageUtilTest.cc'; then $(CYGPATH_W) 'PeerMessageUtilTest.cc'; else $(CYGPATH_W) '$(srcdir)/PeerMessageUtilTest.cc'; fi`
+
+aria2c-BitfieldManTest.o: BitfieldManTest.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -MT aria2c-BitfieldManTest.o -MD -MP -MF "$(DEPDIR)/aria2c-BitfieldManTest.Tpo" -c -o aria2c-BitfieldManTest.o `test -f 'BitfieldManTest.cc' || echo '$(srcdir)/'`BitfieldManTest.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/aria2c-BitfieldManTest.Tpo" "$(DEPDIR)/aria2c-BitfieldManTest.Po"; else rm -f "$(DEPDIR)/aria2c-BitfieldManTest.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='BitfieldManTest.cc' object='aria2c-BitfieldManTest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -c -o aria2c-BitfieldManTest.o `test -f 'BitfieldManTest.cc' || echo '$(srcdir)/'`BitfieldManTest.cc
+
+aria2c-BitfieldManTest.obj: BitfieldManTest.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -MT aria2c-BitfieldManTest.obj -MD -MP -MF "$(DEPDIR)/aria2c-BitfieldManTest.Tpo" -c -o aria2c-BitfieldManTest.obj `if test -f 'BitfieldManTest.cc'; then $(CYGPATH_W) 'BitfieldManTest.cc'; else $(CYGPATH_W) '$(srcdir)/BitfieldManTest.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/aria2c-BitfieldManTest.Tpo" "$(DEPDIR)/aria2c-BitfieldManTest.Po"; else rm -f "$(DEPDIR)/aria2c-BitfieldManTest.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='BitfieldManTest.cc' object='aria2c-BitfieldManTest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -c -o aria2c-BitfieldManTest.obj `if test -f 'BitfieldManTest.cc'; then $(CYGPATH_W) 'BitfieldManTest.cc'; else $(CYGPATH_W) '$(srcdir)/BitfieldManTest.cc'; fi`
+
+aria2c-DefaultDiskWriterTest.o: DefaultDiskWriterTest.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -MT aria2c-DefaultDiskWriterTest.o -MD -MP -MF "$(DEPDIR)/aria2c-DefaultDiskWriterTest.Tpo" -c -o aria2c-DefaultDiskWriterTest.o `test -f 'DefaultDiskWriterTest.cc' || echo '$(srcdir)/'`DefaultDiskWriterTest.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/aria2c-DefaultDiskWriterTest.Tpo" "$(DEPDIR)/aria2c-DefaultDiskWriterTest.Po"; else rm -f "$(DEPDIR)/aria2c-DefaultDiskWriterTest.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='DefaultDiskWriterTest.cc' object='aria2c-DefaultDiskWriterTest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -c -o aria2c-DefaultDiskWriterTest.o `test -f 'DefaultDiskWriterTest.cc' || echo '$(srcdir)/'`DefaultDiskWriterTest.cc
+
+aria2c-DefaultDiskWriterTest.obj: DefaultDiskWriterTest.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -MT aria2c-DefaultDiskWriterTest.obj -MD -MP -MF "$(DEPDIR)/aria2c-DefaultDiskWriterTest.Tpo" -c -o aria2c-DefaultDiskWriterTest.obj `if test -f 'DefaultDiskWriterTest.cc'; then $(CYGPATH_W) 'DefaultDiskWriterTest.cc'; else $(CYGPATH_W) '$(srcdir)/DefaultDiskWriterTest.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/aria2c-DefaultDiskWriterTest.Tpo" "$(DEPDIR)/aria2c-DefaultDiskWriterTest.Po"; else rm -f "$(DEPDIR)/aria2c-DefaultDiskWriterTest.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='DefaultDiskWriterTest.cc' object='aria2c-DefaultDiskWriterTest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aria2c_CXXFLAGS) $(CXXFLAGS) -c -o aria2c-DefaultDiskWriterTest.obj `if test -f 'DefaultDiskWriterTest.cc'; then $(CYGPATH_W) 'DefaultDiskWriterTest.cc'; else $(CYGPATH_W) '$(srcdir)/DefaultDiskWriterTest.cc'; fi`
uninstall-info-am:
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
diff --git a/test/MetaFileUtilTest.cc b/test/MetaFileUtilTest.cc
new file mode 100644
index 00000000..aa53aa74
--- /dev/null
+++ b/test/MetaFileUtilTest.cc
@@ -0,0 +1,77 @@
+#include "MetaFileUtil.h"
+#include "Data.h"
+#include "Dictionary.h"
+#include "List.h"
+#include "DlAbortEx.h"
+#include <string>
+#include <cppunit/extensions/HelperMacros.h>
+
+using namespace std;
+
+class MetaFileUtilTest:public CppUnit::TestFixture {
+
+ CPPUNIT_TEST_SUITE(MetaFileUtilTest);
+ CPPUNIT_TEST(testParseMetaFile);
+ CPPUNIT_TEST(testBdecoding);
+ CPPUNIT_TEST_SUITE_END();
+private:
+
+public:
+ void setUp() {
+ }
+
+ void testParseMetaFile();
+ void testBdecoding();
+};
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION( MetaFileUtilTest );
+
+void MetaFileUtilTest::testParseMetaFile() {
+ MetaEntry* entry = MetaFileUtil::parseMetaFile("test.torrent");
+ Dictionary* d = dynamic_cast<Dictionary*>(entry);
+ CPPUNIT_ASSERT(d != NULL);
+}
+
+void MetaFileUtilTest::testBdecoding() {
+ try {
+ char* str = "5:abcd";
+ MetaEntry* entry = MetaFileUtil::bdecoding(str, strlen(str));
+ CPPUNIT_FAIL("DlAbortEx exception must be throwed.");
+ } catch(DlAbortEx* ex) {
+ delete ex;
+ } catch(...) {
+ CPPUNIT_FAIL("DlAbortEx exception must be throwed.");
+ }
+
+ try {
+ char* str = "i1234";
+ MetaEntry* entry = MetaFileUtil::bdecoding(str, strlen(str));
+ CPPUNIT_FAIL("DlAbortEx exception must be throwed.");
+ } catch(DlAbortEx* ex) {
+ delete ex;
+ } catch(...) {
+ CPPUNIT_FAIL("DlAbortEx exception must be throwed.");
+ }
+
+ try {
+ char* str = "5abcd";
+ MetaEntry* entry = MetaFileUtil::bdecoding(str, strlen(str));
+ CPPUNIT_FAIL("DlAbortEx exception must be throwed.");
+ } catch(DlAbortEx* ex) {
+ delete ex;
+ } catch(...) {
+ CPPUNIT_FAIL("DlAbortEx exception must be throwed.");
+ }
+
+ try {
+ char* str = "d";
+ MetaEntry* entry = MetaFileUtil::bdecoding(str, strlen(str));
+ CPPUNIT_FAIL("DlAbortEx exception must be throwed.");
+ } catch(DlAbortEx* ex) {
+ delete ex;
+ } catch(...) {
+ CPPUNIT_FAIL("DlAbortEx exception must be throwed.");
+ }
+}
+
diff --git a/test/PeerMessageUtilTest.cc b/test/PeerMessageUtilTest.cc
new file mode 100644
index 00000000..d58c3ecf
--- /dev/null
+++ b/test/PeerMessageUtilTest.cc
@@ -0,0 +1,352 @@
+#include "PeerMessageUtil.h"
+#include <netinet/in.h>
+#include <string>
+#include <cppunit/extensions/HelperMacros.h>
+
+using namespace std;
+
+class PeerMessageUtilTest:public CppUnit::TestFixture {
+
+ CPPUNIT_TEST_SUITE(PeerMessageUtilTest);
+ CPPUNIT_TEST(testCreatePeerMessageKeepAlive);
+ CPPUNIT_TEST(testCreatePeerMessageChoke);
+ CPPUNIT_TEST(testCreatePeerMessageUnchoke);
+ CPPUNIT_TEST(testCreatePeerMessageInterested);
+ CPPUNIT_TEST(testCreatePeerMessageNotInterested);
+ CPPUNIT_TEST(testCreatePeerMessageHave);
+ CPPUNIT_TEST(testCreatePeerMessageBitfield);
+ CPPUNIT_TEST(testCreatePeerMessageRequest);
+ CPPUNIT_TEST(testCreatePeerMessagePiece);
+ CPPUNIT_TEST(testCreatePeerMessageCancel);
+ CPPUNIT_TEST(testCheckIntegrityHave);
+ CPPUNIT_TEST(testCheckIntegrityBitfield);
+ CPPUNIT_TEST(testCheckIntegrityRequest);
+ CPPUNIT_TEST_SUITE_END();
+private:
+
+public:
+ void setUp() {
+ }
+
+ void testCreatePeerMessageKeepAlive();
+ void testCreatePeerMessageChoke();
+ void testCreatePeerMessageUnchoke();
+ void testCreatePeerMessageInterested();
+ void testCreatePeerMessageNotInterested();
+ void testCreatePeerMessageHave();
+ void testCreatePeerMessageBitfield();
+ void testCreatePeerMessageRequest();
+ void testCreatePeerMessagePiece();
+ void testCreatePeerMessageCancel();
+
+ void testCheckIntegrityHave();
+ void testCheckIntegrityBitfield();
+ void testCheckIntegrityRequest();
+};
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION( PeerMessageUtilTest );
+
+void setIntParam(char* dest, int param) {
+ int nParam = htonl(param);
+ memcpy(dest, &nParam, 4);
+}
+
+void createNLengthMessage(char* msg, int msgLen, int payloadLen, int id) {
+ memset(msg, 0, msgLen);
+ setIntParam(msg, payloadLen);
+ msg[4] = (char)id;
+}
+
+void PeerMessageUtilTest::testCreatePeerMessageKeepAlive() {
+ char msg[4];
+ memset(msg, 0, sizeof(msg));
+ PeerMessage* pm = PeerMessageUtil::createPeerMessage(NULL, 0);
+ CPPUNIT_ASSERT_EQUAL((int)PeerMessage::KEEP_ALIVE, pm->id);
+}
+
+void PeerMessageUtilTest::testCreatePeerMessageChoke() {
+ char msg[5];
+ createNLengthMessage(msg, sizeof(msg), 1, 0);
+ PeerMessage* pm = PeerMessageUtil::createPeerMessage(&msg[4], 1);
+ CPPUNIT_ASSERT_EQUAL((int)PeerMessage::CHOKE, pm->id);
+
+ try {
+ char msg[6];
+ createNLengthMessage(msg, sizeof(msg), 2, 0);
+ PeerMessageUtil::createPeerMessage(&msg[4], 2);
+ CPPUNIT_FAIL("exception must be throwed.");
+ } catch(...) {
+ }
+}
+
+void PeerMessageUtilTest::testCreatePeerMessageUnchoke() {
+ char msg[5];
+ createNLengthMessage(msg, sizeof(msg), 1, 1);
+ PeerMessage* pm = PeerMessageUtil::createPeerMessage(&msg[4], 1);
+ CPPUNIT_ASSERT_EQUAL((int)PeerMessage::UNCHOKE, pm->id);
+
+ try {
+ char msg[6];
+ createNLengthMessage(msg, sizeof(msg), 2, 1);
+ PeerMessageUtil::createPeerMessage(&msg[4], 2);
+ CPPUNIT_FAIL("exception must be throwed.");
+ } catch(...) {
+ }
+}
+
+void PeerMessageUtilTest::testCreatePeerMessageInterested() {
+ char msg[5];
+ createNLengthMessage(msg, sizeof(msg), 1, 2);
+ PeerMessage* pm = PeerMessageUtil::createPeerMessage(&msg[4], 1);
+ CPPUNIT_ASSERT_EQUAL((int)PeerMessage::INTERESTED, pm->id);
+
+ try {
+ char msg[6];
+ createNLengthMessage(msg, sizeof(msg), 2, 2);
+ PeerMessageUtil::createPeerMessage(&msg[4], 2);
+ CPPUNIT_FAIL("exception must be throwed.");
+ } catch(...) {
+ }
+}
+
+void PeerMessageUtilTest::testCreatePeerMessageNotInterested() {
+ char msg[5];
+ createNLengthMessage(msg, sizeof(msg), 1, 3);
+ PeerMessage* pm = PeerMessageUtil::createPeerMessage(&msg[4], 1);
+ CPPUNIT_ASSERT_EQUAL((int)PeerMessage::NOT_INTERESTED, pm->id);
+
+ try {
+ char msg[6];
+ createNLengthMessage(msg, sizeof(msg), 2, 3);
+ PeerMessageUtil::createPeerMessage(&msg[4], 2);
+ CPPUNIT_FAIL("exception must be throwed.");
+ } catch(...) {
+ }
+}
+
+void PeerMessageUtilTest::testCreatePeerMessageHave() {
+ char msg[9];
+ createNLengthMessage(msg, sizeof(msg), 5, 4);
+ setIntParam(&msg[5], 100);
+ PeerMessage* pm = PeerMessageUtil::createPeerMessage(&msg[4], 5);
+ CPPUNIT_ASSERT_EQUAL((int)PeerMessage::HAVE, pm->id);
+ CPPUNIT_ASSERT_EQUAL(100, pm->index);
+
+ try {
+ char msg[8];
+ createNLengthMessage(msg, sizeof(msg), 4, 4);
+ PeerMessageUtil::createPeerMessage(&msg[4], 4);
+ CPPUNIT_FAIL("exception must be throwed.");
+ } catch(...) {}
+
+ try {
+ char msg[5];
+ createNLengthMessage(msg, sizeof(msg), 1, 4);
+ PeerMessageUtil::createPeerMessage(&msg[4], 1);
+ CPPUNIT_FAIL("exception must be throwed.");
+ } catch(...) {}
+}
+
+void PeerMessageUtilTest::testCreatePeerMessageBitfield() {
+ int msgLen = 5+2;
+ char* msg = new char[msgLen];
+ createNLengthMessage(msg, msgLen, 3, 5);
+ PeerMessage* pm = PeerMessageUtil::createPeerMessage(&msg[4], 3);
+ CPPUNIT_ASSERT_EQUAL((int)PeerMessage::BITFIELD, pm->id);
+ CPPUNIT_ASSERT_EQUAL((unsigned char)0, pm->bitfield[0]);
+ CPPUNIT_ASSERT_EQUAL((unsigned char)0, pm->bitfield[1]);
+ CPPUNIT_ASSERT_EQUAL(2, pm->bitfieldLen);
+
+ try {
+ int msgLen = 5;
+ char* msg = new char[msgLen];
+ createNLengthMessage(msg, msgLen, 1, 5);
+ PeerMessageUtil::createPeerMessage(&msg[4], 1);
+ CPPUNIT_FAIL("exception must be throwed.");
+ } catch(...) {}
+}
+
+void PeerMessageUtilTest::testCreatePeerMessageRequest() {
+ char msg[17];
+ createNLengthMessage(msg, sizeof(msg), 13, 6);
+ setIntParam(&msg[5], 1);
+ setIntParam(&msg[9], 16*1024);
+ setIntParam(&msg[13], 16*1024-1);
+ PeerMessage* pm = PeerMessageUtil::createPeerMessage(&msg[4], 13);
+ CPPUNIT_ASSERT_EQUAL((int)PeerMessage::REQUEST, pm->id);
+ CPPUNIT_ASSERT_EQUAL(1, pm->index);
+ CPPUNIT_ASSERT_EQUAL(16*1024, pm->begin);
+ CPPUNIT_ASSERT_EQUAL(16*1024-1, pm->length);
+
+ try {
+ char msg[13];
+ createNLengthMessage(msg, sizeof(msg), 9, 6);
+ setIntParam(&msg[5], 1);
+ setIntParam(&msg[9], 16*1024);
+ PeerMessageUtil::createPeerMessage(&msg[4], 9);
+ CPPUNIT_FAIL("exception must be throwed.");
+ } catch(...) {}
+}
+
+void PeerMessageUtilTest::testCreatePeerMessagePiece() {
+ char msg[23];
+ createNLengthMessage(msg, sizeof(msg), 9+10, 7);
+ setIntParam(&msg[5], 1);
+ setIntParam(&msg[9], 16*1024);
+ PeerMessage* pm = PeerMessageUtil::createPeerMessage(&msg[4], 19);
+ CPPUNIT_ASSERT_EQUAL((int)PeerMessage::PIECE, pm->id);
+ CPPUNIT_ASSERT_EQUAL(1, pm->index);
+ CPPUNIT_ASSERT_EQUAL(16*1024, pm->begin);
+ CPPUNIT_ASSERT_EQUAL(10, pm->blockLen);
+ for(int i = 0; i < 10; i++) {
+ CPPUNIT_ASSERT_EQUAL((char)0, pm->block[i]);
+ }
+
+ try {
+ char msg[13];
+ createNLengthMessage(msg, sizeof(msg), 9, 7);
+ setIntParam(&msg[5], 1);
+ setIntParam(&msg[9], 16*1024);
+ PeerMessageUtil::createPeerMessage(&msg[4], 9);
+ CPPUNIT_FAIL("exception must be throwed.");
+ } catch(...) {}
+}
+
+void PeerMessageUtilTest::testCreatePeerMessageCancel() {
+ char msg[17];
+ createNLengthMessage(msg, sizeof(msg), 13, 8);
+ setIntParam(&msg[5], 1);
+ setIntParam(&msg[9], 16*1024);
+ setIntParam(&msg[13], 16*1024-1);
+ PeerMessage* pm = PeerMessageUtil::createPeerMessage(&msg[4], 13);
+ CPPUNIT_ASSERT_EQUAL((int)PeerMessage::CANCEL, pm->id);
+ CPPUNIT_ASSERT_EQUAL(1, pm->index);
+ CPPUNIT_ASSERT_EQUAL(16*1024, pm->begin);
+ CPPUNIT_ASSERT_EQUAL(16*1024-1, pm->length);
+
+ try {
+ char msg[13];
+ createNLengthMessage(msg, sizeof(msg), 9, 8);
+ setIntParam(&msg[5], 1);
+ setIntParam(&msg[9], 16*1024);
+ PeerMessageUtil::createPeerMessage(&msg[4], 9);
+ CPPUNIT_FAIL("exception must be throwed.");
+ } catch(...) {}
+}
+
+void PeerMessageUtilTest::testCheckIntegrityHave() {
+ PeerMessage* pm = new PeerMessage();
+ pm->id = PeerMessage::HAVE;
+ pm->index = 119;
+ try {
+ PeerMessageUtil::checkIntegrity(pm, 256*1024, 120, 256*1024*120);
+ } catch(Exception* ex) {
+ cerr << ex->getMsg() << endl;
+ CPPUNIT_FAIL("");
+ }
+
+ pm->index = 120;
+ try {
+ PeerMessageUtil::checkIntegrity(pm, 256*1024, 120, 256*1024*120);
+ CPPUNIT_FAIL("exception must be throwed.");
+ } catch(...) {}
+}
+
+
+void PeerMessageUtilTest::testCheckIntegrityBitfield() {
+ PeerMessage* pm = new PeerMessage();
+ pm->id = PeerMessage::BITFIELD;
+ pm->bitfieldLen = 15;
+ pm->bitfield = new unsigned char[pm->bitfieldLen];
+ memset(pm->bitfield, 1, pm->bitfieldLen);
+ try {
+ PeerMessageUtil::checkIntegrity(pm, 256*1024, 120, 256*1024*120);
+ } catch(Exception* ex) {
+ cerr << ex->getMsg() << endl;
+ CPPUNIT_FAIL("");
+ }
+
+ pm->bitfieldLen = 16;
+ pm->bitfield = new unsigned char[pm->bitfieldLen];
+ memset(pm->bitfield, 1, pm->bitfieldLen);
+ try {
+ PeerMessageUtil::checkIntegrity(pm, 256*1024, 120, 256*1024*120);
+ CPPUNIT_FAIL("exception must be throwed.");
+ } catch(Exception* ex) {
+ }
+
+ pm->bitfieldLen = 14;
+ pm->bitfield = new unsigned char[pm->bitfieldLen];
+ memset(pm->bitfield, 1, pm->bitfieldLen);
+ try {
+ PeerMessageUtil::checkIntegrity(pm, 256*1024, 120, 256*1024*120);
+ CPPUNIT_FAIL("exception must be throwed.");
+ } catch(Exception* ex) {
+ }
+
+ pm->bitfieldLen = 15;
+ pm->bitfield = new unsigned char[pm->bitfieldLen];
+ memset(pm->bitfield, 1, pm->bitfieldLen);
+ pm->bitfield[pm->bitfieldLen-1] &= 0xfe;
+ try {
+ PeerMessageUtil::checkIntegrity(pm, 256*1024, 119, 256*1024*120);
+ } catch(Exception* ex) {
+ cerr << ex->getMsg() << endl;
+ CPPUNIT_FAIL("");
+ }
+
+ pm->bitfieldLen = 15;
+ pm->bitfield = new unsigned char[pm->bitfieldLen];
+ memset(pm->bitfield, 1, pm->bitfieldLen);
+ try {
+ PeerMessageUtil::checkIntegrity(pm, 256*1024, 119, 256*1024*120);
+ CPPUNIT_FAIL("exception must be throwed.");
+ } catch(Exception* ex) {
+ }
+}
+
+void PeerMessageUtilTest::testCheckIntegrityRequest() {
+ PeerMessage* pm = new PeerMessage();
+ pm->id = PeerMessage::REQUEST;
+ pm->index = 119;
+ pm->begin = 0;
+ pm->length = 16*1024;
+
+ try {
+ PeerMessageUtil::checkIntegrity(pm, 256*1024, 120, 256*1024*120);
+ } catch(Exception* ex) {
+ cerr << ex->getMsg() << endl;
+ CPPUNIT_FAIL("");
+ }
+
+ pm->begin = 256*1024;
+ pm->length = 16*1024;
+ try {
+ PeerMessageUtil::checkIntegrity(pm, 256*1024, 120, 256*1024*120);
+ CPPUNIT_FAIL("exception must be throwed.");
+ } catch(Exception* ex) {}
+
+ pm->begin = 0;
+ pm->length = 256*1024+1;
+ try {
+ PeerMessageUtil::checkIntegrity(pm, 256*1024, 120, 256*1024*120);
+ CPPUNIT_FAIL("exception must be throwed.");
+ } catch(Exception* ex) {}
+
+ pm->begin = 0;
+ pm->length = 256*1024;
+ try {
+ PeerMessageUtil::checkIntegrity(pm, 256*1024, 120, 256*1024*120);
+ } catch(Exception* ex) {
+ cerr << ex->getMsg() << endl;
+ CPPUNIT_FAIL("");
+ }
+
+ pm->begin = 0;
+ pm->length = 256*1024;
+ try {
+ PeerMessageUtil::checkIntegrity(pm, 256*1024, 120, 256*1024*120-1);
+ CPPUNIT_FAIL("exception must be throwed.");
+ } catch(Exception* ex) {}
+}
diff --git a/test/ShaVisitorTest.cc b/test/ShaVisitorTest.cc
new file mode 100644
index 00000000..ce32b207
--- /dev/null
+++ b/test/ShaVisitorTest.cc
@@ -0,0 +1,60 @@
+#include "ShaVisitor.h"
+#include "MetaFileUtil.h"
+#include <string>
+#include <cppunit/extensions/HelperMacros.h>
+
+using namespace std;
+
+class ShaVisitorTest:public CppUnit::TestFixture {
+
+ CPPUNIT_TEST_SUITE(ShaVisitorTest);
+ CPPUNIT_TEST(testVisit);
+ CPPUNIT_TEST(testVisitCompound);
+ CPPUNIT_TEST_SUITE_END();
+private:
+
+public:
+ void setUp() {
+ }
+
+ void testVisit();
+ void testVisitCompound();
+};
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION( ShaVisitorTest );
+
+string hexHash(unsigned char* md, int len) {
+ char* temp = new char[len*2+1];
+ for(int i = 0; i < len; i++) {
+ sprintf(temp+i*2, "%02x", md[i]);
+ }
+ temp[len*2] = '\0';
+ string h(temp);
+ delete [] temp;
+ return h;
+}
+
+void ShaVisitorTest::testVisit() {
+ ShaVisitor v;
+ Data d("test", 4);
+ d.accept(&v);
+ unsigned char md[EVP_MAX_MD_SIZE];
+ int len = 0;
+ v.getHash(md, len);
+ string hashHex = hexHash(md, len);
+ CPPUNIT_ASSERT_EQUAL(string("20482dadd856f5ac908848f731d9235d2891c41e"),
+ hashHex);
+}
+
+void ShaVisitorTest::testVisitCompound() {
+ ShaVisitor v;
+ MetaEntry* e = MetaFileUtil::parseMetaFile("test.torrent");
+ e->accept(&v);
+ unsigned char md[EVP_MAX_MD_SIZE];
+ int len = 0;
+ v.getHash(md, len);
+ string hashHex = hexHash(md, len);
+ CPPUNIT_ASSERT_EQUAL(string("9d33ba293924df85f6067a81c65b484de04e8efd"),
+ hashHex);
+}
diff --git a/test/TorrentManTest.cc b/test/TorrentManTest.cc
new file mode 100644
index 00000000..41419bf0
--- /dev/null
+++ b/test/TorrentManTest.cc
@@ -0,0 +1,188 @@
+#include "TorrentMan.h"
+#include <string>
+#include <cppunit/extensions/HelperMacros.h>
+
+using namespace std;
+
+class TorrentManTest:public CppUnit::TestFixture {
+
+ CPPUNIT_TEST_SUITE(TorrentManTest);
+ CPPUNIT_TEST(testUpdatePeers);
+ //CPPUNIT_TEST(testUpdatePeer);
+ CPPUNIT_TEST(testGetPeer);
+ CPPUNIT_TEST(testGetMissingPiece);
+ CPPUNIT_TEST(testCancelPiece);
+ CPPUNIT_TEST(testAddPeer);
+ CPPUNIT_TEST_SUITE_END();
+private:
+
+public:
+ void setUp() {
+ }
+
+ void testUpdatePeers();
+ //void testUpdatePeer();
+ void testGetPeer();
+ void testGetMissingPiece();
+ void testCancelPiece();
+ void testAddPeer();
+};
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION( TorrentManTest );
+
+Peers createPeers() {
+ Peers peers;
+ Peer* peer1 = new Peer("192.168.0.1", 6881);
+ peer1->entryId = 1;
+ Peer* peer2 = new Peer("192.168.0.2", 6881);
+ peer2->entryId = 2;
+ Peer* peer3 = new Peer("192.168.0.3", 6881);
+ peer3->entryId = 3;
+ peers.push_back(peer1);
+ peers.push_back(peer2);
+ peers.push_back(peer3);
+ return peers;
+}
+
+void TorrentManTest::testUpdatePeers() {
+ TorrentMan tm;
+ Peers peers = createPeers();
+ tm.updatePeers(peers);
+ const Peers& peersGot = tm.getPeers();
+ Peers::const_iterator itr = peersGot.begin();
+ CPPUNIT_ASSERT_EQUAL(string("192.168.0.1"), (*itr)->ipaddr);
+ itr++;
+ CPPUNIT_ASSERT_EQUAL(string("192.168.0.2"), (*itr)->ipaddr);
+ itr++;
+ CPPUNIT_ASSERT_EQUAL(string("192.168.0.3"), (*itr)->ipaddr);
+ itr++;
+}
+
+/*
+void TorrentManTest::testUpdatePeer() {
+ TorrentMan tm;
+ Peers peers = createPeers();
+ tm.updatePeers(peers);
+ Peer* peer = tm.getPeer(1);
+ peer->amChocking = true;
+ peer->amInterested = true;
+ tm.updatePeer(peer);
+
+ Peers::const_iterator itr = tm.getPeers().begin();
+ CPPUNIT_ASSERT_EQUAL(3, (int)tm.getPeers().size());
+ CPPUNIT_ASSERT_EQUAL(string("192.168.0.1"), itr->ipaddr);
+ CPPUNIT_ASSERT_EQUAL(true, itr->amChocking);
+ CPPUNIT_ASSERT_EQUAL(true, itr->amInterested);
+ CPPUNIT_ASSERT_EQUAL(1, itr->cuid);
+ itr++;
+ CPPUNIT_ASSERT_EQUAL(string("192.168.0.2"), itr->ipaddr);
+ CPPUNIT_ASSERT_EQUAL(false, itr->amChocking);
+ CPPUNIT_ASSERT_EQUAL(false, itr->amInterested);
+ CPPUNIT_ASSERT_EQUAL(0, itr->cuid);
+ itr++;
+ CPPUNIT_ASSERT_EQUAL(string("192.168.0.3"), itr->ipaddr);
+ CPPUNIT_ASSERT_EQUAL(false, itr->amChocking);
+ CPPUNIT_ASSERT_EQUAL(false, itr->amInterested);
+ CPPUNIT_ASSERT_EQUAL(0, itr->cuid);
+ itr++;
+}
+*/
+
+void TorrentManTest::testGetPeer() {
+ TorrentMan tm;
+ Peers peers = createPeers();
+ tm.updatePeers(peers);
+ CPPUNIT_ASSERT(tm.getPeer(1) != Peer::nullPeer);
+ CPPUNIT_ASSERT(tm.getPeer(2) != Peer::nullPeer);
+ CPPUNIT_ASSERT(tm.getPeer(3) != Peer::nullPeer);
+ CPPUNIT_ASSERT(tm.getPeer(4) == Peer::nullPeer);
+}
+
+void TorrentManTest::testGetMissingPiece() {
+ TorrentMan tm;
+ tm.pieceLength = 512*1024;
+ tm.pieces = 10;
+ tm.totalSize = 5242870;
+ tm.initBitfield();
+
+ unsigned char peerBitfield[2] = { 0xff, 0xff };
+ Piece piece1 = tm.getMissingPiece(peerBitfield, 2);
+ CPPUNIT_ASSERT_EQUAL(0, piece1.index);
+ CPPUNIT_ASSERT_EQUAL(512*1024, piece1.length);
+
+ Piece piece2 = tm.getMissingPiece(peerBitfield, 2);
+ CPPUNIT_ASSERT_EQUAL(1, piece2.index);
+ CPPUNIT_ASSERT_EQUAL(512*1024, piece2.length);
+
+ tm.completePiece(piece1);
+
+ int len = tm.getBitfieldLength();
+ const unsigned char* bitfield = tm.getBitfield();
+ CPPUNIT_ASSERT_EQUAL(2, len);
+ CPPUNIT_ASSERT(bitfield[0]&(1 << 7));
+ for(int i = 0; i < 7; i++) {
+ CPPUNIT_ASSERT(!(bitfield[0]&(1 << i)));
+ }
+
+ tm.completePiece(piece2);
+ bitfield = tm.getBitfield();
+ CPPUNIT_ASSERT_EQUAL(2, len);
+ CPPUNIT_ASSERT(bitfield[0]&(1 << 7));
+ CPPUNIT_ASSERT(bitfield[0]&(1 << 6));
+ for(int i = 0; i < 6; i++) {
+ CPPUNIT_ASSERT(!(bitfield[0]&(1 << i)));
+ }
+
+ for(int i = 0; i < 8; i++) {
+ CPPUNIT_ASSERT(!IS_NULL_PIECE(tm.getMissingPiece(peerBitfield, 2)));
+ }
+ CPPUNIT_ASSERT(IS_NULL_PIECE(tm.getMissingPiece(peerBitfield, 2)));
+}
+
+void TorrentManTest::testCancelPiece() {
+ TorrentMan tm;
+ tm.pieceLength = 512*1024;
+ tm.pieces = 10;
+ tm.totalSize = 5242870;
+ tm.initBitfield();
+
+ unsigned char peerBitfield[2] = { 0xff, 0xff };
+ Piece piece = tm.getMissingPiece(peerBitfield, 2);
+ CPPUNIT_ASSERT_EQUAL(0, piece.index);
+ CPPUNIT_ASSERT_EQUAL(512*1024, piece.length);
+
+ tm.cancelPiece(piece);
+ int len = tm.getBitfieldLength();
+ const unsigned char* bitfield = tm.getBitfield();
+ for(int i = 0; i < 8; i++) {
+ CPPUNIT_ASSERT(!(bitfield[0]&(1 << i)));
+ }
+}
+
+void TorrentManTest::testAddPeer() {
+ TorrentMan tm;
+ Peers peers = createPeers();
+ tm.updatePeers(peers);
+
+ // try to add already added peer
+ Peer* dupPeer = new Peer("192.168.0.2", 6881);
+ CPPUNIT_ASSERT(!tm.addPeer(dupPeer));
+ CPPUNIT_ASSERT_EQUAL(3, (int)tm.getPeers().size());
+
+ // duplicate flag on
+ CPPUNIT_ASSERT(tm.addPeer(dupPeer, true));
+ CPPUNIT_ASSERT_EQUAL(4, (int)tm.getPeers().size());
+
+ // cannot add error peer even though duplicte flag turns on
+ dupPeer->error = 1;
+ Peer* dupPeer2 = new Peer("192.168.0.2", 6881);
+ CPPUNIT_ASSERT(!tm.addPeer(dupPeer2, true));
+ CPPUNIT_ASSERT_EQUAL(4, (int)tm.getPeers().size());
+
+ // try to add new peer
+ Peer* newPeer = new Peer("10.1.0.1", 6881);
+ CPPUNIT_ASSERT(tm.addPeer(newPeer));
+ CPPUNIT_ASSERT_EQUAL(5, (int)tm.getPeers().size());
+
+}
diff --git a/test/test.torrent b/test/test.torrent
new file mode 100644
index 00000000..d7a4ecc1
--- /dev/null
+++ b/test/test.torrent
@@ -0,0 +1 @@
+d8:announce36:http://aria.rednoah.com/announce.php7:comment17:REDNOAH.COM RULES13:creation datei1123456789e4:infod5:filesld6:lengthi256000e4:pathl5:aria23:src6:aria2ceed6:lengthi128900e4:pathl19:aria2-0.2.2.tar.bz2eee4:name10:aria2-test12:piece lengthi128e6:pieces60:AAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCee \ No newline at end of file