-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmetadata_server.h
141 lines (122 loc) · 4.77 KB
/
metadata_server.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#ifndef METADATA_SERVER_H
#define METADATA_SERVER_H
// ------------------------------------------------------------------------------------------------------------------
#include "metadata.h"
#include "port_discovery.h"
#include <QObject>
#include <QHostAddress>
#include <QTimer>
// ------------------------------------------------------------------------------------------------------------------
class QTcpServer;
class CUdpHolePunchingServer;
// ------------------------------------------------------------------------------------------------------------------
class IMetadataServer : public QObject
{
Q_OBJECT
public:
IMetadataServer(QObject* parent, uint16_t port);
virtual void createChannel(QString name, QString password) = 0;
virtual QList<ChannelMetadata> channels() const = 0;
virtual bool start() = 0;
uint16_t port() const { return m_Port; }
private:
uint16_t m_Port;
};
// ------------------------------------------------------------------------------------------------------------------
/*
Diese Klasse stellt einen Wrapper um ein Socket (Client) dar, damit sich die Server-Klasse darum nicht kümmern muss.
Die Klasse speichert auch den aktuellen Channel sowie den Usernamen
*/
class CSimpleMetadataUserSocketInformation : public QObject
{
Q_OBJECT
public:
enum class UserState
{
VALID,
WAITING_FOR_DISCOVERY,
WAITING_FOR_IDENTIFICATION
};
CSimpleMetadataUserSocketInformation(QObject* parent, QTcpSocket *socket);
QTcpSocket* socket() { return m_Socket; }
QString username() const { return m_Username; }
QString channel() const { return m_Channel; }
UserState state() const { return m_State; }
void setUsername(QString username) { this->m_Username = username; }
void setState(UserState state) { this->m_State = state; }
void setChannel(QString channel) { this->m_Channel = channel; }
UserMetadata metadata() const
{
UserMetadata md;
md.username = m_Username;
md.channelName = m_Channel;
md.host = m_LastDiscoveryResult.address;
md.port = m_LastDiscoveryResult.port;
return md;
}
void startDiscovery(uint16_t port);
public slots:
void onSocketReadyRead();
void onSocketError(QAbstractSocket::SocketError error);
void onDiscoverySuccessful(DiscoveryResult result);
signals:
void userSocketReadyRead();
void userSocketError(QAbstractSocket::SocketError error);
void discoverySuccessful(DiscoveryResult result);
private:
CUdpHolePunchingServer* m_HolePunchingServer;
QTcpSocket *m_Socket;
QString m_Username;
QString m_Channel;
UserState m_State;
DiscoveryResult m_LastDiscoveryResult;
};
// ------------------------------------------------------------------------------------------------------------------
class CSimpleMetadataServer : public IMetadataServer
{
Q_OBJECT
public:
CSimpleMetadataServer(QObject* parent, uint16_t port);
virtual void createChannel(QString name, QString password);
virtual QList<ChannelMetadata> channels() const;
virtual bool start() override;
ChannelMetadata* getChannel(QString name);
CSimpleMetadataUserSocketInformation* findInfoWithUsername(QString name);
private:
template<typename T>
void sendToAllClients(T &data)
{
for (auto &socket : m_ConnectedClients)
{
if (socket->state() == CSimpleMetadataUserSocketInformation::UserState::VALID)
writeToSocket(socket->socket(), data);
}
}
template<typename T>
void sendToAllClientsInChannel(T &data, QString channel)
{
for (auto &socket : m_ConnectedClients)
{
if (socket->state() == CSimpleMetadataUserSocketInformation::UserState::VALID &&
socket->channel() == channel)
writeToSocket(socket->socket(), data);
}
}
void handleIdentificationAction(CSimpleMetadataUserSocketInformation *info, QDataStream &stream);
void handleConnectAction(CSimpleMetadataUserSocketInformation *info, QDataStream &stream);
void handleOverviewAction(CSimpleMetadataUserSocketInformation *info, QDataStream &stream);
void handleDisconnectAction(CSimpleMetadataUserSocketInformation *info, QDataStream &stream);
private slots:
void onIncommingConnection();
void onUserSocketError(QAbstractSocket::SocketError error);
void userSocketReayRead();
void onClientDiscoverySuccessful(DiscoveryResult result);
void onHeartbeatTimerTimeout();
private:
QTimer m_ServerHeatbeatTimer{this};
QTcpServer* m_Server;
QList<CSimpleMetadataUserSocketInformation*> m_ConnectedClients;
QMap<QString, ChannelMetadata> m_OwnedChannels;
};
// ------------------------------------------------------------------------------------------------------------------
#endif