packets.h

Go to the documentation of this file.
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 #ifndef __PACKETS_H__
00020 #define __PACKETS_H__
00021 
00022 /**
00023  * @file packets.h
00024  * This is an implementation header for ED2K protocol parser. This file should
00025  * never be included directly from user code - instead include "parser.h".
00026  *
00027  * Declares all supported packet objects, both incoming and outgoing, in
00028  * ED2KPacket namespace to avoid name clashes.
00029  *
00030  * Implementation note: The packet objects, implemented in packets.cpp, should
00031  * be as smart as possible and require as few usage arguments as possible. This
00032  * is done to minimize the usage complexity of these packet objects. Only
00033  * arguments to constructors should be those that we cannot possibly detect
00034  * ourselves during packet generation. The side-effect of this is that the
00035  * implementation file will need to include a large amount of ed2k module
00036  * headers, however the usage simplicity is well worth it.
00037  */
00038 
00039 #include <hn/osdep.h>          // For types
00040 #include <hn/ipv4addr.h>       // For ipv4address
00041 #include <hn/hash.h>           // For Hash<MD4Hash>
00042 #include <hn/range.h>          // For Range32
00043 #include "opcodes.h"           // For opcodes
00044 #include "ed2kfile.h"          // For ED2KFile and ED2KFile::Rating
00045 #include "ed2ksearch.h"        // For ED2KSearchResult
00046 #include "ed2ktypes.h"         // For ED2KHashSet
00047 #include "publickey.h"         // for PublicKey
00048 
00049 #include <boost/tuple/tuple.hpp>
00050 
00051 /**
00052  * Client software
00053  */
00054 enum ED2K_ClientSoftware {
00055         CS_EMULE         = 0x00,  //!< Official eMule
00056         CS_CDONKEY       = 0x01,  //!< CDonkey
00057         CS_LXMULE        = 0x02,  //!< lmule, xmule
00058         CS_AMULE         = 0x03,  //!< amule
00059         CS_SHAREAZA      = 0x04,  //!< shareaza
00060         CS_EMULEPLUS     = 0x05,  //!< emuleplus
00061         CS_HYDRANODE     = 0x06,  //!< hydranode
00062         CS_MLDONKEY_NEW2 = 0x0a,  //!< second new mldonkey
00063         CS_LPHANT        = 0x14,  //!< lphant
00064         CS_HYBRID        = 0x3c,  //!< eDonkey2000 Hybrid
00065         CS_DONKEY        = 0x3d,  //!< eDonkey2000
00066         CS_MLDONKEY      = 0x3e,  //!< original mldonkey
00067         CS_OLDEMULE      = 0x3f,  //!< old eMule
00068         CS_UNKNOWN       = 0x36,  //!< unknown
00069         CS_MLDONKEY_NEW  = 0x98   //!< first new mldonkey
00070 };
00071 
00072 //! Versions
00073 enum ED2K_Versions {
00074         VER_EDONKEY = 0x3c,
00075         VER_OWN = (
00076                 (CS_HYDRANODE << 24) | (APPVER_MAJOR << 17) |
00077                 (APPVER_MINOR << 10) | (APPVER_PATCH << 7)
00078         )
00079 };
00080 
00081 /**
00082  * ED2KPacket namespace contains all packet objects supported by the parser.
00083  */
00084 namespace ED2KPacket {
00085 
00086 extern uint64_t getOverheadUp();
00087 extern uint64_t getOverheadDn();
00088 extern void addOverheadDn(uint32_t amount);
00089 
00090 //! Exception class, thrown when invalid packets are found during parsing.
00091 class InvalidPacket : public std::runtime_error {
00092 public:
00093         InvalidPacket(const std::string &what);
00094 };
00095 
00096 /**
00097  * Abstract base Packet class defines a virtual destructor, and few convenience
00098  * methods for usage by derived classes. This class is never used directly,
00099  * instead one of the concrete derived classes are used.
00100  */
00101 class Packet {
00102 protected:
00103         /**
00104          * The only allowed constructor.
00105          *
00106          * @param proto       Protocol based on which to create the packet.
00107          *                    currently supports PR_ED2K, PR_EMULE and PR_ZLIB
00108          */
00109         Packet(uint8_t proto = PR_ED2K);
00110 
00111         /**
00112          * Pure virtual destructor.
00113          */
00114         virtual ~Packet() = 0;
00115 
00116         //! Keeps the protocol opcode passed to the constructor for later
00117         //! outputting (see makePacket method).
00118         uint8_t m_proto;
00119 
00120         /**
00121          * Makes packet, finalizing the packet generation. This function
00122          * writes the packet header, and (optionally) compresses the packet
00123          * data if m_proto == PR_ZLIB
00124          *
00125          * @param data     Data to make packet of. Assumes data[0] is opcode
00126          * @param hexDump  If set to true, the packet data is printed to stdout
00127          * @return         Packet ready for sending to target
00128          */
00129         std::string makePacket(const std::string &data, bool hexDump = false);
00130 };
00131 
00132 
00133                         /***********************/
00134                         /*  Client <-> Server  */
00135                         /***********************/
00136 
00137 /**
00138  * LoginRequest packet is sent to server after establishing the connection to
00139  * let the server know we are there.
00140  *
00141  * Usage: Client -> Server
00142  */
00143 class LoginRequest : public Packet {
00144 public:
00145         LoginRequest(uint8_t proto = PR_ED2K);
00146         operator std::string();
00147 };
00148 
00149 /**
00150  * ServerMessage is a free-form string message sent by servers after successful
00151  * login. This is a kind of MOTD from servers. Can include newlines and be
00152  * of arbitary length (up to numeric_limits<uin16_t>)
00153  *
00154  * Usage: Server -> Client
00155  */
00156 class ServerMessage : public Packet {
00157 public:
00158         ServerMessage(std::istream &i);
00159 
00160         std::string getMsg() const { return m_msg; }
00161 private:
00162         std::string m_msg;
00163 };
00164 
00165 /**
00166  * ServerStatus is a packet sent by servers after establishing a connection,
00167  * containing number of users and files currently on the server.
00168  *
00169  * Usage: Server -> Client
00170  */
00171 class ServerStatus : public Packet {
00172 public:
00173         ServerStatus(std::istream &i);
00174 
00175         uint32_t getUsers() const { return m_users; }
00176         uint32_t getFiles() const { return m_files; }
00177 private:
00178         uint32_t m_users;
00179         uint32_t m_files;
00180 };
00181 
00182 /**
00183  * IdChange packet is sent by servers after establishing a connection with the
00184  * server to notify the client of their new ID. In eDonkey2000 network, ID's
00185  * below 0x00ffffff are considered "low-id" and penalized. The ID is actually
00186  * the ip address of the client, in network byte order, which the server detects
00187  * by making a client<->client connection to our listening socket. If the server
00188  * is unable to connect to our listening socket, it sends us lowID message and
00189  * assigns us a low (< 0x00ffffff) ID.
00190  *
00191  * New lugdunum (16.44+) servers also send additional u32 containing supported
00192  * features bitfield.
00193  *
00194  * Usage: Server -> Client
00195  */
00196 class IdChange : public Packet {
00197 public:
00198         IdChange(std::istream &i);
00199 
00200         uint32_t getId()    const { return m_id; }
00201         uint32_t getFlags() const { return m_flags; }
00202 private:
00203         uint32_t m_id;
00204         uint32_t m_flags; //!< Lugdunum 16.44+ servers send supported features
00205 };
00206 
00207 /**
00208  * Sent to server, this requests the server to send us its current known servers
00209  * list.
00210  *
00211  * Usage:  Client -> Server
00212  */
00213 class GetServerList : public Packet {
00214 public:
00215         GetServerList(uint8_t proto = PR_ED2K);
00216         operator std::string();
00217 };
00218 
00219 /**
00220  * ServerIdent is a response from server to GetServerList packet, and includes
00221  * information about the server.
00222  *
00223  * Usage:  Server -> Client
00224  */
00225 class ServerIdent : public Packet {
00226 public:
00227         ServerIdent(std::istream &i);
00228 
00229         Hash<MD4Hash> getHash() const { return m_hash; }
00230         IPV4Address   getAddr() const { return m_addr; }
00231         std::string   getName() const { return m_name; }
00232         std::string   getDesc() const { return m_desc; }
00233 private:
00234         Hash<MD4Hash> m_hash;               //!< Server hash
00235         IPV4Address m_addr;                 //!< Server ip address/port
00236         std::string m_name;                 //!< Server name
00237         std::string m_desc;                 //!< Server description
00238 };
00239 
00240 /**
00241  * ServerList packet is sent by servers in response to GetServerList packet,
00242  * and contains a list of known servers to the source.
00243  *
00244  * Usage:  Server -> Client
00245  */
00246 class ServerList : public Packet {
00247 public:
00248         ServerList(std::istream &i);
00249 
00250         uint32_t    getCount()            const { return m_servers.size(); }
00251         IPV4Address getServer(uint32_t n) const { return m_servers.at(n);  }
00252 private:
00253         std::vector<IPV4Address> m_servers;
00254 };
00255 
00256 /**
00257  * OfferFiles packet is used in eDonkey2000 network to publish shared files to
00258  * currently connected server. The packet contains a list of files we want to
00259  * make available for others to download from us.
00260  *
00261  * eDonkey2000 network sets some limitations on the files that can be made
00262  * available. Namely, the file size must be <= numeric_limits<uint32_t>::max(),
00263  * because sizes are used as 32-bit integers in ed2k network. This limits file
00264  * size to roughly 4gb. Additionally, it is generally not recommended to publish
00265  * more than 300 files. Prefered files should be large (iso, avi, etc) files,
00266  * instead of small mp3 collections. Small files should be packet together
00267  * into archives for publishing. However, this is user-related issue and is not
00268  * related to the implementation of this class, but it is good to mention it
00269  * too.
00270  *
00271  * The semantics regarding this packet as as follows:
00272  *
00273  * *) A full list of all shared files should be sent when server connection has
00274  *    been established.
00275  * *) A partial list containing only added files should be sent whenever a new
00276  *    shared file has been added.
00277  * *) An empty list should be sent on regular intervals as keep-alive packet
00278  *    to lugdunum servers.
00279  *
00280  * Usage: Client -> Server
00281  */
00282 class OfferFiles : public Packet {
00283 public:
00284         OfferFiles(uint8_t proto = PR_ED2K);
00285         OfferFiles(boost::shared_ptr<ED2KFile> f, uint8_t proto = PR_ED2K);
00286         void push(boost::shared_ptr<ED2KFile> toAdd) {
00287                 m_toOffer.push_back(toAdd);
00288         }
00289         operator std::string();
00290 private:
00291         std::vector< boost::shared_ptr<ED2KFile> > m_toOffer;
00292         typedef std::vector< boost::shared_ptr<ED2KFile> >::iterator Iter;
00293 };
00294 
00295 /**
00296  * Search packet is used in client<->server communication to perform a search
00297  * on one or more servers. The search query is passed as SearchPtr to this
00298  * object, and handled internally as appropriate.
00299  *
00300  * Usage: Client -> Server
00301  */
00302 class Search : public Packet {
00303 public:
00304         Search(SearchPtr data, uint8_t proto = PR_ED2K);
00305         operator std::string();
00306 private:
00307         SearchPtr m_data;         //!< Search query data
00308 };
00309 
00310 /**
00311  * SearchResult packet is sent by server, and contains one or more search
00312  * results.
00313  *
00314  * Usage: Server -> Client
00315  */
00316 class SearchResult : public Packet {
00317 public:
00318         SearchResult(std::istream &i);
00319         uint32_t getCount() const { return m_results.size(); }
00320         boost::shared_ptr<ED2KSearchResult> getResult(uint32_t num) const {
00321                 return m_results.at(num);
00322         }
00323 private:
00324         std::vector<boost::shared_ptr<ED2KSearchResult> > m_results;
00325 };
00326 
00327 
00328 /**
00329  * Request the callback from a LowID client. This request is relayed to the
00330  * client indicated by @id by the server, after which the client will
00331  * "call back" to us, e.g. connect us. This can only be sent if the sender
00332  * itself is high-id (since otherwise the callee wouldn't be able to connect
00333  * us).
00334  */
00335 class ReqCallback : public Packet {
00336 public:
00337         ReqCallback(uint32_t id);
00338         operator std::string();
00339 private:
00340         uint32_t m_id;
00341 };
00342 
00343 /**
00344  * This packet indicates that a remote client wishes us to "call back" to it.
00345  * This packet is sent by server in case we are a low-id client, thus remote
00346  * clients cannot connect us directly.
00347  */
00348 class CallbackReq : public Packet {
00349 public:
00350         CallbackReq(std::istream &i);
00351 
00352         IPV4Address getAddr() const { return m_addr; }
00353 private:
00354         IPV4Address m_addr;
00355 };
00356 
00357 /**
00358  * Request sources for a hash from server. Note: Requesting sources costs
00359  * credits on server, and thus should be used carefully to avoid getting
00360  * blacklisted.
00361  */
00362 class ReqSources : public Packet {
00363 public:
00364         ReqSources(const Hash<ED2KHash> &h);
00365         operator std::string();
00366 private:
00367         Hash<ED2KHash> m_hash;        //!< File to request sources for
00368 };
00369 
00370 /**
00371  * This is server's response to ReqSources packet, and contains the list of
00372  * sources for the given hash.
00373  */
00374 class FoundSources : public Packet {
00375 public:
00376         FoundSources(std::istream &i);
00377         uint32_t    getCount()            const { return m_sources.size(); }
00378         IPV4Address getSource(uint32_t n) const { return m_sources.at(n);  }
00379         Hash<ED2KHash> getHash()          const { return m_hash;           }
00380         uint32_t    getLowCount()         const { return m_lowCount;       }
00381 private:
00382         Hash<ED2KHash> m_hash;              //!< File these sources belong to
00383         std::vector<IPV4Address> m_sources; //!< Sources list
00384         uint32_t       m_lowCount;          //!< # of LowID sources found
00385 };
00386 
00387 /**
00388  * Global source aquisition; sent via UDP, and contains one or more file hashes,
00389  * for which we wish to get sources for.
00390  */
00391 class GlobGetSources : public Packet {
00392 public:
00393         //! @param sendSize   Whether to also include filesizes
00394         GlobGetSources(bool sendSize);
00395         void addHash(const Hash<ED2KHash> &hash, uint32_t fileSize) {
00396                 m_hashList.push_back(std::make_pair(hash, fileSize));
00397         }
00398         operator std::string();
00399 private:
00400         std::vector<std::pair<Hash<ED2KHash>, uint32_t> > m_hashList;
00401         bool m_sendSize; //!< Whether to include filesizes in the packet
00402 };
00403 
00404 /**
00405  * Response to UDP GlobGetSources, this packet includes hash and list of sources
00406  * corresponding to that hash.
00407  */
00408 class GlobFoundSources : public Packet {
00409 public:
00410         typedef std::vector<IPV4Address>::iterator Iter;
00411 
00412         GlobFoundSources(std::istream &i);
00413 
00414         size_t size() const { return m_sources.size(); }
00415         Iter begin() { return m_sources.begin(); }
00416         Iter end() { return m_sources.end(); }
00417         Hash<ED2KHash> getHash() const { return m_hash; }
00418 private:
00419         Hash<ED2KHash> m_hash;              //!< File these sources belong to
00420         std::vector<IPV4Address> m_sources; //!< Sources list
00421 };
00422 
00423 /**
00424  * Global stats request; requests server to respond it's current users/files
00425  * counts.
00426  */
00427 class GlobStatReq : public Packet {
00428 public:
00429         GlobStatReq();
00430         operator std::string();
00431 
00432         uint32_t getChallenge() const { return m_challenge; }
00433 private:
00434         uint32_t m_challenge;    //!< Random challenge
00435 };
00436 
00437 /**
00438  * Global stats response - includes the servers current users/files counts.
00439  */
00440 class GlobStatRes : public Packet {
00441 public:
00442         GlobStatRes(std::istream &i);
00443 
00444         uint32_t getChallenge()  const { return m_challenge;  }
00445         uint32_t getUsers()      const { return m_users;      }
00446         uint32_t getFiles()      const { return m_files;      }
00447         uint32_t getMaxUsers()   const { return m_maxUsers;   }
00448         uint32_t getSoftLimit()  const { return m_softLimit;  }
00449         uint32_t getHardLimit()  const { return m_hardLimit;  }
00450         uint32_t getUdpFlags()   const { return m_udpFlags;   }
00451         uint32_t getLowIdUsers() const { return m_lowIdUsers; }
00452 private:
00453         uint32_t m_challenge;   //!< Challenge; equals GlobStatReq::m_challenge
00454         uint32_t m_users;       //!< Current online users
00455         uint32_t m_files;       //!< Current online files
00456         uint32_t m_maxUsers;    //!< Max users seen online
00457         uint32_t m_softLimit;   //!< Soft files count limit
00458         uint32_t m_hardLimit;   //!< Hard files count limit
00459         uint32_t m_udpFlags;    //!< UDP flags
00460         uint32_t m_lowIdUsers;  //!< Number of online LowId users
00461 };
00462 
00463                       /*************************/
00464                       /*  Client <-> Client    */
00465                       /*************************/
00466 
00467 /**
00468  * Hello packet is used to initialize a communication with another client.
00469  * The packet contains a set of information about ourselves.
00470  */
00471 class Hello : public Packet {
00472 public:
00473         Hello(uint8_t proto = PR_ED2K, const std::string &modStr = "");
00474         Hello(std::istream &i, bool hashLen = true);
00475         operator std::string();
00476 
00477         Hash<MD4Hash> getHash()       const { return m_hash;       }
00478         IPV4Address   getClientAddr() const { return m_clientAddr; }
00479         IPV4Address   getServerAddr() const { return m_serverAddr; }
00480         std::string   getNick()       const { return m_nick;       }
00481         uint32_t      getVersion()    const { return m_version;    }
00482         std::string   getModStr()     const { return m_modStr;     }
00483         uint32_t      getMuleVer()    const { return m_muleVer;    }
00484         uint16_t      getUdpPort()    const { return m_udpPort;    }
00485         uint32_t      getFeatures()   const { return m_features;   }
00486 protected:
00487         void load(std::istream &i, bool hashLen = true);
00488         std::string save(uint8_t opcode, bool hashLen = true);
00489 private:
00490         Hash<MD4Hash> m_hash;         //!< Userhash
00491         IPV4Address   m_clientAddr;   //!< Client ip address/port
00492         IPV4Address   m_serverAddr;   //!< Server ip address/port
00493         std::string   m_nick;         //!< User nick
00494         uint32_t      m_version;      //!< User client version
00495         std::string   m_modStr;       //!< User client mod string
00496         uint32_t      m_muleVer;      //!< Mule version
00497         uint16_t      m_udpPort;      //!< UDP port
00498         uint32_t      m_features;     //!< eMule extended features bitset
00499 };
00500 
00501 /**
00502  * HelloAnswer packet is the expected response to Hello packet. This includes
00503  * a set of information about the client. HelloAnswer differs from Hello only
00504  * by one byte (hashsize is sent on Hello but not on HelloAnswer), and has
00505  * different opcode.
00506  */
00507 class HelloAnswer : public Hello {
00508 public:
00509         HelloAnswer(uint8_t proto = PR_ED2K, const std::string &modStr = "");
00510         HelloAnswer(std::istream &i);
00511         operator std::string();
00512 };
00513 
00514 class MuleInfo : public Packet {
00515 public:
00516         MuleInfo();
00517         MuleInfo(std::istream &i);
00518         operator std::string();
00519 
00520         uint8_t     getProto()       const { return m_protocol;    }
00521         uint8_t     getVersion()     const { return m_version;     }
00522         uint8_t     getComprVer()    const { return m_comprVer;    }
00523         uint8_t     getUdpVer()      const { return m_udpVer;      }
00524         uint8_t     getCommentVer()  const { return m_commentVer;  }
00525         uint8_t     getExtReqVer()   const { return m_extReqVer;   }
00526         uint8_t     getSrcExchVer()  const { return m_srcExchVer;  }
00527         uint8_t     getCompatCliID() const { return m_compatCliID; }
00528         uint16_t    getUdpPort()     const { return m_udpPort;     }
00529         uint16_t    getFeatures()    const { return m_features;    }
00530         std::string getModStr()      const { return m_modStr;      }
00531 private:
00532         uint8_t     m_protocol;          //!< Protocol version
00533         uint8_t     m_version;           //!< Client version
00534         uint8_t     m_comprVer;          //!< Compression version
00535         uint8_t     m_udpVer;            //!< UDP version
00536         uint8_t     m_commentVer;        //!< Comment version
00537         uint8_t     m_extReqVer;         //!< Ext Req version
00538         uint8_t     m_srcExchVer;        //!< Source Exchange version
00539         uint8_t     m_compatCliID;       //!< Compatible client ID
00540         uint16_t    m_udpPort;           //!< UDP port
00541         uint16_t    m_features;          //!< Supported features
00542         std::string m_modStr;            //!< Mod string
00543 protected:
00544         uint8_t     m_opcode;            //!< For implementation use only
00545 };
00546 
00547 /**
00548  * MuleInfoAnswer packet is the response to MuleInfo packet, and contains the
00549  * exact same data as MuleInfo packet.
00550  */
00551 class MuleInfoAnswer : public MuleInfo {
00552 public:
00553         MuleInfoAnswer();
00554         MuleInfoAnswer(std::istream &i);
00555         operator std::string();
00556 };
00557 
00558 /**
00559  * ReqFile indicates that the sender wishes us to to upload the file to him.
00560  * Thus he sends ReqFile, and expects FileName and (optionally) FileDesc answers
00561  * from us before proceeding.
00562  *
00563  * eMule extends this request by adding partmap and complete source counts if
00564  * client supports extended requests.
00565  */
00566 class ReqFile : public Packet {
00567 public:
00568         ReqFile(const Hash<ED2KHash> &h, const PartData *pd, uint16_t srcCnt=0);
00569         ReqFile(std::istream &i);
00570         operator std::string();
00571 
00572         Hash<ED2KHash> getHash() const { return m_hash; }
00573 private:
00574         Hash<ED2KHash>    m_hash;      //!< File hash
00575         std::vector<bool> m_partMap;   //!< ExtReqv1: part map
00576         uint16_t          m_srcCnt;    //!< ExtReqv2: num COMPLETE sources
00577 };
00578 
00579 /**
00580  * FileName is the expected response to ReqFile, and contains the hash, and
00581  * the file name corresponding to that hash. Note that this packet also implies
00582  * that the sender is in fact sharing the file in question.
00583  */
00584 class FileName : public Packet {
00585 public:
00586         FileName(const Hash<ED2KHash> &hash, const std::string &filename);
00587         FileName(std::istream &i);
00588         operator std::string();
00589 
00590         std::string getName()    const { return m_name; }
00591         Hash<ED2KHash> getHash() const { return m_hash; }
00592 private:
00593         Hash<ED2KHash> m_hash;   //!< File hash
00594         std::string m_name;      //!< File name
00595 };
00596 
00597 /**
00598  * FileDesc packet contains the rating and the comment of the file. It is used
00599  * as reply to ReqFile packet, along with FileName packet, and only sent if
00600  * the file does have a rating/comment set, thus it is optional. Note that this
00601  * packet does not contain the hash of the file.
00602  */
00603 class FileDesc : public Packet {
00604 public:
00605         FileDesc(ED2KFile::Rating rating, const std::string &comment);
00606         FileDesc(std::istream &i);
00607         operator std::string();
00608 
00609         std::string      getComment() const { return m_comment; }
00610         ED2KFile::Rating getRating()  const { return m_rating;  }
00611 private:
00612         ED2KFile::Rating m_rating;        //!< Rating
00613         std::string      m_comment;       //!< Comment
00614 };
00615 
00616 /**
00617  * SetReqFileId is the last request from the client, binding the requested file
00618  * to the hash sent in this packet. This means the client is bound to receive
00619  * the file corresponding to the hash from us. Note that it is allowed (by eMule
00620  * extended protocol) to change the requested file while waiting on the queue.
00621  */
00622 class SetReqFileId : public Packet {
00623 public:
00624         SetReqFileId(const Hash<ED2KHash> &hash);
00625         SetReqFileId(std::istream &i);
00626         operator std::string();
00627 
00628         Hash<ED2KHash> getHash() const { return m_hash; }
00629 private:
00630         Hash<ED2KHash> m_hash;
00631 };
00632 
00633 /**
00634  * Answer to SetReqFileId packet, this indicates that we are not sharing the
00635  * file currently.
00636  */
00637 class NoFile : public Packet {
00638 public:
00639         NoFile(const Hash<ED2KHash> &hash);
00640         NoFile(std::istream &i);
00641         operator std::string();
00642 
00643         Hash<ED2KHash> getHash() const { return m_hash; }
00644 private:
00645         Hash<ED2KHash> m_hash;
00646 };
00647 
00648 /**
00649  * Finalizing the upload request sequence, this packet is sent by the uploading
00650  * client to indicate that the file is ready to be uploaded. It also contains
00651  * the part map of the file (if it is partial). Note that sending the partmap
00652  * is optional, and if not sent, the receiver assumes that the entire file
00653  * is available. Thus partmap is only sent if the file is partial.
00654  */
00655 class FileStatus : public Packet {
00656 public:
00657         FileStatus(const Hash<ED2KHash> &hash, const PartData *pd);
00658         FileStatus(std::istream &i);
00659         operator std::string();
00660 
00661         std::vector<bool> getPartMap() const { return m_partMap; }
00662         Hash<ED2KHash>       getHash() const { return m_hash;    }
00663 private:
00664         Hash<ED2KHash>    m_hash;
00665         std::vector<bool> m_partMap;
00666 };
00667 
00668 /**
00669  * ReqHashSet packet is used to request a hashset from remote client. The
00670  * expected answer to this packet is HashSet packet.
00671  */
00672 class ReqHashSet : public Packet {
00673 public:
00674         ReqHashSet(const Hash<ED2KHash> &hash);
00675         ReqHashSet(std::istream &i);
00676         operator std::string();
00677 
00678         Hash<ED2KHash> getHash() const { return m_hash; }
00679 private:
00680         Hash<ED2KHash> m_hash;          //!< File hash
00681 };
00682 
00683 /**
00684  * HashSet packet is answer to ReqHashSet packet, and contains the hashset
00685  * corresponding to the requested filehash.
00686  *
00687  * There are two semantics here. The tmpSet pointer is used for hashsets passed
00688  * in the first constructor, which takes a pointer. This pointer is not deleted,
00689  * since we cannot take ownership of it here. The m_hashSet pointer however is
00690  * loaded from stream by second constructor, and is dynamically deallocated
00691  * when no longer needed.
00692  *
00693  * It's safe (altough similarly messy) to do it this way rather than not take
00694  * ownership at all for the hashsets created in stream-loading constructor,
00695  * because the latter would expose too large of a risc of memory leaks in case
00696  * of exception-situations, which is unacceptable. Using this approach, the
00697  * constructed HashSet is guaranteed to be destroyed in all cases.
00698  */
00699 class HashSet : public Packet {
00700 public:
00701         HashSet(ED2KHashSet *hashset);
00702         HashSet(std::istream &i);
00703         operator std::string();
00704 
00705         boost::shared_ptr<ED2KHashSet> getHashSet() const { return m_hashSet; }
00706 private:
00707         boost::shared_ptr<ED2KHashSet> m_hashSet;
00708         ED2KHashSet *m_tmpSet;
00709 };
00710 
00711 /**
00712  * StartUploadReq finalizes the upload request sequence. It may optionally
00713  * contain the requested file hash. Upon receiving this packet, the uploading
00714  * client must insert the requesting client into it's upload queue and/or start
00715  * uploading. The responses to this packet are thus QueueRanking or
00716  * AcceptUploadReq.
00717  *
00718  * \note Sending hash in this packet is optional!
00719  */
00720 class StartUploadReq : public Packet {
00721 public:
00722         StartUploadReq();
00723         StartUploadReq(const Hash<ED2KHash> &h);
00724         StartUploadReq(std::istream &i);
00725         operator std::string();
00726 
00727         Hash<ED2KHash> getHash() const { return m_hash; }
00728 private:
00729         Hash<ED2KHash> m_hash;       //!< Optional
00730 };
00731 
00732 /**
00733  * Empty packet, indicating an accepted upload request (e.g. the uploading can
00734  * start right away).
00735  */
00736 class AcceptUploadReq : public Packet {
00737 public:
00738         AcceptUploadReq();
00739         AcceptUploadReq(std::istream &i);
00740         operator std::string();
00741 };
00742 
00743 /**
00744  * Indicates the queue ranking of a queued client.
00745  */
00746 class QueueRanking : public Packet {
00747 public:
00748         QueueRanking(uint16_t rank);
00749         QueueRanking(std::istream &i);
00750         operator std::string();
00751 
00752         uint16_t getQR() const { return m_qr; }
00753 private:
00754         uint16_t m_qr;
00755 };
00756 
00757 /**
00758  * MuleQueueRank packet is different from QueueRanking packet only from
00759  * implementation point of view. While QueueRanking contains 32-bit integer
00760  * value, this one contains 16-bit integer value, plus 10 empty bytes.
00761  */
00762 class MuleQueueRank : public Packet {
00763 public:
00764         MuleQueueRank(uint16_t rank);
00765         MuleQueueRank(std::istream &i);
00766         operator std::string();
00767 
00768         uint16_t getQR() const { return m_qr; }
00769 private:
00770         uint16_t m_qr;
00771 };
00772 
00773 /**
00774  * Requests (up to) three parts, indicated by the three ranges
00775  *
00776  * Important: In ed2k network, the chunk range end offset is NOT included.
00777  * This is different from hydranode Range implementation, where end offset
00778  * is also included. The member m_reqChunks contains the ranges in hydranode
00779  * Range format, and conversions to ed2k format are done during packet
00780  * parsing.
00781  */
00782 class ReqChunks : public Packet {
00783 public:
00784         ReqChunks(const Hash<ED2KHash> &h, const std::list<Range32> &reqparts);
00785         ReqChunks(std::istream &i);
00786         operator std::string();
00787 
00788         Hash<ED2KHash> getHash()       const { return m_hash;             }
00789         uint8_t getReqChunkCount()     const { return m_reqChunks.size(); }
00790         Range32 getReqChunk(uint8_t n) const { return m_reqChunks.at(n);  }
00791 private:
00792         Hash<ED2KHash>        m_hash;               //!< Requested file hash
00793         std::vector<Range32> m_reqChunks;          //!< Requested chunks
00794 };
00795 
00796 /**
00797  * DataChunk packet indicates a single data chunk send from one client to
00798  * another.
00799  */
00800 class DataChunk : public Packet {
00801 public:
00802         DataChunk(
00803                 Hash<ED2KHash> hash, uint32_t begin,
00804                 uint32_t end, const std::string &data
00805         );
00806         DataChunk(std::istream &i);
00807         operator std::string();
00808 
00809         const std::string& getData()  const { return m_data;  }
00810         uint32_t           getBegin() const { return m_begin; }
00811         uint32_t           getEnd()   const { return m_end;   }
00812 private:
00813         Hash<ED2KHash> m_hash;     //!< File hash where the data belongs to
00814         uint32_t       m_begin;    //!< Begin offset (inclusive)
00815         uint32_t       m_end;      //!< End offset (exclusive)
00816         std::string    m_data;     //!< The data
00817 };
00818 
00819 /**
00820  * Emule extended packet, this contains packed data chunk.
00821  *
00822  * This packet contains only part of the entire packed data stream. In ed2k
00823  * protocol, a 180k chunk is compressed, and spread over 10k chunks and sent
00824  * separately. The size member of this packet indicates the total size of the
00825  * packed data (out of which 10kb or so was sent in this packet).
00826  */
00827 class PackedChunk : public Packet {
00828 public:
00829         PackedChunk (
00830                 Hash<ED2KHash> hash, uint32_t begin,
00831                 uint32_t size, const std::string &data
00832         );
00833         PackedChunk(std::istream &i);
00834         operator std::string();
00835 
00836         const std::string& getData()  const { return m_data;  }
00837         uint32_t           getBegin() const { return m_begin; }
00838         uint32_t           getSize()  const { return m_size;  }
00839 private:
00840         Hash<ED2KHash> m_hash;     //!< File hash where the data belongs to
00841         uint32_t       m_begin;    //!< Data begin offset
00842         uint32_t       m_size;     //!< Size of entire packed data chunk
00843         std::string    m_data;     //!< Part of the packed data chunk
00844 };
00845 
00846 /**
00847  * CancelTransfer packet indicates that the receiver of this packet should stop
00848  * sending data. This packet does not contain any payload.
00849  */
00850 class CancelTransfer : public Packet {
00851 public:
00852         CancelTransfer();
00853         CancelTransfer(std::istream &i);
00854         operator std::string();
00855 };
00856 
00857 /**
00858  * SourceExchReq packet is sent from one client to another in order to request
00859  * all sources the remote client knows for a hash.
00860  */
00861 class SourceExchReq : public Packet {
00862 public:
00863         SourceExchReq(const Hash<ED2KHash> &hash);
00864         SourceExchReq(std::istream &i);
00865         operator std::string();
00866 
00867         Hash<ED2KHash> getHash() const { return m_hash; }
00868 private:
00869         Hash<ED2KHash> m_hash;
00870 };
00871 
00872 /**
00873  * AnswerSources packet is the expected answer to SourceExchReq packet, and
00874  * contains the list of sources corresponding to a file hash. As a general
00875  * rule, no more than 500 sources are sent, and other limitations may be
00876  * present, depending on client.
00877  */
00878 class AnswerSources : public Packet {
00879 public:
00880         typedef boost::tuple<uint32_t, uint16_t, uint32_t, uint16_t> Source;
00881         typedef std::vector<Source> SourceList;
00882         typedef SourceList::const_iterator CIter;
00883 
00884         AnswerSources(const Hash<ED2KHash> &hash, const SourceList &srcs);
00885         AnswerSources(std::istringstream &i);
00886         operator std::string();
00887 
00888         Hash<ED2KHash> getHash() const    { return m_hash;            }
00889         CIter begin()            const    { return m_srcList.begin(); }
00890         CIter end()              const    { return m_srcList.end();   }
00891         size_t size()            const    { return m_srcList.size();  }
00892 
00893         /**
00894          * If set to true, all client-ids are swapped before sending
00895          */
00896         void setSwapIds(bool swap) { m_swapIds = swap; }
00897 private:
00898         Hash<ED2KHash> m_hash;
00899         SourceList m_srcList;
00900         bool m_swapIds;
00901 };
00902 
00903 /**
00904  * This packet can occasionally be sent compressed, however our parser then
00905  * resets the opcode to PR_ED2K (since compressed packets from Servers should
00906  * be done so). However, in this case, the packet is supposed to be PR_EMULE
00907  * instead, which leads to the problem, solved by this typedef and duplicate
00908  * DECLARE_PACKET_FACTORY() macro in factories.h.
00909  */
00910 typedef AnswerSources AnswerSources2;
00911 
00912 /**
00913  * A text message sent from one client to another client
00914  */
00915 class Message : public Packet {
00916 public:
00917         Message(const std::string &msg);
00918         Message(std::istream &i);
00919         operator std::string();
00920 
00921         std::string getMsg() const { return m_message; }
00922 private:
00923         std::string m_message;
00924 };
00925 
00926 /**
00927  * ChangeId packet indicates the sending client changed it's ID on the net from
00928  * oldId to newId.
00929  */
00930 class ChangeId : public Packet {
00931 public:
00932         ChangeId(uint32_t oldId, uint32_t newId);
00933         ChangeId(std::istream &i);
00934         operator std::string();
00935 
00936         uint32_t getOldId() const { return m_oldId; }
00937         uint32_t getNewId() const { return m_newId; }
00938 private:
00939         uint32_t m_oldId;
00940         uint32_t m_newId;
00941 };
00942 
00943 /**
00944  * Initiate Secure Identification with remote client; requests the remote
00945  * client to send us signature (and if needed) also publickey. Later, when
00946  * we already have the client's pubkey, we can only request the signature.
00947  */
00948 class SecIdentState : public Packet {
00949 public:
00950         SecIdentState(::SecIdentState s);
00951         SecIdentState(std::istream &i);
00952         operator std::string();
00953 
00954         uint8_t  getState()     const { return m_state;     }
00955         uint32_t getChallenge() const { return m_challenge; }
00956 private:
00957         uint8_t  m_state;     //!< One of ::SecIdentState enum values
00958         uint32_t m_challenge; //!< Random 32bit challenge
00959 };
00960 
00961 /**
00962  * PublicKey packet is the expected response to SecIdentState packet which
00963  * requested PublicKey; it contains - the remote client's public key ofcourse.
00964  */
00965 class PublicKey : public Packet {
00966 public:
00967         PublicKey(const ::PublicKey &pubKey);
00968         PublicKey(std::istream &i);
00969         operator std::string();
00970 
00971         ::PublicKey getKey() const { return m_pubKey; }
00972 private:
00973         ::PublicKey m_pubKey;   //!< Public key
00974 };
00975 
00976 /**
00977  * Signature packet is the expected response to SecIdentState packet which
00978  * requested Signature; it contains - the remote client's signature ofcourse.
00979  */
00980 class Signature : public Packet {
00981 public:
00982         Signature(const std::string &sign, IpType ipType = 0);
00983         Signature(std::istream &i);
00984         operator std::string();
00985 
00986         std::string getSign()   const { return m_signature; }
00987         IpType      getIpType() const { return m_ipType;    }
00988 private:
00989         std::string m_signature; //!< Signature
00990         IpType      m_ipType;    //!< Either local, remote or none
00991 };
00992 
00993                         /*************************
00994                          * Client <-> Client UDP *
00995                          *************************/
00996 
00997 /**
00998  * Used to ping sources every 20 minutes to verify that we are still queued for
00999  * our requested file. By default the packet contains only filehash, but
01000  * UDPv3 adds complete source count, UDPv4 adds full extended info, as in
01001  * ReqFile packet (e.g. partmap).
01002  *
01003  * Note that if you do not send this packet via UDP to eMules at least once per
01004  * hour, you will be dropped from queues.
01005  */
01006 class ReaskFilePing : public Packet {
01007 public:
01008         ReaskFilePing(
01009                 const Hash<ED2KHash> &h, const PartData *pd, uint16_t srcCnt,
01010                 uint8_t udpVersion
01011         );
01012         ReaskFilePing(std::istream &i);
01013         operator std::string();
01014 
01015         Hash<ED2KHash>    getHash()    const { return m_hash;    }
01016         std::vector<bool> getPartMap() const { return m_partMap; }
01017         uint16_t          getSrcCnt()  const { return m_srcCnt;  }
01018 private:
01019         Hash<ED2KHash> m_hash;       //!< Filehash
01020         std::vector<bool> m_partMap; //!< Availability partmap
01021         uint16_t m_srcCnt;           //!< full sources count
01022         uint8_t m_udpVersion;        //!< Client udp version
01023 };
01024 
01025 /**
01026  * QueueFull indicates that the remote client's queue is ... full. This packet
01027  * contains no other data.
01028  */
01029 class QueueFull : public Packet {
01030 public:
01031         QueueFull();
01032         QueueFull(std::istream &i);
01033         operator std::string();
01034 };
01035 
01036 /**
01037  * ReaskAck is an expected response to ReaskFilePing packet, ant includes the
01038  * remote queue ranking. UDPv4 also includes partmap;
01039  */
01040 class ReaskAck : public Packet {
01041 public:
01042         ReaskAck(const PartData *pd, uint16_t rank, uint8_t udpVersion);
01043         ReaskAck(std::istream &i);
01044         operator std::string();
01045 
01046         std::vector<bool> getPartMap() const { return m_partMap; }
01047         uint16_t          getQR()      const { return m_qr;      }
01048 private:
01049         std::vector<bool> m_partMap;    //!< Availability partmap
01050         uint16_t m_qr;                  //!< Remote queue ranking
01051         uint8_t m_udpVersion;           //!< UDP version
01052 };
01053 
01054 /**
01055  * Indicates that the requested file (via last ReaskFilePing) was not found.
01056  * This packet contains no other data.
01057  */
01058 class FileNotFound : public Packet {
01059 public:
01060         FileNotFound();
01061         FileNotFound(std::istream &i);
01062         operator std::string();
01063 };
01064 
01065 /**
01066  * PortTest isn't exactly part of eDonkey2000 nor eMule extended protocol; it
01067  * is instead used to verify correct firewall configurations, for example, by
01068  * a website with an appropriate button. This packet may contain single '1'
01069  * value to indicate successful port test. This packet may be sent both via
01070  * TCP and UDP.
01071  */
01072 class PortTest : public Packet {
01073 public:
01074         PortTest();
01075         PortTest(std::istream &i);
01076         operator std::string();
01077 };
01078 
01079 } // ! namespace ED2KPacket
01080 
01081 #endif