1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-07-22 17:18:39 +00:00

Dynamic_Add_Media v2 (#11550)

This commit is contained in:
sfan5 2021-09-09 16:51:35 +02:00 committed by GitHub
parent bcb6565483
commit bbfae0cc67
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 796 additions and 246 deletions

View file

@ -204,7 +204,7 @@ const ServerCommandFactory serverCommandFactoryTable[TOSERVER_NUM_MSG_TYPES] =
null_command_factory, // 0x3e
null_command_factory, // 0x3f
{ "TOSERVER_REQUEST_MEDIA", 1, true }, // 0x40
null_command_factory, // 0x41
{ "TOSERVER_HAVE_MEDIA", 2, true }, // 0x41
null_command_factory, // 0x42
{ "TOSERVER_CLIENT_READY", 1, true }, // 0x43
null_command_factory, // 0x44

View file

@ -670,21 +670,19 @@ void Client::handleCommand_AnnounceMedia(NetworkPacket* pkt)
m_media_downloader->addFile(name, sha1_raw);
}
try {
{
std::string str;
*pkt >> str;
Strfnd sf(str);
while(!sf.at_end()) {
while (!sf.at_end()) {
std::string baseurl = trim(sf.next(","));
if (!baseurl.empty())
if (!baseurl.empty()) {
m_remote_media_servers.emplace_back(baseurl);
m_media_downloader->addRemoteServer(baseurl);
}
}
}
catch(SerializationError& e) {
// not supported by server or turned off
}
m_media_downloader->step(this);
}
@ -716,31 +714,38 @@ void Client::handleCommand_Media(NetworkPacket* pkt)
if (num_files == 0)
return;
if (!m_media_downloader || !m_media_downloader->isStarted()) {
const char *problem = m_media_downloader ?
"media has not been requested" :
"all media has been received already";
errorstream << "Client: Received media but "
<< problem << "! "
<< " bunch " << bunch_i << "/" << num_bunches
<< " files=" << num_files
<< " size=" << pkt->getSize() << std::endl;
return;
bool init_phase = m_media_downloader && m_media_downloader->isStarted();
if (init_phase) {
// Mesh update thread must be stopped while
// updating content definitions
sanity_check(!m_mesh_update_thread.isRunning());
}
// Mesh update thread must be stopped while
// updating content definitions
sanity_check(!m_mesh_update_thread.isRunning());
for (u32 i=0; i < num_files; i++) {
std::string name;
for (u32 i = 0; i < num_files; i++) {
std::string name, data;
*pkt >> name;
data = pkt->readLongString();
std::string data = pkt->readLongString();
m_media_downloader->conventionalTransferDone(
name, data, this);
bool ok = false;
if (init_phase) {
ok = m_media_downloader->conventionalTransferDone(name, data, this);
} else {
// Check pending dynamic transfers, one of them must be it
for (const auto &it : m_pending_media_downloads) {
if (it.second->conventionalTransferDone(name, data, this)) {
ok = true;
break;
}
}
}
if (!ok) {
errorstream << "Client: Received media \"" << name
<< "\" but no downloads pending. " << num_bunches << " bunches, "
<< num_files << " in this one. (init_phase=" << init_phase
<< ")" << std::endl;
}
}
}
@ -1497,46 +1502,72 @@ void Client::handleCommand_PlayerSpeed(NetworkPacket *pkt)
void Client::handleCommand_MediaPush(NetworkPacket *pkt)
{
std::string raw_hash, filename, filedata;
u32 token;
bool cached;
*pkt >> raw_hash >> filename >> cached;
filedata = pkt->readLongString();
if (m_proto_ver >= 40)
*pkt >> token;
else
filedata = pkt->readLongString();
if (raw_hash.size() != 20 || filedata.empty() || filename.empty() ||
if (raw_hash.size() != 20 || filename.empty() ||
(m_proto_ver < 40 && filedata.empty()) ||
!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)) {
throw PacketError("Illegal filename, data or hash");
}
verbosestream << "Server pushes media file \"" << filename << "\" with "
<< filedata.size() << " bytes of data (cached=" << cached
<< ")" << std::endl;
verbosestream << "Server pushes media file \"" << filename << "\" ";
if (filedata.empty())
verbosestream << "to be fetched ";
else
verbosestream << "with " << filedata.size() << " bytes ";
verbosestream << "(cached=" << cached << ")" << std::endl;
if (m_media_pushed_files.count(filename) != 0) {
// Silently ignore for synchronization purposes
// Ignore (but acknowledge). Previously this was for sync purposes,
// but even in new versions media cannot be replaced at runtime.
if (m_proto_ver >= 40)
sendHaveMedia({ token });
return;
}
// Compute and check checksum of data
std::string computed_hash;
{
SHA1 ctx;
ctx.addBytes(filedata.c_str(), filedata.size());
unsigned char *buf = ctx.getDigest();
computed_hash.assign((char*) buf, 20);
free(buf);
}
if (raw_hash != computed_hash) {
verbosestream << "Hash of file data mismatches, ignoring." << std::endl;
if (!filedata.empty()) {
// LEGACY CODEPATH
// Compute and check checksum of data
std::string computed_hash;
{
SHA1 ctx;
ctx.addBytes(filedata.c_str(), filedata.size());
unsigned char *buf = ctx.getDigest();
computed_hash.assign((char*) buf, 20);
free(buf);
}
if (raw_hash != computed_hash) {
verbosestream << "Hash of file data mismatches, ignoring." << std::endl;
return;
}
// Actually load media
loadMedia(filedata, filename, true);
m_media_pushed_files.insert(filename);
// Cache file for the next time when this client joins the same server
if (cached)
clientMediaUpdateCache(raw_hash, filedata);
return;
}
// Actually load media
loadMedia(filedata, filename, true);
m_media_pushed_files.insert(filename);
// Cache file for the next time when this client joins the same server
if (cached)
clientMediaUpdateCache(raw_hash, filedata);
// create a downloader for this file
auto downloader = new SingleMediaDownloader(cached);
m_pending_media_downloads.emplace_back(token, downloader);
downloader->addFile(filename, raw_hash);
for (const auto &baseurl : m_remote_media_servers)
downloader->addRemoteServer(baseurl);
downloader->step(this);
}
/*

View file

@ -207,6 +207,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
Minimap modes
PROTOCOL VERSION 40:
Added 'basic_debug' privilege
TOCLIENT_MEDIA_PUSH changed, TOSERVER_HAVE_MEDIA added
*/
#define LATEST_PROTOCOL_VERSION 40
@ -317,9 +318,8 @@ enum ToClientCommand
/*
std::string raw_hash
std::string filename
u32 callback_token
bool should_be_cached
u32 len
char filedata[len]
*/
// (oops, there is some gap here)
@ -938,7 +938,13 @@ enum ToServerCommand
}
*/
TOSERVER_RECEIVED_MEDIA = 0x41, // Obsolete
TOSERVER_HAVE_MEDIA = 0x41,
/*
u8 number of callback tokens
for each:
u32 token
*/
TOSERVER_BREATH = 0x42, // Obsolete
TOSERVER_CLIENT_READY = 0x43,

View file

@ -89,7 +89,7 @@ const ToServerCommandHandler toServerCommandTable[TOSERVER_NUM_MSG_TYPES] =
null_command_handler, // 0x3e
null_command_handler, // 0x3f
{ "TOSERVER_REQUEST_MEDIA", TOSERVER_STATE_STARTUP, &Server::handleCommand_RequestMedia }, // 0x40
null_command_handler, // 0x41
{ "TOSERVER_HAVE_MEDIA", TOSERVER_STATE_INGAME, &Server::handleCommand_HaveMedia }, // 0x41
null_command_handler, // 0x42
{ "TOSERVER_CLIENT_READY", TOSERVER_STATE_STARTUP, &Server::handleCommand_ClientReady }, // 0x43
null_command_handler, // 0x44
@ -167,7 +167,7 @@ const ClientCommandFactory clientCommandFactoryTable[TOCLIENT_NUM_MSG_TYPES] =
{ "TOCLIENT_TIME_OF_DAY", 0, true }, // 0x29
{ "TOCLIENT_CSM_RESTRICTION_FLAGS", 0, true }, // 0x2A
{ "TOCLIENT_PLAYER_SPEED", 0, true }, // 0x2B
{ "TOCLIENT_MEDIA_PUSH", 0, true }, // 0x2C (sent over channel 1 too)
{ "TOCLIENT_MEDIA_PUSH", 0, true }, // 0x2C (sent over channel 1 too if legacy)
null_command_factory, // 0x2D
null_command_factory, // 0x2E
{ "TOCLIENT_CHAT_MESSAGE", 0, true }, // 0x2F

View file

@ -362,16 +362,15 @@ void Server::handleCommand_RequestMedia(NetworkPacket* pkt)
session_t peer_id = pkt->getPeerId();
infostream << "Sending " << numfiles << " files to " <<
getPlayerName(peer_id) << std::endl;
verbosestream << "TOSERVER_REQUEST_MEDIA: " << std::endl;
verbosestream << "TOSERVER_REQUEST_MEDIA: requested file(s)" << std::endl;
for (u16 i = 0; i < numfiles; i++) {
std::string name;
*pkt >> name;
tosend.push_back(name);
verbosestream << "TOSERVER_REQUEST_MEDIA: requested file "
<< name << std::endl;
tosend.emplace_back(name);
verbosestream << " " << name << std::endl;
}
sendRequestedMedia(peer_id, tosend);
@ -1801,3 +1800,30 @@ void Server::handleCommand_ModChannelMsg(NetworkPacket *pkt)
broadcastModChannelMessage(channel_name, channel_msg, peer_id);
}
void Server::handleCommand_HaveMedia(NetworkPacket *pkt)
{
std::vector<u32> tokens;
u8 numtokens;
*pkt >> numtokens;
for (u16 i = 0; i < numtokens; i++) {
u32 n;
*pkt >> n;
tokens.emplace_back(n);
}
const session_t peer_id = pkt->getPeerId();
auto player = m_env->getPlayer(peer_id);
for (const u32 token : tokens) {
auto it = m_pending_dyn_media.find(token);
if (it == m_pending_dyn_media.end())
continue;
if (it->second.waiting_players.count(peer_id)) {
it->second.waiting_players.erase(peer_id);
if (player)
getScriptIface()->on_dynamic_media_added(token, player->getName());
}
}
}