tcp_content.cpp

Go to the documentation of this file.
00001 /* $Id$ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00014 #ifdef ENABLE_NETWORK
00015 
00016 #include "../../stdafx.h"
00017 #include "../../textfile_gui.h"
00018 #include "../../fileio_func.h"
00019 #include "../../newgrf_config.h"
00020 #include "../../base_media_base.h"
00021 #include "../../ai/ai.hpp"
00022 #include "../../game/game.hpp"
00023 #include "../../fios.h"
00024 #include "tcp_content.h"
00025 
00027 ContentInfo::ContentInfo()
00028 {
00029   memset(this, 0, sizeof(*this));
00030 }
00031 
00033 ContentInfo::~ContentInfo()
00034 {
00035   free(this->dependencies);
00036   free(this->tags);
00037 }
00038 
00043 void ContentInfo::TransferFrom(ContentInfo *other)
00044 {
00045   if (other != this) {
00046     free(this->dependencies);
00047     free(this->tags);
00048     memcpy(this, other, sizeof(ContentInfo));
00049     other->dependencies = NULL;
00050     other->tags = NULL;
00051   }
00052 }
00053 
00058 size_t ContentInfo::Size() const
00059 {
00060   size_t len = 0;
00061   for (uint i = 0; i < this->tag_count; i++) len += strlen(this->tags[i]) + 1;
00062 
00063   /* The size is never larger than the content info size plus the size of the
00064    * tags and dependencies */
00065   return sizeof(*this) +
00066       sizeof(this->dependency_count) +
00067       sizeof(*this->dependencies) * this->dependency_count;
00068 }
00069 
00074 bool ContentInfo::IsSelected() const
00075 {
00076   switch (this->state) {
00077     case ContentInfo::SELECTED:
00078     case ContentInfo::AUTOSELECTED:
00079     case ContentInfo::ALREADY_HERE:
00080       return true;
00081 
00082     default:
00083       return false;
00084   }
00085 }
00086 
00091 bool ContentInfo::IsValid() const
00092 {
00093   return this->state < ContentInfo::INVALID && this->type >= CONTENT_TYPE_BEGIN && this->type < CONTENT_TYPE_END;
00094 }
00095 
00101 const char *ContentInfo::GetTextfile(TextfileType type) const
00102 {
00103   if (this->state == INVALID) return NULL;
00104   const char *tmp;
00105   switch (this->type) {
00106     default: NOT_REACHED();
00107     case CONTENT_TYPE_AI:
00108       tmp = AI::GetScannerInfo()->FindMainScript(this, true);
00109       break;
00110     case CONTENT_TYPE_AI_LIBRARY:
00111       tmp = AI::GetScannerLibrary()->FindMainScript(this, true);
00112       break;
00113     case CONTENT_TYPE_GAME:
00114       tmp = Game::GetScannerInfo()->FindMainScript(this, true);
00115       break;
00116     case CONTENT_TYPE_GAME_LIBRARY:
00117       tmp = Game::GetScannerLibrary()->FindMainScript(this, true);
00118       break;
00119     case CONTENT_TYPE_NEWGRF: {
00120       const GRFConfig *gc = FindGRFConfig(BSWAP32(this->unique_id), FGCM_EXACT, this->md5sum);
00121       tmp = gc != NULL ? gc->filename : NULL;
00122       break;
00123     }
00124     case CONTENT_TYPE_BASE_GRAPHICS:
00125       tmp = TryGetBaseSetFile(this, true, BaseGraphics::GetAvailableSets());
00126       break;
00127     case CONTENT_TYPE_BASE_SOUNDS:
00128       tmp = TryGetBaseSetFile(this, true, BaseSounds::GetAvailableSets());
00129       break;
00130     case CONTENT_TYPE_BASE_MUSIC:
00131       tmp = TryGetBaseSetFile(this, true, BaseMusic::GetAvailableSets());
00132       break;
00133     case CONTENT_TYPE_SCENARIO:
00134     case CONTENT_TYPE_HEIGHTMAP:
00135       extern const char *FindScenario(const ContentInfo *ci, bool md5sum);
00136       tmp = FindScenario(this, true);
00137       break;
00138   }
00139   if (tmp == NULL) return NULL;
00140   return ::GetTextfile(type, GetContentInfoSubDir(this->type), tmp);
00141 }
00142 
00143 void NetworkContentSocketHandler::Close()
00144 {
00145   CloseConnection();
00146   if (this->sock == INVALID_SOCKET) return;
00147 
00148   closesocket(this->sock);
00149   this->sock = INVALID_SOCKET;
00150 }
00151 
00156 #define CONTENT_COMMAND(type) case type: return this->NetworkPacketReceive_ ## type ## _command(p); break;
00157 
00164 bool NetworkContentSocketHandler::HandlePacket(Packet *p)
00165 {
00166   PacketContentType type = (PacketContentType)p->Recv_uint8();
00167 
00168   switch (this->HasClientQuit() ? PACKET_CONTENT_END : type) {
00169     case PACKET_CONTENT_CLIENT_INFO_LIST:      return this->Receive_CLIENT_INFO_LIST(p);
00170     case PACKET_CONTENT_CLIENT_INFO_ID:        return this->Receive_CLIENT_INFO_ID(p);
00171     case PACKET_CONTENT_CLIENT_INFO_EXTID:     return this->Receive_CLIENT_INFO_EXTID(p);
00172     case PACKET_CONTENT_CLIENT_INFO_EXTID_MD5: return this->Receive_CLIENT_INFO_EXTID_MD5(p);
00173     case PACKET_CONTENT_SERVER_INFO:           return this->Receive_SERVER_INFO(p);
00174     case PACKET_CONTENT_CLIENT_CONTENT:        return this->Receive_CLIENT_CONTENT(p);
00175     case PACKET_CONTENT_SERVER_CONTENT:        return this->Receive_SERVER_CONTENT(p);
00176 
00177     default:
00178       if (this->HasClientQuit()) {
00179         DEBUG(net, 0, "[tcp/content] received invalid packet type %d from %s", type, this->client_addr.GetAddressAsString());
00180       } else {
00181         DEBUG(net, 0, "[tcp/content] received illegal packet from %s", this->client_addr.GetAddressAsString());
00182       }
00183       return false;
00184   }
00185 }
00186 
00190 void NetworkContentSocketHandler::ReceivePackets()
00191 {
00192   Packet *p;
00193   while ((p = this->ReceivePacket()) != NULL) {
00194     bool cont = this->HandlePacket(p);
00195     delete p;
00196     if (!cont) return;
00197   }
00198 }
00199 
00200 
00206 bool NetworkContentSocketHandler::ReceiveInvalidPacket(PacketContentType type)
00207 {
00208   DEBUG(net, 0, "[tcp/content] received illegal packet type %d from %s", type, this->client_addr.GetAddressAsString());
00209   return false;
00210 }
00211 
00212 bool NetworkContentSocketHandler::Receive_CLIENT_INFO_LIST(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CONTENT_CLIENT_INFO_LIST); }
00213 bool NetworkContentSocketHandler::Receive_CLIENT_INFO_ID(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CONTENT_CLIENT_INFO_ID); }
00214 bool NetworkContentSocketHandler::Receive_CLIENT_INFO_EXTID(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CONTENT_CLIENT_INFO_EXTID); }
00215 bool NetworkContentSocketHandler::Receive_CLIENT_INFO_EXTID_MD5(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CONTENT_CLIENT_INFO_EXTID_MD5); }
00216 bool NetworkContentSocketHandler::Receive_SERVER_INFO(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CONTENT_SERVER_INFO); }
00217 bool NetworkContentSocketHandler::Receive_CLIENT_CONTENT(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CONTENT_CLIENT_CONTENT); }
00218 bool NetworkContentSocketHandler::Receive_SERVER_CONTENT(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CONTENT_SERVER_CONTENT); }
00219 
00225 Subdirectory GetContentInfoSubDir(ContentType type)
00226 {
00227   switch (type) {
00228     default: return NO_DIRECTORY;
00229     case CONTENT_TYPE_AI:           return AI_DIR;
00230     case CONTENT_TYPE_AI_LIBRARY:   return AI_LIBRARY_DIR;
00231     case CONTENT_TYPE_GAME:         return GAME_DIR;
00232     case CONTENT_TYPE_GAME_LIBRARY: return GAME_LIBRARY_DIR;
00233     case CONTENT_TYPE_NEWGRF:       return NEWGRF_DIR;
00234 
00235     case CONTENT_TYPE_BASE_GRAPHICS:
00236     case CONTENT_TYPE_BASE_SOUNDS:
00237     case CONTENT_TYPE_BASE_MUSIC:
00238       return BASESET_DIR;
00239 
00240     case CONTENT_TYPE_SCENARIO:
00241     case CONTENT_TYPE_HEIGHTMAP:
00242       return SCENARIO_DIR;
00243   }
00244 }
00245 
00246 #endif /* ENABLE_NETWORK */