serverlist.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 /** @file serverlist.h Interface for ServerList and Server classes */
00020 
00021 #ifndef __SERVERLIST_H__
00022 #define __SERVERLIST_H__
00023 
00024 #include "ed2ktypes.h"                                  // types and fwd dclrs
00025 #include <hn/hnfwd.h>                                   // forward declrs
00026 #include <hn/search.h>                                  // Search API
00027 #include <hn/ipv4addr.h>                                // ipv4addr
00028 #include <hn/object.h>                                  // object api
00029 
00030 namespace Detail {
00031         struct FileQueryList;  // Files Query Times list implementation
00032         struct MIServerList;   // ServerList implementation
00033         struct QTIter;         // QueryTime Iterator
00034         class Server;
00035 }
00036 
00037 /**
00038  * ServerList class encapsulates the list of known servers. The list is loaded
00039  * from config/ed2k/server.met on startup, and saved to same file on shutdown.
00040  * The file format conforms to eDonkey2000 protocol specification. This class
00041  * also has the added responsibility of handling server connections, as well as
00042  * communication with currently connected server.
00043  *
00044  * ServerList class is a singleton with lazy initialization. The only instance
00045  * of this class may be retrieved via static instance() member function.
00046  */
00047 class ServerList : public Object, public boost::signals::trackable {
00048 public:
00049         //! Return the only instance of this class
00050         static ServerList& instance() {
00051                 static ServerList *s = new ServerList();
00052                 return *s;
00053         }
00054 
00055         //! Load the list from file, adding all found items to the list
00056         void load(const std::string &file);
00057 
00058         //! Save the list to the specified file
00059         void save(const std::string &file) const;
00060 
00061         /**
00062          * Initialize ServerList networking
00063          */
00064         void init();
00065 
00066         /**
00067          * Exit ServerList
00068          */
00069         void exit();
00070 
00071         /**
00072          * \brief Connect to a random server.
00073          *
00074          * If the connections fail, the connecting attempt to continue until the
00075          * connection has been established, or the list is exhausted.
00076          */
00077         void connect();
00078 
00079         /**
00080          * \brief Connect to a specific server, possibly disconnecting from
00081          *        current server, if connected.
00082          *
00083          * @param s    Server to connect to
00084          */
00085         void connect(Detail::Server *s);
00086 
00087         /**
00088          * \returns Address of currently connected server
00089          * \throws std::runtime_error if not connected
00090          */
00091         IPV4Address getCurServerAddr() const;
00092 
00093         /**
00094          * Get current connection status.
00095          *
00096          * @return       Bitfield containing one or more of Status values.
00097          */
00098         uint8_t getStatus() const { return m_status; }
00099 
00100         /**
00101          * Request callback from a client via server
00102          *
00103          * @param id    ID if the client we wish to contact us
00104          */
00105         void reqCallback(uint32_t id);
00106 
00107         /**
00108          * Add a server by address
00109          *
00110          * @param addr      Address of the server
00111          */
00112         void addServer(IPV4Address addr);
00113 
00114         // ddeml.h (included from windows.h included from gettickcount.h)
00115         // defines ST_CONNECTED already
00116         #ifdef ST_CONNECTED
00117                 #undef ST_CONNECTED
00118         #endif
00119 
00120         //! Statuses
00121         enum Status {
00122                 ST_CONNECTED  = 0x01,       //!< Connected
00123                 ST_CONNECTING = 0x02        //!< Not connected
00124         };
00125 
00126 private:
00127 
00128         // internal data
00129         // -------------
00130 
00131         ED2KClientSocket*      m_serverSocket;   //!< Socket to current server
00132         Detail::Server*        m_currentServer;  //!< Currently connected server
00133         SearchPtr              m_curSearch;      //!< Current search in progress
00134         ED2KUDPSocket*         m_udpSocket;      //!< Server udp listener
00135         uint64_t               m_lastSourceRequest; //!< Time of last src req
00136 
00137         //! Server stream parser
00138         boost::shared_ptr<ED2KParser<ServerList> > m_parser;
00139         //! Keeps track of currect connection status
00140         uint8_t m_status;
00141 
00142         //! List of servers, sorted by IP and Name
00143         boost::scoped_ptr<Detail::MIServerList> m_list;
00144 
00145         //! Events emitted from ServerList class (used internally only)
00146         enum ServerListEvent {
00147                 EVT_PINGSERVER,    //!< Ping server with empty OfferFiles packet
00148                 EVT_REQSOURCES,    //!< Request sources from server
00149                 EVT_LOGINTIMEOUT,  //!< Login attempt timeouts
00150                 EVT_QUERYSERVER,   //!< UDP GetSources and Ping request time
00151                 EVT_CONNECT        //!< Attempt to connect to next server
00152         };
00153 
00154         //! Events emitted from Server class (used internally only)
00155         enum ServerEvent {
00156                 EVT_PINGTIMEOUT    //!< Indicates UDP query timed out
00157         };
00158 
00159         // internal functions
00160 
00161         DECLARE_EVENT_TABLE(ServerList*, ServerListEvent);
00162 
00163         ServerList();                        //!< Singleton - private
00164         ~ServerList();                       //!< Singleton - private
00165 
00166         //! Event handler for our own events, used for timed events
00167         void onServerListEvent(ServerList *sl, ServerListEvent evt);
00168 
00169         //! Event handler for currentserver events
00170         void onServerSocketEvent(ED2KClientSocket *c, SocketEvent evt);
00171 
00172         //! Event handler for internal Server events
00173         void onServerEvent(Detail::Server *serc, int event);
00174 
00175         //! Sends login request
00176         void sendLoginRequest();
00177 
00178         /**
00179          * Sends our current shared files list to server (all of them)
00180          *
00181          * @param useZlib        Whether to use Zlib compression (and the
00182          *                       related 'special' id's during sending.
00183          */
00184         void publishFiles(bool useZlib);
00185 
00186         /**
00187          * Publish a single file to server.
00188          *
00189          * @param sf             File to publish
00190          */
00191         void publishFile(SharedFile *sf);
00192 
00193         /**
00194          * Perform a search on eDonkey2000 network, based on criteria described
00195          * in argument.
00196          *
00197          * @param search         Pointer to search object describing the search
00198          *                       criteria.
00199          */
00200         void performSearch(SearchPtr search);
00201 
00202         /**
00203          * Adds a set of hardcoded servers to the server list.
00204          */
00205         void addDefaultServers();
00206 
00207         /**
00208          * Event handler for events emitted from SharedFile. This function is
00209          * called from event table and should never be called directly.
00210          */
00211         void onSharedFileEvent(SharedFile *sf, int evt);
00212 
00213         /**
00214          * Request sources for all temporary files which have the neccesery
00215          * information (e.g. ED2KHash).
00216          */
00217         void reqSources();
00218 
00219         /**
00220          * Requests sources for download from current server (if connected).
00221          * Does nothing if we are currently not connected to a server.
00222          *
00223          * @param d           Download to request sources for
00224          */
00225         void reqSources(Download &d);
00226 
00227         /**
00228          * Chooses next server to perform UDP queries with
00229          */
00230         void queryNextServer();
00231 
00232         //! Ping the server pointed to by iterator
00233         void pingServer(Detail::QTIter &it);
00234         //! Get sources via UDP from server pointed to by iterator
00235         void udpGetSources(Detail::QTIter &it);
00236 
00237         /**
00238          * Event handler for server udp listener
00239          */
00240         void onUdpData(ED2KUDPSocket *sock, SocketEvent evt);
00241 
00242         /**
00243          * Handles GlobFoundSources data from UDP servers
00244          *
00245          * @param i      Input stream to read packet(s) from
00246          * @param from   The server that sent this data
00247          */
00248         void handleGlobSources(std::istringstream &i, IPV4Address from);
00249 
00250         /**
00251          * Handles GlobStatRes data from UDP servers
00252          *
00253          * @param i      Input stream to read packet from
00254          * @param from   The server that sent this data
00255          */
00256         void handleGlobStatRes(std::istringstream &i, IPV4Address from);
00257 
00258 public:
00259         //! @name Packet handlers
00260         //@{
00261         void onPacket(const ED2KPacket::ServerMessage &p);
00262         void onPacket(const ED2KPacket::IdChange &p);
00263         void onPacket(const ED2KPacket::ServerStatus &p);
00264         void onPacket(const ED2KPacket::ServerIdent &p);
00265         void onPacket(const ED2KPacket::ServerList &p);
00266         void onPacket(const ED2KPacket::SearchResult &p);
00267         void onPacket(const ED2KPacket::CallbackReq &p);
00268         void onPacket(const ED2KPacket::FoundSources  &p);
00269         //@}
00270 
00271 private:
00272         virtual uint8_t getOperCount() const;
00273         virtual Object::Operation getOper(uint8_t n) const;
00274         virtual void doOper(const Object::Operation &op);
00275 
00276 };
00277 
00278 #endif