1 #include "abstractclient.h"
2
3 #include "client_metatypes.h"
4 #include "featureset.h"
5 #include "get_pb_extension.h"
6 #include "pb/commands.pb.h"
7 #include "pb/event_add_to_list.pb.h"
8 #include "pb/event_connection_closed.pb.h"
9 #include "pb/event_game_joined.pb.h"
10 #include "pb/event_list_rooms.pb.h"
11 #include "pb/event_notify_user.pb.h"
12 #include "pb/event_remove_from_list.pb.h"
13 #include "pb/event_replay_added.pb.h"
14 #include "pb/event_server_identification.pb.h"
15 #include "pb/event_server_message.pb.h"
16 #include "pb/event_server_shutdown.pb.h"
17 #include "pb/event_user_joined.pb.h"
18 #include "pb/event_user_left.pb.h"
19 #include "pb/event_user_message.pb.h"
20 #include "pb/server_message.pb.h"
21 #include "pending_command.h"
22
23 #include <google/protobuf/descriptor.h>
24
AbstractClient(QObject * parent)25 AbstractClient::AbstractClient(QObject *parent) : QObject(parent), nextCmdId(0), status(StatusDisconnected)
26 {
27 qRegisterMetaType<QVariant>("QVariant");
28 qRegisterMetaType<CommandContainer>("CommandContainer");
29 qRegisterMetaType<Response>("Response");
30 qRegisterMetaType<Response::ResponseCode>("Response::ResponseCode");
31 qRegisterMetaType<ClientStatus>("ClientStatus");
32 qRegisterMetaType<RoomEvent>("RoomEvent");
33 qRegisterMetaType<GameEventContainer>("GameEventContainer");
34 qRegisterMetaType<Event_ServerIdentification>("Event_ServerIdentification");
35 qRegisterMetaType<Event_ConnectionClosed>("Event_ConnectionClosed");
36 qRegisterMetaType<Event_ServerShutdown>("Event_ServerShutdown");
37 qRegisterMetaType<Event_AddToList>("Event_AddToList");
38 qRegisterMetaType<Event_RemoveFromList>("Event_RemoveFromList");
39 qRegisterMetaType<Event_UserJoined>("Event_UserJoined");
40 qRegisterMetaType<Event_UserLeft>("Event_UserLeft");
41 qRegisterMetaType<Event_ServerMessage>("Event_ServerMessage");
42 qRegisterMetaType<Event_ListRooms>("Event_ListRooms");
43 qRegisterMetaType<Event_GameJoined>("Event_GameJoined");
44 qRegisterMetaType<Event_UserMessage>("Event_UserMessage");
45 qRegisterMetaType<Event_NotifyUser>("Event_NotifyUser");
46 qRegisterMetaType<ServerInfo_User>("ServerInfo_User");
47 qRegisterMetaType<QList<ServerInfo_User>>("QList<ServerInfo_User>");
48 qRegisterMetaType<Event_ReplayAdded>("Event_ReplayAdded");
49 qRegisterMetaType<QList<QString>>("missingFeatures");
50
51 FeatureSet features;
52 features.initalizeFeatureList(clientFeatures);
53
54 connect(this, SIGNAL(sigQueuePendingCommand(PendingCommand *)), this, SLOT(queuePendingCommand(PendingCommand *)));
55 }
56
~AbstractClient()57 AbstractClient::~AbstractClient()
58 {
59 }
60
processProtocolItem(const ServerMessage & item)61 void AbstractClient::processProtocolItem(const ServerMessage &item)
62 {
63 switch (item.message_type()) {
64 case ServerMessage::RESPONSE: {
65 const Response &response = item.response();
66 const int cmdId = response.cmd_id();
67
68 PendingCommand *pend = pendingCommands.value(cmdId, 0);
69 if (!pend)
70 return;
71 pendingCommands.remove(cmdId);
72
73 pend->processResponse(response);
74 pend->deleteLater();
75 break;
76 }
77 case ServerMessage::SESSION_EVENT: {
78 const SessionEvent &event = item.session_event();
79 switch ((SessionEvent::SessionEventType)getPbExtension(event)) {
80 case SessionEvent::SERVER_IDENTIFICATION:
81 emit serverIdentificationEventReceived(event.GetExtension(Event_ServerIdentification::ext));
82 break;
83 case SessionEvent::SERVER_MESSAGE:
84 emit serverMessageEventReceived(event.GetExtension(Event_ServerMessage::ext));
85 break;
86 case SessionEvent::SERVER_SHUTDOWN:
87 emit serverShutdownEventReceived(event.GetExtension(Event_ServerShutdown::ext));
88 break;
89 case SessionEvent::CONNECTION_CLOSED:
90 emit connectionClosedEventReceived(event.GetExtension(Event_ConnectionClosed::ext));
91 break;
92 case SessionEvent::USER_MESSAGE:
93 emit userMessageEventReceived(event.GetExtension(Event_UserMessage::ext));
94 break;
95 case SessionEvent::NOTIFY_USER:
96 emit notifyUserEventReceived(event.GetExtension(Event_NotifyUser::ext));
97 break;
98 case SessionEvent::LIST_ROOMS:
99 emit listRoomsEventReceived(event.GetExtension(Event_ListRooms::ext));
100 break;
101 case SessionEvent::ADD_TO_LIST:
102 emit addToListEventReceived(event.GetExtension(Event_AddToList::ext));
103 break;
104 case SessionEvent::REMOVE_FROM_LIST:
105 emit removeFromListEventReceived(event.GetExtension(Event_RemoveFromList::ext));
106 break;
107 case SessionEvent::USER_JOINED:
108 emit userJoinedEventReceived(event.GetExtension(Event_UserJoined::ext));
109 break;
110 case SessionEvent::USER_LEFT:
111 emit userLeftEventReceived(event.GetExtension(Event_UserLeft::ext));
112 break;
113 case SessionEvent::GAME_JOINED:
114 emit gameJoinedEventReceived(event.GetExtension(Event_GameJoined::ext));
115 break;
116 case SessionEvent::REPLAY_ADDED:
117 emit replayAddedEventReceived(event.GetExtension(Event_ReplayAdded::ext));
118 break;
119 default:
120 break;
121 }
122 break;
123 }
124 case ServerMessage::GAME_EVENT_CONTAINER: {
125 emit gameEventContainerReceived(item.game_event_container());
126 break;
127 }
128 case ServerMessage::ROOM_EVENT: {
129 emit roomEventReceived(item.room_event());
130 break;
131 }
132 }
133 }
134
setStatus(const ClientStatus _status)135 void AbstractClient::setStatus(const ClientStatus _status)
136 {
137 QMutexLocker locker(&clientMutex);
138 if (_status != status) {
139 status = _status;
140 emit statusChanged(_status);
141 }
142 }
143
sendCommand(const CommandContainer & cont)144 void AbstractClient::sendCommand(const CommandContainer &cont)
145 {
146 sendCommand(new PendingCommand(cont));
147 }
148
sendCommand(PendingCommand * pend)149 void AbstractClient::sendCommand(PendingCommand *pend)
150 {
151 pend->moveToThread(thread());
152 emit sigQueuePendingCommand(pend);
153 }
154
queuePendingCommand(PendingCommand * pend)155 void AbstractClient::queuePendingCommand(PendingCommand *pend)
156 {
157 // This function is always called from the client thread via signal/slot.
158 const int cmdId = getNewCmdId();
159 pend->getCommandContainer().set_cmd_id(cmdId);
160
161 pendingCommands.insert(cmdId, pend);
162
163 sendCommandContainer(pend->getCommandContainer());
164 }
165
prepareSessionCommand(const::google::protobuf::Message & cmd)166 PendingCommand *AbstractClient::prepareSessionCommand(const ::google::protobuf::Message &cmd)
167 {
168 CommandContainer cont;
169 SessionCommand *c = cont.add_session_command();
170 c->GetReflection()->MutableMessage(c, cmd.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(cmd);
171 return new PendingCommand(cont);
172 }
173
prepareRoomCommand(const::google::protobuf::Message & cmd,int roomId)174 PendingCommand *AbstractClient::prepareRoomCommand(const ::google::protobuf::Message &cmd, int roomId)
175 {
176 CommandContainer cont;
177 RoomCommand *c = cont.add_room_command();
178 cont.set_room_id(roomId);
179 c->GetReflection()->MutableMessage(c, cmd.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(cmd);
180 return new PendingCommand(cont);
181 }
182
prepareModeratorCommand(const::google::protobuf::Message & cmd)183 PendingCommand *AbstractClient::prepareModeratorCommand(const ::google::protobuf::Message &cmd)
184 {
185 CommandContainer cont;
186 ModeratorCommand *c = cont.add_moderator_command();
187 c->GetReflection()->MutableMessage(c, cmd.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(cmd);
188 return new PendingCommand(cont);
189 }
190
prepareAdminCommand(const::google::protobuf::Message & cmd)191 PendingCommand *AbstractClient::prepareAdminCommand(const ::google::protobuf::Message &cmd)
192 {
193 CommandContainer cont;
194 AdminCommand *c = cont.add_admin_command();
195 c->GetReflection()->MutableMessage(c, cmd.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(cmd);
196 return new PendingCommand(cont);
197 }
198