00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <net/NetServerTCPRead.h>
00022 #include <net/NetServerTCP.h>
00023 #include <net/NetMessagePool.h>
00024 #include <common/Clock.h>
00025 #include <common/Logger.h>
00026 #include <common/Defines.h>
00027
00028 NetServerTCPRead::NetServerTCPRead(unsigned int id,
00029 TCPsocket socket,
00030 NetServerTCPProtocol *protocol,
00031 NetMessageHandler *messageHandler,
00032 bool *checkDeleted) :
00033 id_(id),
00034 socket_(socket), sockSet_(0), protocol_(protocol),
00035 outgoingMessagesMutex_(0), checkDeleted_(checkDeleted),
00036 disconnect_(false), messageHandler_(messageHandler),
00037 sentDisconnect_(false), startCount_(0),
00038 ctrlThread_(0), recvThread_(0), sendThread_(0)
00039 {
00040 sockSet_ = SDLNet_AllocSocketSet(1);
00041 SDLNet_TCP_AddSocket(sockSet_, socket);
00042 outgoingMessagesMutex_ = SDL_CreateMutex();
00043 }
00044
00045 NetServerTCPRead::~NetServerTCPRead()
00046 {
00047 SDL_LockMutex(outgoingMessagesMutex_);
00048 while (!newMessages_.empty())
00049 {
00050 NetMessage *message = newMessages_.front();
00051 newMessages_.pop_front();
00052 NetMessagePool::instance()->addToPool(message);
00053 }
00054 SDL_UnlockMutex(outgoingMessagesMutex_);
00055
00056 SDL_DestroyMutex(outgoingMessagesMutex_);
00057 outgoingMessagesMutex_ = 0;
00058 SDLNet_FreeSocketSet(sockSet_);
00059 sockSet_ = 0;
00060 }
00061
00062 unsigned int NetServerTCPRead::getIpAddressFromSocket(TCPsocket socket)
00063 {
00064 unsigned int addr = 0;
00065 IPaddress *address = SDLNet_TCP_GetPeerAddress(socket);
00066 if (address)
00067 {
00068 addr = SDLNet_Read32(&address->host);
00069 }
00070 return addr;
00071 }
00072
00073 unsigned int NetServerTCPRead::getIpAddress()
00074 {
00075 return getIpAddressFromSocket(socket_);
00076 }
00077
00078 void NetServerTCPRead::start()
00079 {
00080
00081 NetMessage *message = NetMessagePool::instance()->
00082 getFromPool(NetMessage::ConnectMessage,
00083 id_,
00084 getIpAddress());
00085 messageHandler_->addMessage(message);
00086
00087 recvThread_ = SDL_CreateThread(
00088 NetServerTCPRead::recvThreadFunc, (void *) this);
00089 sendThread_ = SDL_CreateThread(
00090 NetServerTCPRead::sendThreadFunc, (void *) this);
00091 ctrlThread_ = SDL_CreateThread(
00092 NetServerTCPRead::ctrlThreadFunc, (void *) this);
00093 if (!ctrlThread_ || !recvThread_ || !sendThread_)
00094 {
00095 Logger::log( "ERROR: Run out of threads");
00096 }
00097 }
00098
00099 void NetServerTCPRead::addMessage(NetMessage *message)
00100 {
00101 if (message->getMessageType() != NetMessage::DisconnectMessage &&
00102 message->getBuffer().getBuffer() == 0)
00103 {
00104 DIALOG_ASSERT(0);
00105 }
00106
00107 SDL_LockMutex(outgoingMessagesMutex_);
00108 newMessages_.push_back(message);
00109 if (message->getMessageType() == NetMessage::DisconnectMessage &&
00110 !sentDisconnect_)
00111 {
00112 sentDisconnect_ = true;
00113 NetMessage *message = NetMessagePool::instance()->
00114 getFromPool(NetMessage::DisconnectMessage,
00115 id_,
00116 getIpAddress());
00117 messageHandler_->addMessage(message);
00118 }
00119 SDL_UnlockMutex(outgoingMessagesMutex_);
00120 }
00121
00122 bool NetServerTCPRead::getDisconnect()
00123 {
00124 SDL_LockMutex(outgoingMessagesMutex_);
00125 bool result = disconnect_;
00126 SDL_UnlockMutex(outgoingMessagesMutex_);
00127
00128 if (result)
00129 {
00130 int status = 0;
00131 SDL_WaitThread(ctrlThread_, &status);
00132 }
00133 return result;
00134 }
00135
00136 int NetServerTCPRead::ctrlThreadFunc(void *netServerTCPRead)
00137 {
00138 NetServerTCPRead *ns = (NetServerTCPRead *) netServerTCPRead;
00139 ns->actualCtrlThreadFunc();
00140 return 0;
00141 }
00142
00143 int NetServerTCPRead::sendThreadFunc(void *netServerTCPRead)
00144 {
00145 NetServerTCPRead *ns = (NetServerTCPRead *) netServerTCPRead;
00146 ns->actualSendRecvThreadFunc(true);
00147 return 0;
00148 }
00149
00150 int NetServerTCPRead::recvThreadFunc(void *netServerTCPRead)
00151 {
00152 NetServerTCPRead *ns = (NetServerTCPRead *) netServerTCPRead;
00153 ns->actualSendRecvThreadFunc(false);
00154 return 0;
00155 }
00156
00157 void NetServerTCPRead::actualCtrlThreadFunc()
00158 {
00159
00160 bool done = false;
00161 while (!done)
00162 {
00163 SDL_LockMutex(outgoingMessagesMutex_);
00164 if (startCount_ == 2) done = true;
00165 SDL_UnlockMutex(outgoingMessagesMutex_);
00166 SDL_Delay(100);
00167 }
00168
00169
00170 int status;
00171 SDL_WaitThread(sendThread_, &status);
00172 SDL_WaitThread(recvThread_, &status);
00173
00174
00175 SDLNet_TCP_Close(socket_);
00176
00177
00178 SDL_LockMutex(outgoingMessagesMutex_);
00179 disconnect_ = true;
00180 *checkDeleted_ = true;
00181 SDL_UnlockMutex(outgoingMessagesMutex_);
00182 }
00183
00184 void NetServerTCPRead::actualSendRecvThreadFunc(bool send)
00185 {
00186 SDL_LockMutex(outgoingMessagesMutex_);
00187 startCount_++;
00188 SDL_UnlockMutex(outgoingMessagesMutex_);
00189
00190 Clock netClock;
00191 while (!sentDisconnect_)
00192 {
00193 netClock.getTimeDifference();
00194
00195 if (send)
00196 {
00197 if (!pollOutgoing()) break;
00198 }
00199 else
00200 {
00201 if (!pollIncoming()) break;
00202 }
00203
00204 float timeDiff = netClock.getTimeDifference();
00205 if (timeDiff > 15.0f)
00206 {
00207 Logger::log(S3D::formatStringBuffer(
00208 "Warning: %s net loop took %.2f seconds, client %u",
00209 (send?"Send":"Recv"),
00210 timeDiff, id_));
00211 }
00212 }
00213
00214 SDL_LockMutex(outgoingMessagesMutex_);
00215 if (!sentDisconnect_)
00216 {
00217 sentDisconnect_ = true;
00218 NetMessage *message = NetMessagePool::instance()->
00219 getFromPool(NetMessage::DisconnectMessage,
00220 id_,
00221 getIpAddress());
00222 messageHandler_->addMessage(message);
00223 }
00224 SDL_UnlockMutex(outgoingMessagesMutex_);
00225 }
00226
00227 bool NetServerTCPRead::pollIncoming()
00228 {
00229 int numready = SDLNet_CheckSockets(sockSet_, 100);
00230 if (numready == -1) return false;
00231 if (numready == 0)
00232 {
00233 SDL_Delay(10);
00234 return true;
00235 }
00236
00237 if(SDLNet_SocketReady(socket_))
00238 {
00239 NetMessage *message = protocol_->readBuffer(socket_, id_);
00240 if (!message)
00241 {
00242
00243 return false;
00244 }
00245 else
00246 {
00247 if (!sentDisconnect_)
00248 {
00249
00250 messageHandler_->addMessage(message);
00251 }
00252 else
00253 {
00254 NetMessagePool::instance()->addToPool(message);
00255 }
00256 }
00257 }
00258
00259 return true;
00260 }
00261
00262 bool NetServerTCPRead::pollOutgoing()
00263 {
00264 NetMessage *message = 0;
00265 SDL_LockMutex(outgoingMessagesMutex_);
00266 if (!newMessages_.empty())
00267 {
00268 message = newMessages_.front();
00269 newMessages_.pop_front();
00270 }
00271 SDL_UnlockMutex(outgoingMessagesMutex_);
00272
00273 bool result = true;
00274 if (message)
00275 {
00276 if (message->getMessageType() == NetMessage::DisconnectMessage)
00277 {
00278 result = false;
00279 }
00280 else
00281 {
00282 if (!protocol_->sendBuffer(message->getBuffer(), socket_, id_))
00283 {
00284 Logger::log( "Failed to send message to client");
00285 result = false;
00286 }
00287 }
00288 message->setType(NetMessage::SentMessage);
00289 messageHandler_->addMessage(message);
00290 }
00291 else SDL_Delay(100);
00292
00293 return result;
00294 }