Main Page | Class Hierarchy | Class List | File List | Class Members

/Users/baford/proj/netsteria/sst/lib/regcli.h

00001 #ifndef SST_REGCLI_H
00002 #define SST_REGCLI_H
00003 
00004 #include <QSet>
00005 
00006 #include "reg.h"
00007 #include "sock.h"
00008 #include "timer.h"
00009 
00010 class QHostInfo;
00011 
00012 
00013 namespace SST {
00014 
00015 class Host;
00016 class RegReceiver;
00017 
00018 class RegClient : public QObject
00019 {
00020         friend class RegReceiver;
00021         Q_OBJECT
00022 
00023 private:
00024         static const int maxRereg = 60*60*1000; // Max time before rereg - 1 hr
00025 
00026 
00027         Host *const h;          // Pointer to our per-host state
00028 
00029         enum State {
00030                 Idle = 0,       // Unregistered and not doing anything
00031                 Resolve,        // Resolving rendezvous server's host name
00032                 Insert1,        // Sent Insert1 request, waiting response
00033                 Insert2,        // Sent Insert2 request, waiting response
00034                 Registered,     // Successfully registered
00035         } state;
00036 
00037         // DNS resolution info
00038         QString srvname;        // DNS hostname or IP address of server
00039         quint16 srvport;        // Port number of registration server
00040         int lookupid;           // QHostInfo lookupId for DNS resolution
00041         QList<QHostAddress> addrs;      // Server addresses from resolution
00042         RegInfo inf;            // Registration metadata
00043 
00044         // Registration process state
00045         QByteArray idi;         // Initiator's identity (i.e., mine)
00046         QByteArray ni;          // Initiator's nonce
00047         QByteArray nhi;         // Initiator's hashed nonce
00048         QByteArray chal;        // Responder's challenge from Insert1 reply
00049         QByteArray key;         // Our encoded public key to send to server
00050         QByteArray sig;         // Our signature to send in Insert2
00051 
00052         // Outstanding lookups and searches for which we're awaiting replies.
00053         QSet<QByteArray> lookups;       // IDs we're doing lookups on
00054         QSet<QByteArray> punches;       // Lookups with notify requests
00055         QSet<QString> searches;         // Strings we're searching for
00056 
00057         // Retry state
00058         Timer retrytimer;       // Retransmission timer
00059         bool persist;           // True if we should never give up
00060 
00061         Timer reregtimer;       // Counts lifetime of our reg entry
00062 
00063         // Error state
00064         QString err;
00065 
00066 
00067         // As the result of an error, disconnect and notify the client.
00068         void fail(const QString &error);
00069 
00070 public:
00071         RegClient(Host *h, QObject *parent = NULL);
00072         ~RegClient();
00073 
00074         // Set the metadata to attach to our registration
00075         inline RegInfo info() { return inf; }
00076         inline void setInfo(const RegInfo &info) { inf = info; }
00077 
00078         // Attempt to register with the specified registration server.
00079         // We'll send a stateChanged() signal when it succeeds or fails.
00080         void registerAt(const QString &srvhost,
00081                         quint16 port = REGSERVER_DEFAULT_PORT);
00082 
00083         // Attempt to re-register with the same server previously indicated.
00084         void reregister();
00085 
00086         inline QString serverName() { return srvname; }
00087         inline quint16 serverPort() { return srvport; }
00088 
00089         inline QString errorString() { return err; }
00090         inline void setErrorString(const QString &err) { this->err = err; }
00091 
00092         inline bool idle() { return state == Idle; }
00093         inline bool registered() { return state == Registered; }
00094         inline bool registering() { return !idle() && !registered(); }
00095 
00096         // A persistent RegClient will never give up trying to register,
00097         // and will try to re-register if its connection is lost.
00098         inline void setPersistent(bool persist) { this->persist = persist; }
00099         inline bool isPersistent() { return persist; }
00100 
00101         // Request information about a specific ID from the server.
00102         // Will send a lookupDone() signal when the request completes.
00103         // If 'notify', ask regserver to notify the target as well.
00104         // Must be in the registered() state to initiate a lookup.
00105         void lookup(const QByteArray &id, bool notify = false);
00106 
00107         // Search for IDs of clients with metadata matching a search string.
00108         // Will send a searchDone() signal when the request completes.
00109         // Must be in the registered() state to initiate a search.
00110         void search(const QString &text);
00111 
00112         // Disconnect from our server or cancel the registration process,
00113         // and return immediately to the idle state.
00114         void disconnect();
00115 
00116 
00117 signals:
00118         void stateChanged();
00119         void lookupDone(const QByteArray &id, const Endpoint &loc,
00120                         const RegInfo &info);
00121         void lookupNotify(const QByteArray &id, const Endpoint &loc,
00122                         const RegInfo &info);
00123         void searchDone(const QString &text, const QList<QByteArray> ids,
00124                         bool complete);
00125 
00126 private:
00127         void goInsert1();
00128         void sendInsert1();
00129         void gotInsert1Reply(XdrStream &rs);
00130 
00131         void goInsert2();
00132         void sendInsert2();
00133         void gotInsert2Reply(XdrStream &rs);
00134 
00135         void sendLookup(const QByteArray &id, bool notify);
00136         void gotLookupReply(XdrStream &rs, bool isnotify);
00137 
00138         void sendSearch(const QString &text);
00139         void gotSearchReply(XdrStream &rs);
00140 
00141         void send(const QByteArray &msg);
00142 
00143 
00144 private slots:
00145         void resolveDone(const QHostInfo &hi);  // DNS lookup done
00146         void timeout(bool fail);                // Retry timer timeout
00147         void reregTimeout();                    // Reregister timeout
00148 };
00149 
00150 // Private helper class for RegClient -
00151 // attaches to our Socket and dispatches control messages to different clients
00152 class RegReceiver : public SocketReceiver
00153 {
00154         friend class RegClient;
00155         friend class RegHostState;
00156 
00157 private:
00158         // Global hash table of active RegClient instances,
00159         // for dispatching incoming messages based on hashed nonce (nhi).
00160         QHash<QByteArray,RegClient*> nhihash;
00161 
00162 
00163         RegReceiver(Host *h);
00164         virtual void receive(QByteArray &msg, XdrStream &ds,
00165                                 const SocketEndpoint &src);
00166 };
00167 
00168 // Per-host state for the registration client.
00169 class RegHostState : public QObject
00170 {
00171         friend class RegClient;
00172         Q_OBJECT
00173 
00174 private:
00175         RegReceiver rcvr;
00176 
00177         // Global registry of every RegClient for this host, so we can
00178         // produce signals when RegClients are created or destroyed.
00179         QSet<RegClient*> cliset;
00180 
00181 public:
00182         inline RegHostState(Host *h) : rcvr(h) { }
00183 
00184         inline QList<RegClient*> regClients()
00185                 { return cliset.toList(); }
00186 
00187 signals:
00188         void regClientCreate(RegClient *rc);
00189         void regClientDestroy(RegClient *rc);
00190 };
00191 
00192 } // namespace SST
00193 
00194 #endif  // SST_REGCLI_H

Generated on Wed Mar 28 11:48:05 2007 for SST by doxygen 1.3.4