Update to 12.0-beta1

This commit is contained in:
dP
2021-08-15 14:57:29 +03:00
parent ac7d3eba75
commit 9df4f2c4fc
666 changed files with 61302 additions and 20466 deletions

View File

@@ -56,27 +56,27 @@ bool ClientNetworkContentSocketHandler::Receive_SERVER_INFO(Packet *p)
ci->id = (ContentID)p->Recv_uint32();
ci->filesize = p->Recv_uint32();
p->Recv_string(ci->name, lengthof(ci->name));
p->Recv_string(ci->version, lengthof(ci->version));
p->Recv_string(ci->url, lengthof(ci->url));
p->Recv_string(ci->description, lengthof(ci->description), SVS_REPLACE_WITH_QUESTION_MARK | SVS_ALLOW_NEWLINE);
ci->name = p->Recv_string(NETWORK_CONTENT_NAME_LENGTH);
ci->version = p->Recv_string(NETWORK_CONTENT_VERSION_LENGTH);
ci->url = p->Recv_string(NETWORK_CONTENT_URL_LENGTH);
ci->description = p->Recv_string(NETWORK_CONTENT_DESC_LENGTH, SVS_REPLACE_WITH_QUESTION_MARK | SVS_ALLOW_NEWLINE);
ci->unique_id = p->Recv_uint32();
for (uint j = 0; j < sizeof(ci->md5sum); j++) {
ci->md5sum[j] = p->Recv_uint8();
}
ci->dependency_count = p->Recv_uint8();
ci->dependencies = MallocT<ContentID>(ci->dependency_count);
for (uint i = 0; i < ci->dependency_count; i++) ci->dependencies[i] = (ContentID)p->Recv_uint32();
uint dependency_count = p->Recv_uint8();
ci->dependencies.reserve(dependency_count);
for (uint i = 0; i < dependency_count; i++) ci->dependencies.push_back((ContentID)p->Recv_uint32());
ci->tag_count = p->Recv_uint8();
ci->tags = MallocT<char[32]>(ci->tag_count);
for (uint i = 0; i < ci->tag_count; i++) p->Recv_string(ci->tags[i], lengthof(*ci->tags));
uint tag_count = p->Recv_uint8();
ci->tags.reserve(tag_count);
for (uint i = 0; i < tag_count; i++) ci->tags.push_back(p->Recv_string(NETWORK_CONTENT_TAG_LENGTH));
if (!ci->IsValid()) {
delete ci;
this->Close();
this->CloseConnection();
return false;
}
@@ -143,16 +143,15 @@ bool ClientNetworkContentSocketHandler::Receive_SERVER_INFO(Packet *p)
if (ici->type == ci->type && ici->unique_id == ci->unique_id &&
memcmp(ci->md5sum, ici->md5sum, sizeof(ci->md5sum)) == 0) {
/* Preserve the name if possible */
if (StrEmpty(ci->name)) strecpy(ci->name, ici->name, lastof(ci->name));
if (ci->name.empty()) ci->name = ici->name;
if (ici->IsSelected()) ci->state = ici->state;
/*
* As ici might be selected by the content window we cannot delete that.
* However, we want to keep most of the values of ci, except the values
* we (just) already preserved.
* So transfer data and ownership of allocated memory from ci to ici.
*/
ici->TransferFrom(ci);
*ici = *ci;
delete ci;
this->OnReceiveContentInfo(ici);
@@ -221,9 +220,9 @@ void ClientNetworkContentSocketHandler::RequestContentList(uint count, const Con
* A packet begins with the packet size and a byte for the type.
* Then this packet adds a uint16 for the count in this packet.
* The rest of the packet can be used for the IDs. */
uint p_count = std::min<uint>(count, (SEND_MTU - sizeof(PacketSize) - sizeof(byte) - sizeof(uint16)) / sizeof(uint32));
uint p_count = std::min<uint>(count, (TCP_MTU - sizeof(PacketSize) - sizeof(byte) - sizeof(uint16)) / sizeof(uint32));
Packet *p = new Packet(PACKET_CONTENT_CLIENT_INFO_ID);
Packet *p = new Packet(PACKET_CONTENT_CLIENT_INFO_ID, TCP_MTU);
p->Send_uint16(p_count);
for (uint i = 0; i < p_count; i++) {
@@ -248,10 +247,10 @@ void ClientNetworkContentSocketHandler::RequestContentList(ContentVector *cv, bo
this->Connect();
assert(cv->size() < 255);
assert(cv->size() < (SEND_MTU - sizeof(PacketSize) - sizeof(byte) - sizeof(uint8)) /
assert(cv->size() < (TCP_MTU - sizeof(PacketSize) - sizeof(byte) - sizeof(uint8)) /
(sizeof(uint8) + sizeof(uint32) + (send_md5sum ? /*sizeof(ContentInfo::md5sum)*/16 : 0)));
Packet *p = new Packet(send_md5sum ? PACKET_CONTENT_CLIENT_INFO_EXTID_MD5 : PACKET_CONTENT_CLIENT_INFO_EXTID);
Packet *p = new Packet(send_md5sum ? PACKET_CONTENT_CLIENT_INFO_EXTID_MD5 : PACKET_CONTENT_CLIENT_INFO_EXTID, TCP_MTU);
p->Send_uint8((uint8)cv->size());
for (const ContentInfo *ci : *cv) {
@@ -343,8 +342,7 @@ void ClientNetworkContentSocketHandler::DownloadSelectedContentHTTP(const Conten
this->http_response_index = -1;
NetworkAddress address(NETWORK_CONTENT_MIRROR_HOST, NETWORK_CONTENT_MIRROR_PORT);
new NetworkHTTPContentConnecter(address, this, NETWORK_CONTENT_MIRROR_URL, content_request);
new NetworkHTTPContentConnecter(NetworkContentMirrorConnectionString(), this, NETWORK_CONTENT_MIRROR_URL, content_request);
/* NetworkHTTPContentConnecter takes over freeing of content_request! */
}
@@ -363,9 +361,9 @@ void ClientNetworkContentSocketHandler::DownloadSelectedContentFallback(const Co
* A packet begins with the packet size and a byte for the type.
* Then this packet adds a uint16 for the count in this packet.
* The rest of the packet can be used for the IDs. */
uint p_count = std::min<uint>(count, (SEND_MTU - sizeof(PacketSize) - sizeof(byte) - sizeof(uint16)) / sizeof(uint32));
uint p_count = std::min<uint>(count, (TCP_MTU - sizeof(PacketSize) - sizeof(byte) - sizeof(uint16)) / sizeof(uint32));
Packet *p = new Packet(PACKET_CONTENT_CLIENT_CONTENT);
Packet *p = new Packet(PACKET_CONTENT_CLIENT_CONTENT, TCP_MTU);
p->Send_uint16(p_count);
for (uint i = 0; i < p_count; i++) {
@@ -411,7 +409,8 @@ static bool GunzipFile(const ContentInfo *ci)
FILE *ftmp = fopen(GetFullFilename(ci, true).c_str(), "rb");
if (ftmp == nullptr) return false;
/* Duplicate the handle, and close the FILE*, to avoid double-closing the handle later. */
gzFile fin = gzdopen(dup(fileno(ftmp)), "rb");
int fdup = dup(fileno(ftmp));
gzFile fin = gzdopen(fdup, "rb");
fclose(ftmp);
FILE *fout = fopen(GetFullFilename(ci, false).c_str(), "wb");
@@ -450,7 +449,12 @@ static bool GunzipFile(const ContentInfo *ci)
}
}
if (fin != nullptr) gzclose(fin);
if (fin != nullptr) {
gzclose(fin);
} else if (fdup != -1) {
/* Failing gzdopen does not close the passed file descriptor. */
close(fdup);
}
if (fout != nullptr) fclose(fout);
return ret;
@@ -459,6 +463,18 @@ static bool GunzipFile(const ContentInfo *ci)
#endif /* defined(WITH_ZLIB) */
}
/**
* Simple wrapper around fwrite to be able to pass it to Packet's TransferOut.
* @param file The file to write data to.
* @param buffer The buffer to write to the file.
* @param amount The number of bytes to write.
* @return The number of bytes that were written.
*/
static inline ssize_t TransferOutFWrite(FILE *file, const char *buffer, size_t amount)
{
return fwrite(buffer, 1, amount, file);
}
bool ClientNetworkContentSocketHandler::Receive_SERVER_CONTENT(Packet *p)
{
if (this->curFile == nullptr) {
@@ -468,19 +484,19 @@ bool ClientNetworkContentSocketHandler::Receive_SERVER_CONTENT(Packet *p)
this->curInfo->type = (ContentType)p->Recv_uint8();
this->curInfo->id = (ContentID)p->Recv_uint32();
this->curInfo->filesize = p->Recv_uint32();
p->Recv_string(this->curInfo->filename, lengthof(this->curInfo->filename));
this->curInfo->filename = p->Recv_string(NETWORK_CONTENT_FILENAME_LENGTH);
if (!this->BeforeDownload()) {
this->Close();
this->CloseConnection();
return false;
}
} else {
/* We have a file opened, thus are downloading internal content */
size_t toRead = (size_t)(p->size - p->pos);
if (fwrite(p->buffer + p->pos, 1, toRead, this->curFile) != toRead) {
DeleteWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_CONTENT_DOWNLOAD);
size_t toRead = p->RemainingBytesToTransfer();
if (toRead != 0 && (size_t)p->TransferOut(TransferOutFWrite, this->curFile) != toRead) {
CloseWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_CONTENT_DOWNLOAD);
ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD, STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD_FILE_NOT_WRITABLE, WL_ERROR);
this->Close();
this->CloseConnection();
fclose(this->curFile);
this->curFile = nullptr;
@@ -512,7 +528,7 @@ bool ClientNetworkContentSocketHandler::BeforeDownload()
std::string filename = GetFullFilename(this->curInfo, true);
if (filename.empty() || (this->curFile = fopen(filename.c_str(), "wb")) == nullptr) {
/* Unless that fails of course... */
DeleteWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_CONTENT_DOWNLOAD);
CloseWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_CONTENT_DOWNLOAD);
ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD, STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD_FILE_NOT_WRITABLE, WL_ERROR);
return false;
}
@@ -687,7 +703,7 @@ void ClientNetworkContentSocketHandler::OnReceiveData(const char *data, size_t l
}
/* Copy the string, without extension, to the filename. */
strecpy(this->curInfo->filename, tmp, lastof(this->curInfo->filename));
this->curInfo->filename = tmp;
/* Request the next file. */
if (!this->BeforeDownload()) {
@@ -732,7 +748,7 @@ public:
* Initiate the connecting.
* @param address The address of the server.
*/
NetworkContentConnecter(const NetworkAddress &address) : TCPConnecter(address) {}
NetworkContentConnecter(const std::string &connection_string) : TCPConnecter(connection_string, NETWORK_CONTENT_SERVER_PORT) {}
void OnFailure() override
{
@@ -758,18 +774,22 @@ void ClientNetworkContentSocketHandler::Connect()
{
if (this->sock != INVALID_SOCKET || this->isConnecting) return;
this->isConnecting = true;
new NetworkContentConnecter(NetworkAddress(NETWORK_CONTENT_SERVER_HOST, NETWORK_CONTENT_SERVER_PORT, AF_UNSPEC));
new NetworkContentConnecter(NetworkContentServerConnectionString());
}
/**
* Disconnect from the content server.
*/
void ClientNetworkContentSocketHandler::Close()
NetworkRecvStatus ClientNetworkContentSocketHandler::CloseConnection(bool error)
{
if (this->sock == INVALID_SOCKET) return;
NetworkContentSocketHandler::Close();
NetworkContentSocketHandler::CloseConnection();
if (this->sock == INVALID_SOCKET) return NETWORK_RECV_STATUS_OKAY;
this->CloseSocket();
this->OnDisconnect();
return NETWORK_RECV_STATUS_OKAY;
}
/**
@@ -781,7 +801,7 @@ void ClientNetworkContentSocketHandler::SendReceive()
if (this->sock == INVALID_SOCKET || this->isConnecting) return;
if (std::chrono::steady_clock::now() > this->lastActivity + IDLE_TIMEOUT) {
this->Close();
this->CloseConnection();
return;
}
@@ -906,8 +926,8 @@ void ClientNetworkContentSocketHandler::ReverseLookupDependency(ConstContentVect
for (const ContentInfo *ci : this->infos) {
if (ci == child) continue;
for (uint i = 0; i < ci->dependency_count; i++) {
if (ci->dependencies[i] == child->id) {
for (auto &dependency : ci->dependencies) {
if (dependency == child->id) {
parents.push_back(ci);
break;
}
@@ -948,10 +968,10 @@ void ClientNetworkContentSocketHandler::CheckDependencyState(ContentInfo *ci)
/* Selection is easy; just walk all children and set the
* autoselected state. That way we can see what we automatically
* selected and thus can unselect when a dependency is removed. */
for (uint i = 0; i < ci->dependency_count; i++) {
ContentInfo *c = this->GetContent(ci->dependencies[i]);
for (auto &dependency : ci->dependencies) {
ContentInfo *c = this->GetContent(dependency);
if (c == nullptr) {
this->DownloadContentInfo(ci->dependencies[i]);
this->DownloadContentInfo(dependency);
} else if (c->state == ContentInfo::UNSELECTED) {
c->state = ContentInfo::AUTOSELECTED;
this->CheckDependencyState(c);
@@ -974,10 +994,10 @@ void ClientNetworkContentSocketHandler::CheckDependencyState(ContentInfo *ci)
this->Unselect(c->id);
}
for (uint i = 0; i < ci->dependency_count; i++) {
const ContentInfo *c = this->GetContent(ci->dependencies[i]);
for (auto &dependency : ci->dependencies) {
const ContentInfo *c = this->GetContent(dependency);
if (c == nullptr) {
DownloadContentInfo(ci->dependencies[i]);
DownloadContentInfo(dependency);
continue;
}
if (c->state != ContentInfo::AUTOSELECTED) continue;
@@ -989,9 +1009,9 @@ void ClientNetworkContentSocketHandler::CheckDependencyState(ContentInfo *ci)
/* First check whether anything depends on us */
int sel_count = 0;
bool force_selection = false;
for (const ContentInfo *ci : parents) {
if (ci->IsSelected()) sel_count++;
if (ci->state == ContentInfo::SELECTED) force_selection = true;
for (const ContentInfo *parent_ci : parents) {
if (parent_ci->IsSelected()) sel_count++;
if (parent_ci->state == ContentInfo::SELECTED) force_selection = true;
}
if (sel_count == 0) {
/* Nothing depends on us */
@@ -1006,8 +1026,8 @@ void ClientNetworkContentSocketHandler::CheckDependencyState(ContentInfo *ci)
this->ReverseLookupTreeDependency(parents, c);
/* Is there anything that is "force" selected?, if so... we're done. */
for (const ContentInfo *ci : parents) {
if (ci->state != ContentInfo::SELECTED) continue;
for (const ContentInfo *parent_ci : parents) {
if (parent_ci->state != ContentInfo::SELECTED) continue;
force_selection = true;
break;