00001 /** 00002 * Copyright (C) 2004-2005 Alo Sarv <madcat_@users.sourceforge.net> 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation; either version 2 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software 00016 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 */ 00018 00019 /** @file creditsdb.h Interface for CreditsDb and ClientCredits classes */ 00020 00021 #ifndef __CREDITSDB_H__ 00022 #define __CREDITSDB_H__ 00023 00024 #include <hn/object.h> 00025 #include <hn/hash.h> 00026 #include <math.h> 00027 #include "ed2ktypes.h" 00028 #include "publickey.h" 00029 00030 /** 00031 * Credits object represent one single client's credits entry. 00032 */ 00033 class Credits { 00034 public: 00035 //! Construct by publickey and hash 00036 Credits(PublicKey key, const Hash<MD4Hash> &h); 00037 00038 float getScore() const { 00039 if (m_downloaded < 1024*1024) { 00040 return 1.0; 00041 } 00042 float score1 = m_uploaded?m_downloaded*2/m_uploaded :10; 00043 float score2 = sqrt(m_downloaded/1024.0*1024.0) + 2; 00044 return score1 > score2 ? score1 : score2; 00045 } 00046 00047 uint64_t getUploaded() const { return m_uploaded; } 00048 uint64_t getDownloaded() const { return m_downloaded; } 00049 uint32_t getLastSeen() const { return m_lastSeen; } 00050 Hash<MD4Hash> getHash() const { return m_hash; } 00051 PublicKey getPubKey() const { return m_pubKey; } 00052 00053 void addUploaded(uint32_t amount) { m_uploaded += amount; } 00054 void addDownloaded(uint32_t amount) { m_downloaded += amount; } 00055 void setLastSeen(uint32_t time) { m_lastSeen = time; } 00056 private: 00057 friend class CreditsDb; 00058 00059 /** 00060 * Construct and load from stream. This is used only by 00061 * CreditsDb, and is thus private. 00062 * 00063 * @param i Input stream to read data from 00064 * @param ver Version of stream (pubkey or not) 00065 */ 00066 Credits(std::istream &i, uint8_t ver); 00067 00068 Credits(); //!< Forbidden 00069 ~Credits(); //!< Allowed by CreditsDb 00070 Credits(const Credits&); //!< Forbidden 00071 const Credits& operator=(const Credits&); //! Forbidden 00072 00073 //! @name Data 00074 //@{ 00075 Hash<MD4Hash> m_hash; //!< Userhash 00076 uint64_t m_uploaded; //!< Sent to him/her 00077 uint64_t m_downloaded; //!< Received from him/her 00078 uint32_t m_lastSeen; //!< Time last seen 00079 PublicKey m_pubKey; //!< public key 00080 //@} 00081 00082 //! Output operator to streams, used for writing clients.met 00083 friend std::ostream& operator<<(std::ostream &o, const Credits &c); 00084 }; 00085 00086 namespace Detail { 00087 struct CreditsList; 00088 } 00089 00090 /** 00091 * CreditsDb class stores and maintains ClientCredits type objects, which 00092 * represent eDonkey2000 client credits. Actually, what this means is we 00093 * store the clients userhash and public key, and keep track of how much we 00094 * have sent data to the client, and how much we have received back. All of 00095 * this forms the base for eMule extended protocol feature, which rewards 00096 * uploaders based on their credits. More on that in UploadQueue-related 00097 * classes. Note that not all clients connecting to eDonkey2000 network support 00098 * credits, and thus only clients giving back credits should be rewarded here. 00099 * At the point of this writing (15/10/2004), only eMule-derived clients, plus 00100 * ShareAza fully support this system as far as I know. 00101 * 00102 * CreditsDb stores its contents at config/ed2k/clients.met between sessions. 00103 * The file format conforms to eMule's respective file format. 00104 * 00105 * This class is a Singleton, the only instance of this class may be retrieved 00106 * through instance() member function. 00107 */ 00108 class CreditsDb { 00109 public: 00110 //! Singleton, lazy instanciating 00111 static CreditsDb& instance() { 00112 static CreditsDb *cdb = new CreditsDb(); 00113 return *cdb; 00114 } 00115 00116 /** 00117 * Initializes public/private RSA keypair either by loading it from 00118 * file, or creating new one if needed. 00119 */ 00120 void initCrypting(); 00121 00122 /** 00123 * Load the contents from file, adding all entries found there to list 00124 * 00125 * @param file File to read data from 00126 * 00127 * \throws std::runtime_error if parsing fails 00128 */ 00129 void load(const std::string &file); 00130 00131 /** 00132 * Save the contents to file. 00133 * 00134 * @param file File to write to 00135 */ 00136 void save(const std::string &file) const; 00137 00138 /** 00139 * @returns Own public key 00140 */ 00141 PublicKey getPublicKey() const { return m_pubKey; } 00142 00143 /** 00144 * Find credits, looking with PublicKey. 00145 * 00146 * @param key Client's PublicKey to search for 00147 * @return Pointer to Credits object corresponding to @param key, or 00148 * 0 if not found. 00149 */ 00150 Credits* find(const PublicKey &key) const; 00151 00152 /** 00153 * Find credits, looking with userhash. 00154 * 00155 * @param hash Client's userhash 00156 * @return Pointer to Credits object corresponding to @param hash, 00157 * or 0 if not found. 00158 * 00159 * \note Usage of this function is discouraged, due to hash-stealers. 00160 */ 00161 Credits* find(const Hash<MD4Hash> &hash) const; 00162 00163 /** 00164 * Create credits entry for specified publickey/hash 00165 */ 00166 Credits* create(PublicKey key, const Hash<MD4Hash> &hash); 00167 00168 /** 00169 * Creates a signature to be sent to client owning target credits. 00170 * 00171 * @param key Remote client's public key 00172 * @param callenge Challenge value 00173 * @param ipType Type of IP (if any) to include 00174 * @param ip The ip to be included (if any) 00175 * @return Signature to be sent back to client 00176 */ 00177 static std::string createSignature( 00178 PublicKey key, uint32_t challenge, IpType ipType, uint32_t ip 00179 ); 00180 00181 /** 00182 * Attempts to verify signature against public key stored here. 00183 * 00184 * @param key Remote client's public key 00185 * @param challenge Challenge value sent to this client previously 00186 * @param sign The signature the remote client sent back 00187 * @param ipType Type of IP included in the signature (if any) 00188 * @param ip IP address included in the signature (if any) 00189 * @return True if verification succeeds, false otherwise 00190 */ 00191 static bool verifySignature( 00192 PublicKey key, uint32_t challenge, 00193 const std::string &sign, IpType ipType, uint32_t ip 00194 ); 00195 private: 00196 CreditsDb(); //!< Singleton 00197 ~CreditsDb(); //!< Singleton 00198 CreditsDb(const CreditsDb&); //!< No copying allowed 00199 const CreditsDb& operator=(const CreditsDb&); //!< No copying allowed 00200 00201 /** 00202 * Loads private RSA key from file, and calculates public RSA key from 00203 * it. 00204 * 00205 * @param where File to read private key from. 00206 */ 00207 void loadCryptKey(const std::string &where); 00208 00209 /** 00210 * Creates new public/private RSA keypair, and saves it to file. 00211 * 00212 * @param where File to write private key to. 00213 */ 00214 void createCryptKey(const std::string &where); 00215 00216 //! Public RSA key 00217 PublicKey m_pubKey; 00218 00219 boost::scoped_ptr<Detail::CreditsList> m_list; 00220 }; 00221 00222 #endif