1 ////////////////////////////////////////////////////////////////////////////////
2 // Scorched3D (c) 2000-2011
3 //
4 // This file is part of Scorched3D.
5 //
6 // Scorched3D is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
10 //
11 // Scorched3D is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License along
17 // with this program; if not, write to the Free Software Foundation, Inc.,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 ////////////////////////////////////////////////////////////////////////////////
20
21 #include <coms/ComsMessageHandler.h>
22 #include <common/Defines.h>
23 #include <common/Logger.h>
24
~ComsMessageConnectionHandlerI()25 ComsMessageConnectionHandlerI::~ComsMessageConnectionHandlerI()
26 {
27 }
28
~ComsMessageHandlerI()29 ComsMessageHandlerI::~ComsMessageHandlerI()
30 {
31 }
32
ComsMessageHandler(const char * instanceName)33 ComsMessageHandler::ComsMessageHandler(const char *instanceName) :
34 instanceName_(instanceName),
35 connectionHandler_(0), comsMessageLogging_(false)
36 {
37 }
38
~ComsMessageHandler()39 ComsMessageHandler::~ComsMessageHandler()
40 {
41 }
42
setConnectionHandler(ComsMessageConnectionHandlerI * handler)43 void ComsMessageHandler::setConnectionHandler(
44 ComsMessageConnectionHandlerI *handler)
45 {
46 connectionHandler_ = handler;
47 }
48
addHandler(ComsMessageType & comsMessageType,ComsMessageHandlerI * handler)49 void ComsMessageHandler::addHandler(ComsMessageType &comsMessageType,
50 ComsMessageHandlerI *handler)
51 {
52 unsigned int id = comsMessageType.getId();
53 if (recvHandlers_.size() < id + 1) recvHandlers_.resize(id + 1);
54 recvHandlers_[id] = handler;
55 }
56
addSentHandler(ComsMessageType & comsMessageType,ComsMessageHandlerI * handler)57 void ComsMessageHandler::addSentHandler(ComsMessageType &comsMessageType,
58 ComsMessageHandlerI *handler)
59 {
60 unsigned int id = comsMessageType.getId();
61 if (sentHandlers_.size() < id + 1) sentHandlers_.resize(id + 1);
62 sentHandlers_[id] = handler;
63 }
64
processMessage(NetMessage & message)65 void ComsMessageHandler::processMessage(NetMessage &message)
66 {
67 switch(message.getMessageType())
68 {
69 case NetMessage::BufferMessage:
70 if (connectionHandler_)
71 connectionHandler_->messageRecv(message.getDestinationId());
72 processReceiveMessage(message);
73 break;
74 case NetMessage::SentMessage:
75 if (connectionHandler_)
76 connectionHandler_->messageSent(message.getDestinationId());
77 processSentMessage(message);
78 break;
79 case NetMessage::DisconnectMessage:
80 if (comsMessageLogging_)
81 {
82 Logger::log(S3D::formatStringBuffer("ComsMessage::Disconnected(%i, %i)",
83 message.getDestinationId(), message.getFlags()));
84 }
85
86 if (connectionHandler_)
87 connectionHandler_->clientDisconnected(message);
88 break;
89 case NetMessage::ConnectMessage:
90 if (comsMessageLogging_)
91 {
92 Logger::log(S3D::formatStringBuffer("ComsMessage::Connected(%i)",
93 message.getDestinationId()));
94 }
95
96 if (connectionHandler_)
97 connectionHandler_->clientConnected(message);
98 break;
99 default:
100 if (connectionHandler_)
101 connectionHandler_->clientError(message,
102 "Failed to recognise message type");
103 break;
104 }
105 }
106
processReceiveMessage(NetMessage & message)107 void ComsMessageHandler::processReceiveMessage(NetMessage &message)
108 {
109 processMessage(message, recvHandlers_, "RECV");
110 }
111
processSentMessage(NetMessage & message)112 void ComsMessageHandler::processSentMessage(NetMessage &message)
113 {
114 processMessage(message, sentHandlers_, "SEND");
115 }
116
processMessage(NetMessage & message,std::vector<ComsMessageHandlerI * > & handlers,const char * sendRecv)117 void ComsMessageHandler::processMessage(NetMessage &message,
118 std::vector<ComsMessageHandlerI *> &handlers,
119 const char *sendRecv)
120 {
121 if (handlers.empty()) return;
122
123 // Get how big the buffer is
124 unsigned int bufferUsed = message.getBuffer().getBufferUsed();
125 if (bufferUsed < 1)
126 {
127 if (connectionHandler_)
128 connectionHandler_->clientError(message,
129 S3D::formatStringBuffer("Failed to get %s message compression state", sendRecv));
130 }
131
132 // Check if the buffer is sent compressed
133 bool compressed = (message.getBuffer().getBuffer()[bufferUsed - 1] == '1');
134 message.getBuffer().setBufferUsed(bufferUsed - 1);
135 if (compressed)
136 {
137 if (!message.getBuffer().uncompressBuffer())
138 {
139 if (connectionHandler_)
140 connectionHandler_->clientError(message,
141 S3D::formatStringBuffer("Failed to uncompress %s message", sendRecv));
142 }
143 }
144 NetBufferReader reader(message.getBuffer());
145
146 unsigned char messageTypeId;
147 if (!reader.getFromBuffer(messageTypeId))
148 {
149 if (connectionHandler_)
150 connectionHandler_->clientError(message,
151 S3D::formatStringBuffer("Failed to decode %s message type", sendRecv));
152 return;
153 }
154 ComsMessageType *comsMessageType = ComsMessageType::getTypeForId(messageTypeId);
155 if (!comsMessageType)
156 {
157 if (connectionHandler_)
158 connectionHandler_->clientError(message,
159 S3D::formatStringBuffer("Failed to find %s message type %u",
160 sendRecv, messageTypeId));
161 return;
162 }
163 const char *messageTypeStr = comsMessageType->getName().c_str();
164
165 if (comsMessageLogging_)
166 {
167 Logger::log(S3D::formatStringBuffer("%s::process%s(%s, %i, %u%s)",
168 instanceName_.c_str(),
169 sendRecv,
170 messageTypeStr, message.getDestinationId(),
171 bufferUsed,
172 compressed?", compressed":""));
173 }
174 if (messageTypeId >= handlers.size())
175 {
176 if (connectionHandler_)
177 connectionHandler_->clientError(message,
178 S3D::formatStringBuffer("Failed to find %s message type handler \"%s\"",
179 sendRecv, messageTypeStr));
180 return;
181 }
182 ComsMessageHandlerI *handler = handlers[messageTypeId];
183 if (!handler)
184 {
185 if (connectionHandler_)
186 connectionHandler_->clientError(message,
187 S3D::formatStringBuffer("Failed to find %s message type handler \"%s\"",
188 sendRecv, messageTypeStr));
189 return;
190 }
191 if (!handler->processMessage(
192 message, messageTypeStr, reader))
193 {
194 if (connectionHandler_)
195 connectionHandler_->clientError(message,
196 S3D::formatStringBuffer("Failed to handle %s message type handler \"%s\"",
197 sendRecv, messageTypeStr));
198 return;
199 }
200
201 if (comsMessageLogging_)
202 {
203 Logger::log(S3D::formatStringBuffer("%s::processFinished%s(%s, %i)",
204 instanceName_.c_str(),
205 sendRecv,
206 messageTypeStr, message.getDestinationId()));
207 }
208 }
209