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

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

00001 //
00002 // Class implementing a UDP socket for Netsteria use.
00003 // Multiplexes between flow-setup/key exchange traffic (which goes to key.cc)
00004 // and per-flow data traffic (which goes to flow.cc).
00005 // XX Rename Socket* to Net* or Link*?
00006 // 
00007 #ifndef SST_SOCK_H
00008 #define SST_SOCK_H
00009 
00010 #include <QHash>
00011 #include <QPair>
00012 #include <QPointer>
00013 #include <QHostAddress>
00014 #include <QUdpSocket>
00015 #include <QPointer>
00016 
00017 #include "util.h"
00018 
00019 #define NETSTERIA_DEFAULT_PORT  8661
00020 
00021 class QSettings;
00022 
00023 
00024 namespace SST {
00025 
00026 class XdrStream;
00027 class Socket;
00028 class SocketFlow;
00029 class SocketReceiver;
00030 class SocketHostState;
00031 
00032 
00033 // An 8-bit channel number distinguishes different flows
00034 // between the same pair of socket-layer endpoints.
00035 // Channel number 0 is always invalid.
00036 typedef quint8 Channel;
00037 
00038 
00039 // SockEndpoint builds on the basic Endpoint class
00040 // to keep an association with a particular Socket as well.
00041 struct SocketEndpoint : public Endpoint
00042 {
00043         QPointer<Socket> sock;
00044 
00045         inline SocketEndpoint() { }
00046         inline SocketEndpoint(const SocketEndpoint &other)
00047                 : Endpoint(other), sock(other.sock) { }
00048         SocketEndpoint(const Endpoint &ep, Socket *sock);
00049 
00050         // Send a message to this endpoint on this socket
00051         bool send(const char *data, int size) const;
00052         inline bool send(const QByteArray &msg) const
00053                 { return send(msg.constData(), msg.size()); }
00054 };
00055 
00056 
00061 class Socket : public QObject
00062 {
00063         friend class SocketFlow;
00064         Q_OBJECT
00065 
00066 private:
00068         SocketHostState *const h;
00069 
00071         QHash<QPair<Endpoint,Channel>, SocketFlow*> flows;
00072 
00074         bool act;
00075 
00076 
00077 public:
00078         inline Socket(SocketHostState *host, QObject *parent = NULL)
00079                 : QObject(parent), h(host), act(false) { }
00080 
00084         inline bool active() { return act; }
00085 
00089         void setActive(bool act);
00090 
00096         virtual bool bind(const QHostAddress &addr = QHostAddress::Any,
00097                 quint16 port = 0,
00098                 QUdpSocket::BindMode mode = QUdpSocket::DefaultForPlatform) = 0;
00099 
00104         virtual bool send(const Endpoint &ep, const char *data, int size) = 0;
00105         inline bool send(const Endpoint &ep, const QByteArray &msg)
00106                 { return send(ep, msg.constData(), msg.size()); }
00107 
00110         virtual QList<Endpoint> localEndpoints() = 0;
00111 
00112         virtual quint16 localPort() = 0;
00113 
00115         inline SocketFlow *flow(const Endpoint &dst, Channel chan)
00116                 { return flows.value(QPair<Endpoint,Channel>(dst, chan)); }
00117 
00119         virtual QString errorString() = 0;
00120 
00121 
00122 protected:
00123 
00127         void receive(QByteArray &msg, const SocketEndpoint &src);
00128 };
00129 
00130 
00132 class UdpSocket : public Socket
00133 {
00134         Q_OBJECT
00135 
00136         QUdpSocket usock;
00137 
00138 public:
00139         UdpSocket(SocketHostState *host, QObject *parent = NULL);
00140 
00146         bool bind(const QHostAddress &addr = QHostAddress::Any,
00147                 quint16 port = 0,
00148                 QUdpSocket::BindMode mode = QUdpSocket::DefaultForPlatform);
00149 
00150         // Send a packet on this UDP socket.
00151         // Implements of Socket::send().
00152         bool send(const Endpoint &ep, const char *data, int size);
00153 
00154         // Return all known local endpoints referring to this socket.
00155         // Implements Socket::localEndpoints().
00156         QList<Endpoint> localEndpoints();
00157 
00158         quint16 localPort() { return usock.localPort(); }
00159 
00161         inline QString errorString() { return usock.errorString(); }
00162 
00163 
00164 private slots:
00165         void udpReadyRead();
00166 };
00167 
00168 
00169 // Base class for flows that may be bound to a socket,
00170 // for dispatching received packets based on endpoint and channel number.
00171 // May be used as an abstract base by overriding the receive() method,
00172 // or used as a concrete class by connecting to the received() signal.
00173 class SocketFlow : public QObject
00174 {
00175         friend class Socket;
00176         Q_OBJECT
00177 
00178 private:
00179         Socket *sock;           // Socket we're currently bound to, if any
00180         Endpoint remoteep;      // UDP endpoint of remote end
00181         Channel localchan;      // Channel number of this flow at local node
00182         Channel remotechan;     // Channel number of this flow at remote node
00183         bool active;            // True if we're sending and accepting packets
00184 
00185 public:
00186         SocketFlow(QObject *parent = NULL);
00187         virtual ~SocketFlow();
00188 
00189         // Set up for communication with specified remote endpoint,
00190         // allocating and binding a local channel number in the process.
00191         // Returns 0 if no channels are available for specified endpoint.
00192         Channel bind(Socket *sock, const Endpoint &remoteep);
00193         inline Channel bind(const SocketEndpoint &remoteep)
00194                 { return bind(remoteep.sock, remoteep); }
00195 
00196         // Bind to a particular channel number.
00197         // Returns false if the channel is already in use.
00198         bool bind(Socket *sock, const Endpoint &remoteep, Channel chan);
00199 
00200         // Set the channel number to direct packets to the remote endpoint.
00201         // This MUST be done before a new flow can be activated.
00202         inline void setRemoteChannel(Channel chan) { remotechan = chan; }
00203 
00204         // Return the remote endpoint we're bound to, if any
00205         inline SocketEndpoint remoteEndpoint()
00206                 { return SocketEndpoint(remoteep, sock); }
00207 
00208         // Return current local and remote channel numbers
00209         inline Channel localChannel() { return localchan; }
00210         inline Channel remoteChannel() { return remotechan; }
00211 
00212         // Start or stop the flow.
00213         virtual void start();
00214         virtual void stop();
00215 
00216         // Return infrormation about flow state.
00217         inline bool isActive() { return active; }
00218         inline bool isBound() { return sock != NULL; }
00219 
00220         // Stop flow and unbind from any currently bound remote endpoint.
00221         void unbind();
00222 
00223 protected:
00224 
00225         inline bool udpSend(QByteArray &pkt) const
00226                 { Q_ASSERT(active); return sock->send(remoteep, pkt); }
00227 
00228         virtual void receive(QByteArray &msg, const SocketEndpoint &src);
00229 
00230 signals:
00231         void received(QByteArray &msg, const SocketEndpoint &src);
00232 };
00233 
00234 
00235 // SocketReceiver is an abstract base class for control protocols
00236 // that need to multiplex onto Netsteria sockets:
00237 // e.g., the key exchange protocol (key*) and registration protocol (reg*).
00238 // A control protocol is identified by a 32-bit magic value,
00239 // whose topmost byte must be zero to distinguish it from flows.
00240 class SocketReceiver : public QObject
00241 {
00242         friend class Socket;
00243 
00244         SocketHostState *const h;
00245         quint32 mag;
00246 
00247 protected:
00248         void bind(quint32 magic);
00249         void unbind();
00250 
00251         inline bool isBound() { return mag != 0; }
00252         inline quint32 magic() { return mag; }
00253 
00254         // Socket calls this method to dispatch control messages.
00255         // The supplied XdrStream is positioned just after the
00256         // 4-byte magic value identifying the control protocol.
00257         virtual void receive(QByteArray &msg, XdrStream &ds,
00258                                 const SocketEndpoint &src) = 0;
00259 
00260         inline SocketReceiver(SocketHostState *h, QObject *parent = NULL)
00261                 : QObject(parent), h(h), mag(0) { }
00262         inline SocketReceiver(SocketHostState *h, quint32 magic,
00263                                 QObject *parent = NULL)
00264                 : QObject(parent), h(h), mag(0) { bind(magic); }
00265         virtual ~SocketReceiver();
00266 
00267 };
00268 
00269 
00274 class SocketHostState : public QObject
00275 {
00276         friend class Socket;
00277         friend class SocketReceiver;
00278 
00279         Q_OBJECT
00280 
00282         QList<Socket*> actsocks;
00283 
00285         QPointer<Socket> mainsock;
00286 
00289         QHash<quint32, SocketReceiver*> receivers;
00290 
00291 
00292 public:
00293         inline SocketHostState() : mainsock(NULL) { }
00294         virtual ~SocketHostState();
00295 
00302         inline QList<Socket*> activeSockets()
00303                 { return actsocks; }
00304 
00306         QList<Endpoint> activeLocalEndpoints();
00307 
00308         inline SocketReceiver *lookupReceiver(quint32 magic)
00309                 { return receivers.value(magic); }
00310 
00311 
00315         virtual Socket *newSocket(QObject *parent = NULL);
00316 
00329         Socket *initSocket(QSettings *settings = NULL,
00330                 int defaultport = NETSTERIA_DEFAULT_PORT);
00331 };
00332 
00333 } // namespace SST
00334 
00335 
00336 // Hash function for (Endpoint,Channel) tuples
00337 inline uint qHash(const QPair<SST::Endpoint,SST::Channel> fl)
00338         { return qHash(fl.first) + qHash(fl.second); }
00339 
00340 
00341 #endif  // SST_SOCK_H

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