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