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