00001
00002
00003
00004
00005
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
00034
00035
00036 typedef quint8 Channel;
00037
00038
00039
00040
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
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
00151
00152 bool send(const Endpoint &ep, const char *data, int size);
00153
00154
00155
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
00170
00171
00172
00173 class SocketFlow : public QObject
00174 {
00175 friend class Socket;
00176 Q_OBJECT
00177
00178 private:
00179 Socket *sock;
00180 Endpoint remoteep;
00181 Channel localchan;
00182 Channel remotechan;
00183 bool active;
00184
00185 public:
00186 SocketFlow(QObject *parent = NULL);
00187 virtual ~SocketFlow();
00188
00189
00190
00191
00192 Channel bind(Socket *sock, const Endpoint &remoteep);
00193 inline Channel bind(const SocketEndpoint &remoteep)
00194 { return bind(remoteep.sock, remoteep); }
00195
00196
00197
00198 bool bind(Socket *sock, const Endpoint &remoteep, Channel chan);
00199
00200
00201
00202 inline void setRemoteChannel(Channel chan) { remotechan = chan; }
00203
00204
00205 inline SocketEndpoint remoteEndpoint()
00206 { return SocketEndpoint(remoteep, sock); }
00207
00208
00209 inline Channel localChannel() { return localchan; }
00210 inline Channel remoteChannel() { return remotechan; }
00211
00212
00213 virtual void start();
00214 virtual void stop();
00215
00216
00217 inline bool isActive() { return active; }
00218 inline bool isBound() { return sock != NULL; }
00219
00220
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
00236
00237
00238
00239
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
00255
00256
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 }
00334
00335
00336
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