1 /***************************************************************************
3 * Copyright (C) 2006 David Brodsky *
5 * This program is free software; you can redistribute it and/or *
6 * modify it under the terms of the GNU General Public License as *
7 * published by the Free Software Foundation and appearing *
8 * in the file LICENSE.GPL included in the packaging of this file. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
13 * General Public License for more details. *
15 ***************************************************************************/
21 #include <tairon/core/config.h>
22 #include <tairon/core/exceptions.h>
23 #include <tairon/core/log.h>
24 #include <tairon/core/tinyxml.h>
26 #include "torrentmanager.h"
28 #include "core/bencode.h"
29 #include "torrentclient.h"
31 #define TAIRENT_VERSION "0.1"
39 TorrentManager
*TorrentManager::torrentManager
= 0;
41 /* {{{ TorrentManager::TorrentManager() */
42 TorrentManager::TorrentManager()
45 throw Tairon::Core::SingletonException("Cannot make another instance of Tairent::Main::TorrentManager");
50 torrentManager
= this;
54 /* {{{ TorrentManager::~TorrentManager() */
55 TorrentManager::~TorrentManager()
61 /* {{{ TorrentManager::destroy() */
62 void TorrentManager::destroy()
64 for (std::map
<String
, TorrentStruct
*>::const_iterator it
= torrents
.begin(); it
!= torrents
.end(); ++it
) {
65 if (it
->second
->client
)
66 delete it
->second
->client
;
67 if (it
->second
->metaInfo
)
68 delete it
->second
->metaInfo
;
75 /* {{{ TorrentManager::getClient(const String &) */
76 TorrentClient
*TorrentManager::getClient(const String
&infoHash
)
78 if (torrents
.count(infoHash
)) {
79 TorrentStruct
*t
= torrents
[infoHash
];
83 // TODO: create client
86 return 0; // no client found
90 /* {{{ TorrentManager::getClientID() */
91 const String
&TorrentManager::getClientID()
97 /* {{{ TorrentManager::hexToBin(char) */
98 char TorrentManager::hexToBin(char c
)
100 if ((c
>= '0') && (c
<= '9'))
106 /* {{{ TorrentManager::hexToBin(const String &) */
107 String
TorrentManager::hexToBin(const String
&data
)
110 ret
.resize(data
.length() / 2);
113 const char *d
= data
;
115 ret
[i
++] = (hexToBin(*d
) << 4) | (hexToBin(*(d
+ 1)));
123 /* {{{ TorrentManager::loadMetaInfo(const String &) */
124 Tairent::Core::BEncode
*TorrentManager::loadMetaInfo(const String
&filename
)
126 std::ifstream
f(filename
, std::ios_base::in
);
128 WARNING((const char *) String("Cannot load informations from " + filename
));
132 Tairent::Core::BEncode
*ret
= new Tairent::Core::BEncode();
135 } catch (const Tairent::Core::BEncodeException
&e
) {
136 WARNING((const char *) String("Cannot load metainfo from " + filename
+ ": " + (const String
&) e
));
145 /* {{{ TorrentManager::loadTorrent(TiXmlNode *) */
146 void TorrentManager::loadTorrent(TiXmlNode
*t
)
148 TiXmlElement
*element
= t
->ToElement();
149 const char *data
= element
->Attribute("file");
153 INFO((const char *) String(String("Loading informations about ") + data
));
155 TorrentStruct
*torrent
= new TorrentStruct
;
158 torrent
->torrentFile
= data
;
160 data
= element
->Attribute("complete");
161 if (data
&& (data
[0] == '1'))
162 torrent
->complete
= true;
164 torrent
->complete
= false;
166 data
= element
->Attribute("hash");
168 torrent
->metaInfo
= 0;
169 torrents
[hexToBin(data
)] = torrent
;
171 torrent
->metaInfo
= loadMetaInfo(torrent
->torrentFile
);
172 if (!torrent
->metaInfo
)
174 String hash
= (*torrent
->metaInfo
)["info"].computeSHA1();
175 torrents
[hash
] = torrent
;
180 /* {{{ TorrentManager::loadTorrents() */
181 void TorrentManager::loadTorrents()
183 TiXmlDocument document
;
185 if (!document
.LoadFile((*Tairon::Core::Config::self())["torrents-directory"] + "/torrents.xml"))
188 TiXmlElement
*root
= document
.RootElement();
192 if (root
->ValueStr() != "torrents") // invalid file
195 for (TiXmlNode
*node
= root
->FirstChild(); node
; node
= node
->NextSibling()) {
196 if (node
->Type() != TiXmlNode::ELEMENT
)
198 if (node
->ValueStr() == "torrent")
204 /* {{{ TorrentManager::makeClientID() */
205 void TorrentManager::makeClientID()
209 clientID
= "TA-" TAIRENT_VERSION
"-";
210 size_t len
= clientID
.length();
213 std::ifstream
f("/dev/urandom", std::ios_base::in
);
215 for (size_t i
= len
; i
< 20; ++i
)
216 clientID
[i
] = (char) f
.get();
218 } else { // cannot open /dev/urandom? fall back to standard random
220 for (size_t i
= len
; i
< 20; ++i
)
221 clientID
[i
] = random() % 256;
226 /* {{{ TorrentManager::startTorrents() */
227 void TorrentManager::startTorrents()
229 for (std::map
<String
, TorrentStruct
*>::const_iterator it
= torrents
.begin(); it
!= torrents
.end(); ++it
) {
230 TorrentStruct
*t
= it
->second
;
235 t
->metaInfo
= loadMetaInfo(t
->torrentFile
);
237 if (!t
->metaInfo
) { // metainfo loading failed
238 WARNING((const char *) String("Cannot start torrent " + t
->torrentFile
));
242 t
->client
= new TorrentClient(t
, it
->first
);
247 /* {{{ TorrentManager::stopTorrents() */
248 void TorrentManager::stopTorrents()
250 for (std::map
<String
, TorrentStruct
*>::const_iterator it
= torrents
.begin(); it
!= torrents
.end(); ++it
)
251 it
->second
->client
->stop();
257 }; // namespace Tairent
259 // vim: ai sw=4 ts=4 noet fdm=marker