#ifndef SOCKET_H #define SOCKET_H #include #include #include #include class PacketReader; enum { C2B_OOB_Login = 0x80000001, B2C_OOB_LoginSuccess = 0x80000001, B2C_OOB_LoginFailed = 0x80000002, C2B_ConsoleInput = 1, B2C_ConsoleOutput = 1 }; struct Packet { int id; quint32 type; QByteArray data; Packet(quint32 type_) { type = type_; } Packet(quint32 type_, const QByteArray &data_) { type = type_; data = data_; } bool isOutOfBand() const { return ((type & 0x80000000) != 0); } }; class Socket : public QObject { Q_OBJECT public: enum { SessionKeySize = 64, MaxConsoleStringSize = 2000, ProtocolVersion = 1 }; explicit Socket(QObject *parent = 0); ~Socket(); void setup(QTcpSocket *socket); const quint8 *sessionKey() const { return m_sessionKey; } signals: void finished(); // Socket management protected: void unlinkSocket(bool disconnect); virtual void takeOverSocket(Socket *donor); protected slots: virtual void socketConnected(); private slots: void socketReceived(); void socketError(QAbstractSocket::SocketError error); void socketDisconnected(); protected: QTcpSocket *socket() const { return m_socket; } private: QTcpSocket *m_socket; QByteArray m_readBuffer; void sendPacketOverSocket(const Packet &packet); protected: // Connection state int m_handshakeStatus; bool m_identified; quint8 m_sessionKey[SessionKeySize]; // Packets system public: void sendPacket(Packet &packet, bool isHandshakePacket = false); protected: virtual void handlePacket(int type, PacketReader &reader); void flushPacketCache(); void clearAcknowledgedPackets(int lastReceivedID); int lastReceivedPacketID() const { return m_lastReceivedPacketID; } private: QList m_packetCache; int m_lastSentPacketID; int m_lastReceivedPacketID; }; #endif // CLIENT_H