00001
00002
00005 #if defined(ENABLE_NETWORK)
00006
00007 #include "../stdafx.h"
00008 #include "../rev.h"
00009 #include "../fileio_func.h"
00010 #include "../string_func.h"
00011 #include "../ai/ai.hpp"
00012 #include "../window_func.h"
00013 #include "../gui.h"
00014 #include "../variables.h"
00015 #include "network_content.h"
00016
00017 #include "table/strings.h"
00018
00019 #if defined(WITH_ZLIB)
00020 #include <zlib.h>
00021 #endif
00022
00023 extern bool TarListAddFile(const char *filename);
00024 extern bool HasGraphicsSet(const ContentInfo *ci, bool md5sum);
00025 extern bool HasScenario(const ContentInfo *ci, bool md5sum);
00026 ClientNetworkContentSocketHandler _network_content_client;
00027
00029 static bool HasGRFConfig(const ContentInfo *ci, bool md5sum)
00030 {
00031 return FindGRFConfig(BSWAP32(ci->unique_id), md5sum ? ci->md5sum : NULL) != NULL;
00032 }
00033
00041 typedef bool (*HasProc)(const ContentInfo *ci, bool md5sum);
00042
00043 DEF_CONTENT_RECEIVE_COMMAND(Client, PACKET_CONTENT_SERVER_INFO)
00044 {
00045 ContentInfo *ci = new ContentInfo();
00046 ci->type = (ContentType)p->Recv_uint8();
00047 ci->id = (ContentID)p->Recv_uint32();
00048 ci->filesize = p->Recv_uint32();
00049
00050 p->Recv_string(ci->name, lengthof(ci->name));
00051 p->Recv_string(ci->version, lengthof(ci->name));
00052 p->Recv_string(ci->url, lengthof(ci->url));
00053 p->Recv_string(ci->description, lengthof(ci->description), true);
00054
00055 ci->unique_id = p->Recv_uint32();
00056 for (uint j = 0; j < sizeof(ci->md5sum); j++) {
00057 ci->md5sum[j] = p->Recv_uint8();
00058 }
00059
00060 ci->dependency_count = p->Recv_uint8();
00061 ci->dependencies = MallocT<ContentID>(ci->dependency_count);
00062 for (uint i = 0; i < ci->dependency_count; i++) ci->dependencies[i] = (ContentID)p->Recv_uint32();
00063
00064 ci->tag_count = p->Recv_uint8();
00065 ci->tags = MallocT<char[32]>(ci->tag_count);
00066 for (uint i = 0; i < ci->tag_count; i++) p->Recv_string(ci->tags[i], lengthof(*ci->tags));
00067
00068 if (!ci->IsValid()) {
00069 delete ci;
00070 this->Close();
00071 return false;
00072 }
00073
00074
00075 HasProc proc = NULL;
00076 switch (ci->type) {
00077 case CONTENT_TYPE_NEWGRF:
00078 proc = HasGRFConfig;
00079 break;
00080
00081 case CONTENT_TYPE_BASE_GRAPHICS:
00082 proc = HasGraphicsSet;
00083 break;
00084
00085 case CONTENT_TYPE_AI:
00086 case CONTENT_TYPE_AI_LIBRARY:
00087 proc = AI::HasAI; break;
00088 break;
00089
00090 case CONTENT_TYPE_SCENARIO:
00091 case CONTENT_TYPE_HEIGHTMAP:
00092 proc = HasScenario;
00093 break;
00094
00095 default:
00096 break;
00097 }
00098
00099 if (proc != NULL) {
00100 if (proc(ci, true)) {
00101 ci->state = ContentInfo::ALREADY_HERE;
00102 } else {
00103 ci->state = ContentInfo::UNSELECTED;
00104 if (proc(ci, false)) ci->upgrade = true;
00105 }
00106 } else {
00107 ci->state = ContentInfo::UNSELECTED;
00108 }
00109
00110
00111 if (ci->state == ContentInfo::UNSELECTED && ci->filesize == 0) ci->state = ContentInfo::DOES_NOT_EXIST;
00112
00113
00114 for (ContentIterator iter = this->infos.Begin(); iter != this->infos.End(); iter++) {
00115 ContentInfo *ici = *iter;
00116 if (ici->type == ci->type && ici->unique_id == ci->unique_id &&
00117 memcmp(ci->md5sum, ici->md5sum, sizeof(ci->md5sum)) == 0) {
00118
00119 if (StrEmpty(ci->name)) strecpy(ci->name, ici->name, lastof(ci->name));
00120 if (ici->IsSelected()) ci->state = ici->state;
00121
00122 delete ici;
00123 *iter = ci;
00124
00125 this->OnReceiveContentInfo(ci);
00126 return true;
00127 }
00128 }
00129
00130
00131 if (ci->filesize == 0) {
00132 delete ci;
00133 return true;
00134 }
00135
00136 *this->infos.Append() = ci;
00137
00138
00139 for (ContentIterator iter = this->infos.Begin(); iter != this->infos.End(); iter++) {
00140 this->CheckDependencyState(*iter);
00141 }
00142
00143 this->OnReceiveContentInfo(ci);
00144
00145 return true;
00146 }
00147
00148 void ClientNetworkContentSocketHandler::RequestContentList(ContentType type)
00149 {
00150 if (type == CONTENT_TYPE_END) {
00151 this->RequestContentList(CONTENT_TYPE_BASE_GRAPHICS);
00152 this->RequestContentList(CONTENT_TYPE_SCENARIO);
00153 this->RequestContentList(CONTENT_TYPE_HEIGHTMAP);
00154 this->RequestContentList(CONTENT_TYPE_AI);
00155 this->RequestContentList(CONTENT_TYPE_NEWGRF);
00156 this->RequestContentList(CONTENT_TYPE_AI_LIBRARY);
00157 return;
00158 }
00159
00160 this->Connect();
00161
00162 Packet *p = new Packet(PACKET_CONTENT_CLIENT_INFO_LIST);
00163 p->Send_uint8 ((byte)type);
00164 p->Send_uint32(_openttd_newgrf_version);
00165
00166 this->Send_Packet(p);
00167 }
00168
00169 void ClientNetworkContentSocketHandler::RequestContentList(uint count, const ContentID *content_ids)
00170 {
00171 this->Connect();
00172
00173 while (count > 0) {
00174
00175
00176
00177
00178
00179 uint p_count = min(count, (SEND_MTU - sizeof(PacketSize) - sizeof(byte) - sizeof(byte) - sizeof(uint16)) / sizeof(uint32));
00180
00181 Packet *p = new Packet(PACKET_CONTENT_CLIENT_INFO_ID);
00182 p->Send_uint16(p_count);
00183
00184 for (uint i = 0; i < p_count; i++) {
00185 p->Send_uint32(content_ids[i]);
00186 }
00187
00188 this->Send_Packet(p);
00189 count -= p_count;
00190 content_ids += count;
00191 }
00192 }
00193
00194 void ClientNetworkContentSocketHandler::RequestContentList(ContentVector *cv, bool send_md5sum)
00195 {
00196 if (cv == NULL) return;
00197
00198 this->Connect();
00199
00200
00201 assert(cv->Length() < 255);
00202 assert(cv->Length() < (SEND_MTU - sizeof(PacketSize) - sizeof(byte) - sizeof(uint8)) / (send_md5sum ? 20 : sizeof(uint32)));
00203
00204 Packet *p = new Packet(send_md5sum ? PACKET_CONTENT_CLIENT_INFO_EXTID_MD5 : PACKET_CONTENT_CLIENT_INFO_EXTID);
00205 p->Send_uint8(cv->Length());
00206
00207 for (ContentIterator iter = cv->Begin(); iter != cv->End(); iter++) {
00208 const ContentInfo *ci = *iter;
00209 p->Send_uint8((byte)ci->type);
00210 p->Send_uint32(ci->unique_id);
00211 if (!send_md5sum) continue;
00212
00213 for (uint j = 0; j < sizeof(ci->md5sum); j++) {
00214 p->Send_uint8(ci->md5sum[j]);
00215 }
00216 }
00217
00218 this->Send_Packet(p);
00219
00220 for (ContentIterator iter = cv->Begin(); iter != cv->End(); iter++) {
00221 ContentInfo *ci = *iter;
00222 bool found = false;
00223 for (ContentIterator iter2 = this->infos.Begin(); iter2 != this->infos.End(); iter2++) {
00224 ContentInfo *ci2 = *iter2;
00225 if (ci->type == ci2->type && ci->unique_id == ci2->unique_id &&
00226 (!send_md5sum || memcmp(ci->md5sum, ci2->md5sum, sizeof(ci->md5sum)) == 0)) {
00227 found = true;
00228 break;
00229 }
00230 }
00231 if (!found) {
00232 *this->infos.Append() = ci;
00233 } else {
00234 delete ci;
00235 }
00236 }
00237 }
00238
00239 void ClientNetworkContentSocketHandler::DownloadSelectedContent(uint &files, uint &bytes)
00240 {
00241 files = 0;
00242 bytes = 0;
00243
00245 ContentID *ids = MallocT<ContentID>(infos.Length());
00246 for (ContentIterator iter = infos.Begin(); iter != infos.End(); iter++) {
00247 const ContentInfo *ci = *iter;
00248 if (!ci->IsSelected()) continue;
00249
00250 ids[files++] = ci->id;
00251 bytes += ci->filesize;
00252 }
00253
00254 uint count = files;
00255 ContentID *content_ids = ids;
00256 this->Connect();
00257
00258 while (count > 0) {
00259
00260
00261
00262
00263 uint p_count = min(count, (SEND_MTU - sizeof(PacketSize) - sizeof(byte) - sizeof(uint16)) / sizeof(uint32));
00264
00265 Packet *p = new Packet(PACKET_CONTENT_CLIENT_CONTENT);
00266 p->Send_uint16(p_count);
00267
00268 for (uint i = 0; i < p_count; i++) {
00269 p->Send_uint32(content_ids[i]);
00270 }
00271
00272 this->Send_Packet(p);
00273 count -= p_count;
00274 content_ids += count;
00275 }
00276
00277 free(ids);
00278 }
00279
00287 static char *GetFullFilename(const ContentInfo *ci, bool compressed)
00288 {
00289 Subdirectory dir;
00290 switch (ci->type) {
00291 default: return NULL;
00292 case CONTENT_TYPE_BASE_GRAPHICS: dir = DATA_DIR; break;
00293 case CONTENT_TYPE_NEWGRF: dir = DATA_DIR; break;
00294 case CONTENT_TYPE_AI: dir = AI_DIR; break;
00295 case CONTENT_TYPE_AI_LIBRARY: dir = AI_LIBRARY_DIR; break;
00296 case CONTENT_TYPE_SCENARIO: dir = SCENARIO_DIR; break;
00297 case CONTENT_TYPE_HEIGHTMAP: dir = HEIGHTMAP_DIR; break;
00298 }
00299
00300 static char buf[MAX_PATH];
00301 FioGetFullPath(buf, lengthof(buf), SP_AUTODOWNLOAD_DIR, dir, ci->filename);
00302 strecat(buf, compressed ? ".tar.gz" : ".tar", lastof(buf));
00303
00304 return buf;
00305 }
00306
00312 static bool GunzipFile(const ContentInfo *ci)
00313 {
00314 #if defined(WITH_ZLIB)
00315 bool ret = true;
00316 FILE *ftmp = fopen(GetFullFilename(ci, true), "rb");
00317 gzFile fin = gzdopen(fileno(ftmp), "rb");
00318 FILE *fout = fopen(GetFullFilename(ci, false), "wb");
00319
00320 if (fin == NULL || fout == NULL) {
00321 ret = false;
00322 goto exit;
00323 }
00324
00325 byte buff[8192];
00326 while (!gzeof(fin)) {
00327 int read = gzread(fin, buff, sizeof(buff));
00328 if (read < 0 || (size_t)read != fwrite(buff, 1, read, fout)) {
00329 ret = false;
00330 break;
00331 }
00332 }
00333
00334 exit:
00335 if (fin != NULL) {
00336
00337 gzclose(fin);
00338 } else if (ftmp != NULL) {
00339
00340
00341 fclose(ftmp);
00342 }
00343 if (fout != NULL) fclose(fout);
00344
00345 return ret;
00346 #else
00347 NOT_REACHED();
00348 #endif
00349 }
00350
00351 DEF_CONTENT_RECEIVE_COMMAND(Client, PACKET_CONTENT_SERVER_CONTENT)
00352 {
00353 if (this->curFile == NULL) {
00354
00355 this->curInfo = new ContentInfo;
00356 this->curInfo->type = (ContentType)p->Recv_uint8();
00357 this->curInfo->id = (ContentID)p->Recv_uint32();
00358 this->curInfo->filesize = p->Recv_uint32();
00359 p->Recv_string(this->curInfo->filename, lengthof(this->curInfo->filename));
00360
00361 if (!this->curInfo->IsValid()) {
00362 delete this->curInfo;
00363 this->curInfo = NULL;
00364 this->Close();
00365 return false;
00366 }
00367
00368 if (this->curInfo->filesize != 0) {
00369
00370 const char *filename = GetFullFilename(this->curInfo, true);
00371 if (filename == NULL) {
00372
00373 DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
00374 ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD, STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD_FILE_NOT_WRITABLE, 0, 0);
00375 this->Close();
00376 return false;
00377 }
00378
00379 this->curFile = fopen(filename, "wb");
00380 }
00381 } else {
00382
00383 size_t toRead = (size_t)(p->size - p->pos);
00384 if (fwrite(p->buffer + p->pos, 1, toRead, this->curFile) != toRead) {
00385 DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
00386 ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD, STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD_FILE_NOT_WRITABLE, 0, 0);
00387 this->Close();
00388 fclose(this->curFile);
00389 this->curFile = NULL;
00390
00391 return false;
00392 }
00393
00394 this->OnDownloadProgress(this->curInfo, (uint)toRead);
00395
00396 if (toRead == 0) {
00397
00398
00399 fclose(this->curFile);
00400 this->curFile = NULL;
00401
00402 if (GunzipFile(this->curInfo)) {
00403 unlink(GetFullFilename(this->curInfo, true));
00404
00405 TarListAddFile(GetFullFilename(this->curInfo, false));
00406
00407 this->OnDownloadComplete(this->curInfo->id);
00408 } else {
00409 ShowErrorMessage(INVALID_STRING_ID, STR_CONTENT_ERROR_COULD_NOT_EXTRACT, 0, 0);
00410 }
00411 }
00412 }
00413
00414
00415 if (this->curFile == NULL) {
00416 delete this->curInfo;
00417 this->curInfo = NULL;
00418 }
00419
00420 return true;
00421 }
00422
00428 ClientNetworkContentSocketHandler::ClientNetworkContentSocketHandler() :
00429 NetworkContentSocketHandler(INVALID_SOCKET, NULL),
00430 curFile(NULL),
00431 curInfo(NULL),
00432 isConnecting(false)
00433 {
00434 }
00435
00437 ClientNetworkContentSocketHandler::~ClientNetworkContentSocketHandler()
00438 {
00439 delete this->curInfo;
00440 if (this->curFile != NULL) fclose(this->curFile);
00441
00442 for (ContentIterator iter = this->infos.Begin(); iter != this->infos.End(); iter++) delete *iter;
00443 }
00444
00445 class NetworkContentConnecter : TCPConnecter {
00446 public:
00447 NetworkContentConnecter(const NetworkAddress &address) : TCPConnecter(address) {}
00448
00449 virtual void OnFailure()
00450 {
00451 _network_content_client.isConnecting = false;
00452 _network_content_client.OnConnect(false);
00453 }
00454
00455 virtual void OnConnect(SOCKET s)
00456 {
00457 assert(_network_content_client.sock == INVALID_SOCKET);
00458 _network_content_client.isConnecting = false;
00459 _network_content_client.sock = s;
00460 _network_content_client.has_quit = false;
00461 _network_content_client.OnConnect(true);
00462 }
00463 };
00464
00468 void ClientNetworkContentSocketHandler::Connect()
00469 {
00470 this->lastActivity = _realtime_tick;
00471
00472 if (this->sock != INVALID_SOCKET || this->isConnecting) return;
00473 this->isConnecting = true;
00474 new NetworkContentConnecter(NetworkAddress(NETWORK_CONTENT_SERVER_HOST, NETWORK_CONTENT_SERVER_PORT));
00475 }
00476
00480 void ClientNetworkContentSocketHandler::Close()
00481 {
00482 if (this->sock == INVALID_SOCKET) return;
00483 NetworkContentSocketHandler::Close();
00484
00485 this->OnDisconnect();
00486 }
00487
00492 void ClientNetworkContentSocketHandler::SendReceive()
00493 {
00494 if (this->sock == INVALID_SOCKET || this->isConnecting) return;
00495
00496 if (this->lastActivity + IDLE_TIMEOUT < _realtime_tick) {
00497 this->Close();
00498 return;
00499 }
00500
00501 fd_set read_fd, write_fd;
00502 struct timeval tv;
00503
00504 FD_ZERO(&read_fd);
00505 FD_ZERO(&write_fd);
00506
00507 FD_SET(this->sock, &read_fd);
00508 FD_SET(this->sock, &write_fd);
00509
00510 tv.tv_sec = tv.tv_usec = 0;
00511 #if !defined(__MORPHOS__) && !defined(__AMIGA__)
00512 select(FD_SETSIZE, &read_fd, &write_fd, NULL, &tv);
00513 #else
00514 WaitSelect(FD_SETSIZE, &read_fd, &write_fd, NULL, &tv, NULL);
00515 #endif
00516 if (FD_ISSET(this->sock, &read_fd)) {
00517 this->Recv_Packets();
00518 this->lastActivity = _realtime_tick;
00519 }
00520
00521 this->writable = !!FD_ISSET(this->sock, &write_fd);
00522 this->Send_Packets();
00523 }
00524
00529 void ClientNetworkContentSocketHandler::DownloadContentInfo(ContentID cid)
00530 {
00531
00532 if (this->requested.Contains(cid)) return;
00533
00534 *this->requested.Append() = cid;
00535 assert(this->requested.Contains(cid));
00536 this->RequestContentList(1, &cid);
00537 }
00538
00544 ContentInfo *ClientNetworkContentSocketHandler::GetContent(ContentID cid)
00545 {
00546 for (ContentIterator iter = this->infos.Begin(); iter != this->infos.End(); iter++) {
00547 ContentInfo *ci = *iter;
00548 if (ci->id == cid) return ci;
00549 }
00550 return NULL;
00551 }
00552
00553
00558 void ClientNetworkContentSocketHandler::Select(ContentID cid)
00559 {
00560 ContentInfo *ci = this->GetContent(cid);
00561 if (ci == NULL || ci->state != ContentInfo::UNSELECTED) return;
00562
00563 ci->state = ContentInfo::SELECTED;
00564 this->CheckDependencyState(ci);
00565 }
00566
00571 void ClientNetworkContentSocketHandler::Unselect(ContentID cid)
00572 {
00573 ContentInfo *ci = this->GetContent(cid);
00574 if (ci == NULL || !ci->IsSelected()) return;
00575
00576 ci->state = ContentInfo::UNSELECTED;
00577 this->CheckDependencyState(ci);
00578 }
00579
00581 void ClientNetworkContentSocketHandler::SelectAll()
00582 {
00583 for (ContentIterator iter = this->infos.Begin(); iter != this->infos.End(); iter++) {
00584 ContentInfo *ci = *iter;
00585 if (ci->state == ContentInfo::UNSELECTED) {
00586 ci->state = ContentInfo::SELECTED;
00587 this->CheckDependencyState(ci);
00588 }
00589 }
00590 }
00591
00593 void ClientNetworkContentSocketHandler::SelectUpgrade()
00594 {
00595 for (ContentIterator iter = this->infos.Begin(); iter != this->infos.End(); iter++) {
00596 ContentInfo *ci = *iter;
00597 if (ci->state == ContentInfo::UNSELECTED && ci->upgrade) {
00598 ci->state = ContentInfo::SELECTED;
00599 this->CheckDependencyState(ci);
00600 }
00601 }
00602 }
00603
00605 void ClientNetworkContentSocketHandler::UnselectAll()
00606 {
00607 for (ContentIterator iter = this->infos.Begin(); iter != this->infos.End(); iter++) {
00608 ContentInfo *ci = *iter;
00609 if (ci->IsSelected()) ci->state = ContentInfo::UNSELECTED;
00610 }
00611 }
00612
00614 void ClientNetworkContentSocketHandler::ToggleSelectedState(const ContentInfo *ci)
00615 {
00616 switch (ci->state) {
00617 case ContentInfo::SELECTED:
00618 case ContentInfo::AUTOSELECTED:
00619 this->Unselect(ci->id);
00620 break;
00621
00622 case ContentInfo::UNSELECTED:
00623 this->Select(ci->id);
00624 break;
00625
00626 default:
00627 break;
00628 }
00629 }
00630
00636 void ClientNetworkContentSocketHandler::ReverseLookupDependency(ConstContentVector &parents, const ContentInfo *child) const
00637 {
00638 for (ConstContentIterator iter = this->infos.Begin(); iter != this->infos.End(); iter++) {
00639 const ContentInfo *ci = *iter;
00640 if (ci == child) continue;
00641
00642 for (uint i = 0; i < ci->dependency_count; i++) {
00643 if (ci->dependencies[i] == child->id) {
00644 *parents.Append() = ci;
00645 break;
00646 }
00647 }
00648 }
00649 }
00650
00656 void ClientNetworkContentSocketHandler::ReverseLookupTreeDependency(ConstContentVector &tree, const ContentInfo *child) const
00657 {
00658 *tree.Append() = child;
00659
00660
00661 for (ConstContentIterator iter = tree.Begin(); iter != tree.End(); iter++) {
00662 ConstContentVector parents;
00663 this->ReverseLookupDependency(parents, *iter);
00664
00665 for (ConstContentIterator piter = parents.Begin(); piter != parents.End(); piter++) {
00666 tree.Include(*piter);
00667 }
00668 }
00669 }
00670
00675 void ClientNetworkContentSocketHandler::CheckDependencyState(ContentInfo *ci)
00676 {
00677 if (ci->IsSelected() || ci->state == ContentInfo::ALREADY_HERE) {
00678
00679
00680
00681 for (uint i = 0; i < ci->dependency_count; i++) {
00682 ContentInfo *c = this->GetContent(ci->dependencies[i]);
00683 if (c == NULL) {
00684 this->DownloadContentInfo(ci->dependencies[i]);
00685 } else if (c->state == ContentInfo::UNSELECTED) {
00686 c->state = ContentInfo::AUTOSELECTED;
00687 this->CheckDependencyState(c);
00688 }
00689 }
00690 return;
00691 }
00692
00693 if (ci->state != ContentInfo::UNSELECTED) return;
00694
00695
00696
00697
00698
00699 ConstContentVector parents;
00700 this->ReverseLookupDependency(parents, ci);
00701 for (ConstContentIterator iter = parents.Begin(); iter != parents.End(); iter++) {
00702 const ContentInfo *c = *iter;
00703 if (!c->IsSelected()) continue;
00704
00705 this->Unselect(c->id);
00706 }
00707
00708 for (uint i = 0; i < ci->dependency_count; i++) {
00709 const ContentInfo *c = this->GetContent(ci->dependencies[i]);
00710 if (c == NULL) {
00711 DownloadContentInfo(ci->dependencies[i]);
00712 continue;
00713 }
00714 if (c->state != ContentInfo::AUTOSELECTED) continue;
00715
00716
00717 parents.Clear();
00718 this->ReverseLookupDependency(parents, c);
00719
00720
00721 int sel_count = 0;
00722 bool force_selection = false;
00723 for (ConstContentIterator iter = parents.Begin(); iter != parents.End(); iter++) {
00724 if ((*iter)->IsSelected()) sel_count++;
00725 if ((*iter)->state == ContentInfo::SELECTED) force_selection = true;
00726 }
00727 if (sel_count == 0) {
00728
00729 this->Unselect(c->id);
00730 continue;
00731 }
00732
00733 if (force_selection) continue;
00734
00735
00736 parents.Clear();
00737 this->ReverseLookupTreeDependency(parents, c);
00738
00739
00740 for (ConstContentIterator iter = parents.Begin(); iter != parents.End(); iter++) {
00741 if ((*iter)->state != ContentInfo::SELECTED) continue;
00742
00743 force_selection = true;
00744 break;
00745 }
00746
00747
00748 if (force_selection) continue;
00749
00750
00751
00752
00753
00754 for (ConstContentIterator iter = parents.Begin(); iter != parents.End(); iter++) {
00755 const ContentInfo *c = *iter;
00756 if (c->state == ContentInfo::AUTOSELECTED) this->Unselect(c->id);
00757 }
00758 for (ConstContentIterator iter = parents.Begin(); iter != parents.End(); iter++) {
00759 this->CheckDependencyState(this->GetContent((*iter)->id));
00760 }
00761 }
00762 }
00763
00764 void ClientNetworkContentSocketHandler::Clear()
00765 {
00766 for (ContentIterator iter = this->infos.Begin(); iter != this->infos.End(); iter++) delete *iter;
00767
00768 this->infos.Clear();
00769 this->requested.Clear();
00770 }
00771
00772
00773
00774 void ClientNetworkContentSocketHandler::OnConnect(bool success)
00775 {
00776 for (ContentCallback **iter = this->callbacks.Begin(); iter != this->callbacks.End(); ) {
00777 ContentCallback *cb = *iter;
00778 cb->OnConnect(success);
00779 if (iter != this->callbacks.End() && *iter == cb) iter++;
00780 }
00781 }
00782
00783 void ClientNetworkContentSocketHandler::OnDisconnect()
00784 {
00785 for (ContentCallback **iter = this->callbacks.Begin(); iter != this->callbacks.End(); ) {
00786 ContentCallback *cb = *iter;
00787 cb->OnDisconnect();
00788 if (iter != this->callbacks.End() && *iter == cb) iter++;
00789 }
00790 }
00791
00792 void ClientNetworkContentSocketHandler::OnReceiveContentInfo(const ContentInfo *ci)
00793 {
00794 for (ContentCallback **iter = this->callbacks.Begin(); iter != this->callbacks.End(); ) {
00795 ContentCallback *cb = *iter;
00796 cb->OnReceiveContentInfo(ci);
00797 if (iter != this->callbacks.End() && *iter == cb) iter++;
00798 }
00799 }
00800
00801 void ClientNetworkContentSocketHandler::OnDownloadProgress(const ContentInfo *ci, uint bytes)
00802 {
00803 for (ContentCallback **iter = this->callbacks.Begin(); iter != this->callbacks.End(); ) {
00804 ContentCallback *cb = *iter;
00805 cb->OnDownloadProgress(ci, bytes);
00806 if (iter != this->callbacks.End() && *iter == cb) iter++;
00807 }
00808 }
00809
00810 void ClientNetworkContentSocketHandler::OnDownloadComplete(ContentID cid)
00811 {
00812 ContentInfo *ci = this->GetContent(cid);
00813 if (ci != NULL) {
00814 ci->state = ContentInfo::ALREADY_HERE;
00815 }
00816
00817 for (ContentCallback **iter = this->callbacks.Begin(); iter != this->callbacks.End(); ) {
00818 ContentCallback *cb = *iter;
00819 cb->OnDownloadComplete(cid);
00820 if (iter != this->callbacks.End() && *iter == cb) iter++;
00821 }
00822 }
00823
00824 #endif