aboutsummaryrefslogtreecommitdiff
path: root/src/network
diff options
context:
space:
mode:
authorElias Fleckenstein <eliasfleckenstein@web.de>2021-09-19 20:56:13 +0200
committerElias Fleckenstein <eliasfleckenstein@web.de>2021-09-19 20:56:13 +0200
commitc8900e169a1ddceec07a449f1ae7c4322ff02036 (patch)
tree5156605fb473d25786426eb6876ba2e7d3b7507b /src/network
parent950d2c9b3e10cbace9236e820c8119d1abb9e01f (diff)
parente0529da5c84f224c380e6d5e063392cb01f85683 (diff)
downloaddragonfireclient-c8900e169a1ddceec07a449f1ae7c4322ff02036.tar.xz
Merge branch 'master' of https://github.com/minetest/minetest
Diffstat (limited to 'src/network')
-rw-r--r--src/network/clientopcodes.cpp2
-rw-r--r--src/network/clientpackethandler.cpp187
-rw-r--r--src/network/connection.cpp72
-rw-r--r--src/network/connection.h40
-rw-r--r--src/network/connectionthreads.cpp41
-rw-r--r--src/network/networkpacket.cpp9
-rw-r--r--src/network/networkpacket.h3
-rw-r--r--src/network/networkprotocol.h14
-rw-r--r--src/network/serveropcodes.cpp4
-rw-r--r--src/network/serverpackethandler.cpp54
10 files changed, 241 insertions, 185 deletions
diff --git a/src/network/clientopcodes.cpp b/src/network/clientopcodes.cpp
index 55cfdd4dc..a98a5e7d1 100644
--- a/src/network/clientopcodes.cpp
+++ b/src/network/clientopcodes.cpp
@@ -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
diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp
index 2fea03fbf..6497bb26a 100644
--- a/src/network/clientpackethandler.cpp
+++ b/src/network/clientpackethandler.cpp
@@ -90,7 +90,7 @@ void Client::handleCommand_Hello(NetworkPacket* pkt)
// This is only neccessary though when we actually want to add casing support
if (m_chosen_auth_mech != AUTH_MECHANISM_NONE) {
- // we recieved a TOCLIENT_HELLO while auth was already going on
+ // we received a TOCLIENT_HELLO while auth was already going on
errorstream << "Client: TOCLIENT_HELLO while auth was already going on"
<< "(chosen_mech=" << m_chosen_auth_mech << ")." << std::endl;
if (m_chosen_auth_mech == AUTH_MECHANISM_SRP ||
@@ -158,7 +158,7 @@ void Client::handleCommand_AcceptSudoMode(NetworkPacket* pkt)
m_password = m_new_password;
- verbosestream << "Client: Recieved TOCLIENT_ACCEPT_SUDO_MODE." << std::endl;
+ verbosestream << "Client: Received TOCLIENT_ACCEPT_SUDO_MODE." << std::endl;
// send packet to actually set the password
startAuth(AUTH_MECHANISM_FIRST_SRP);
@@ -263,7 +263,7 @@ void Client::handleCommand_NodemetaChanged(NetworkPacket *pkt)
return;
std::istringstream is(pkt->readLongString(), std::ios::binary);
- std::stringstream sstr;
+ std::stringstream sstr(std::ios::binary | std::ios::in | std::ios::out);
decompressZlib(is, sstr);
NodeMetadataList meta_updates_list(false);
@@ -684,21 +684,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);
}
@@ -730,31 +728,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();
- // Mesh update thread must be stopped while
- // updating content definitions
- sanity_check(!m_mesh_update_thread.isRunning());
+ if (init_phase) {
+ // 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;
+ }
}
}
@@ -769,12 +774,11 @@ void Client::handleCommand_NodeDef(NetworkPacket* pkt)
// Decompress node definitions
std::istringstream tmp_is(pkt->readLongString(), std::ios::binary);
- std::ostringstream tmp_os;
+ std::stringstream tmp_os(std::ios::binary | std::ios::in | std::ios::out);
decompressZlib(tmp_is, tmp_os);
// Deserialize node definitions
- std::istringstream tmp_is2(tmp_os.str());
- m_nodedef->deSerialize(tmp_is2);
+ m_nodedef->deSerialize(tmp_os);
m_nodedef_received = true;
}
@@ -789,12 +793,11 @@ void Client::handleCommand_ItemDef(NetworkPacket* pkt)
// Decompress item definitions
std::istringstream tmp_is(pkt->readLongString(), std::ios::binary);
- std::ostringstream tmp_os;
+ std::stringstream tmp_os(std::ios::binary | std::ios::in | std::ios::out);
decompressZlib(tmp_is, tmp_os);
// Deserialize node definitions
- std::istringstream tmp_is2(tmp_os.str());
- m_itemdef->deSerialize(tmp_is2);
+ m_itemdef->deSerialize(tmp_os);
m_itemdef_received = true;
}
@@ -915,6 +918,11 @@ void Client::handleCommand_Privileges(NetworkPacket* pkt)
m_privileges.insert(priv);
infostream << priv << " ";
}
+
+ // Enable basic_debug on server versions before it was added
+ if (m_proto_ver < 40)
+ m_privileges.insert("basic_debug");
+
infostream << std::endl;
}
@@ -1078,6 +1086,7 @@ void Client::handleCommand_HudAdd(NetworkPacket* pkt)
v2s32 size;
s16 z_index = 0;
std::string text2;
+ u32 style = 0;
*pkt >> server_id >> type >> pos >> name >> scale >> text >> number >> item
>> dir >> align >> offset;
@@ -1086,6 +1095,7 @@ void Client::handleCommand_HudAdd(NetworkPacket* pkt)
*pkt >> size;
*pkt >> z_index;
*pkt >> text2;
+ *pkt >> style;
} catch(PacketError &e) {};
ClientEvent *event = new ClientEvent();
@@ -1106,6 +1116,7 @@ void Client::handleCommand_HudAdd(NetworkPacket* pkt)
event->hudadd->size = size;
event->hudadd->z_index = z_index;
event->hudadd->text2 = text2;
+ event->hudadd->style = style;
m_client_event_queue.push(event);
}
@@ -1133,17 +1144,29 @@ void Client::handleCommand_HudChange(NetworkPacket* pkt)
*pkt >> server_id >> stat;
- if (stat == HUD_STAT_POS || stat == HUD_STAT_SCALE ||
- stat == HUD_STAT_ALIGN || stat == HUD_STAT_OFFSET)
- *pkt >> v2fdata;
- else if (stat == HUD_STAT_NAME || stat == HUD_STAT_TEXT || stat == HUD_STAT_TEXT2)
- *pkt >> sdata;
- else if (stat == HUD_STAT_WORLD_POS)
- *pkt >> v3fdata;
- else if (stat == HUD_STAT_SIZE )
- *pkt >> v2s32data;
- else
- *pkt >> intdata;
+ // Keep in sync with:server.cpp -> SendHUDChange
+ switch ((HudElementStat)stat) {
+ case HUD_STAT_POS:
+ case HUD_STAT_SCALE:
+ case HUD_STAT_ALIGN:
+ case HUD_STAT_OFFSET:
+ *pkt >> v2fdata;
+ break;
+ case HUD_STAT_NAME:
+ case HUD_STAT_TEXT:
+ case HUD_STAT_TEXT2:
+ *pkt >> sdata;
+ break;
+ case HUD_STAT_WORLD_POS:
+ *pkt >> v3fdata;
+ break;
+ case HUD_STAT_SIZE:
+ *pkt >> v2s32data;
+ break;
+ default:
+ *pkt >> intdata;
+ break;
+ }
ClientEvent *event = new ClientEvent();
event->type = CE_HUDCHANGE;
@@ -1507,46 +1530,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);
}
/*
diff --git a/src/network/connection.cpp b/src/network/connection.cpp
index 0ba8c36b2..a4970954f 100644
--- a/src/network/connection.cpp
+++ b/src/network/connection.cpp
@@ -200,17 +200,12 @@ RPBSearchResult ReliablePacketBuffer::findPacket(u16 seqnum)
return i;
}
-RPBSearchResult ReliablePacketBuffer::notFound()
-{
- return m_list.end();
-}
-
bool ReliablePacketBuffer::getFirstSeqnum(u16& result)
{
MutexAutoLock listlock(m_list_mutex);
if (m_list.empty())
return false;
- const BufferedPacket &p = *m_list.begin();
+ const BufferedPacket &p = m_list.front();
result = readU16(&p.data[BASE_HEADER_SIZE + 1]);
return true;
}
@@ -220,14 +215,14 @@ BufferedPacket ReliablePacketBuffer::popFirst()
MutexAutoLock listlock(m_list_mutex);
if (m_list.empty())
throw NotFoundException("Buffer is empty");
- BufferedPacket p = *m_list.begin();
- m_list.erase(m_list.begin());
+ BufferedPacket p = std::move(m_list.front());
+ m_list.pop_front();
if (m_list.empty()) {
m_oldest_non_answered_ack = 0;
} else {
m_oldest_non_answered_ack =
- readU16(&m_list.begin()->data[BASE_HEADER_SIZE + 1]);
+ readU16(&m_list.front().data[BASE_HEADER_SIZE + 1]);
}
return p;
}
@@ -241,15 +236,7 @@ BufferedPacket ReliablePacketBuffer::popSeqnum(u16 seqnum)
<< " not found in reliable buffer"<<std::endl);
throw NotFoundException("seqnum not found in buffer");
}
- BufferedPacket p = *r;
-
-
- RPBSearchResult next = r;
- ++next;
- if (next != notFound()) {
- u16 s = readU16(&(next->data[BASE_HEADER_SIZE+1]));
- m_oldest_non_answered_ack = s;
- }
+ BufferedPacket p = std::move(*r);
m_list.erase(r);
@@ -257,12 +244,12 @@ BufferedPacket ReliablePacketBuffer::popSeqnum(u16 seqnum)
m_oldest_non_answered_ack = 0;
} else {
m_oldest_non_answered_ack =
- readU16(&m_list.begin()->data[BASE_HEADER_SIZE + 1]);
+ readU16(&m_list.front().data[BASE_HEADER_SIZE + 1]);
}
return p;
}
-void ReliablePacketBuffer::insert(BufferedPacket &p, u16 next_expected)
+void ReliablePacketBuffer::insert(const BufferedPacket &p, u16 next_expected)
{
MutexAutoLock listlock(m_list_mutex);
if (p.data.getSize() < BASE_HEADER_SIZE + 3) {
@@ -355,7 +342,7 @@ void ReliablePacketBuffer::insert(BufferedPacket &p, u16 next_expected)
}
/* update last packet number */
- m_oldest_non_answered_ack = readU16(&(*m_list.begin()).data[BASE_HEADER_SIZE+1]);
+ m_oldest_non_answered_ack = readU16(&m_list.front().data[BASE_HEADER_SIZE+1]);
}
void ReliablePacketBuffer::incrementTimeouts(float dtime)
@@ -367,17 +354,19 @@ void ReliablePacketBuffer::incrementTimeouts(float dtime)
}
}
-std::list<BufferedPacket> ReliablePacketBuffer::getTimedOuts(float timeout,
- unsigned int max_packets)
+std::list<BufferedPacket>
+ ReliablePacketBuffer::getTimedOuts(float timeout, u32 max_packets)
{
MutexAutoLock listlock(m_list_mutex);
std::list<BufferedPacket> timed_outs;
for (BufferedPacket &bufferedPacket : m_list) {
if (bufferedPacket.time >= timeout) {
+ // caller will resend packet so reset time and increase counter
+ bufferedPacket.time = 0.0f;
+ bufferedPacket.resend_count++;
+
timed_outs.push_back(bufferedPacket);
- //this packet will be sent right afterwards reset timeout here
- bufferedPacket.time = 0.0f;
if (timed_outs.size() >= max_packets)
break;
}
@@ -1051,20 +1040,20 @@ bool UDPPeer::processReliableSendCommand(
m_connection->GetProtocolID(), m_connection->GetPeerID(),
c.channelnum);
- toadd.push(p);
+ toadd.push(std::move(p));
}
if (have_sequence_number) {
volatile u16 pcount = 0;
while (!toadd.empty()) {
- BufferedPacket p = toadd.front();
+ BufferedPacket p = std::move(toadd.front());
toadd.pop();
// LOG(dout_con<<connection->getDesc()
// << " queuing reliable packet for peer_id: " << c.peer_id
// << " channel: " << (c.channelnum&0xFF)
// << " seqnum: " << readU16(&p.data[BASE_HEADER_SIZE+1])
// << std::endl)
- chan.queued_reliables.push(p);
+ chan.queued_reliables.push(std::move(p));
pcount++;
}
sanity_check(chan.queued_reliables.size() < 0xFFFF);
@@ -1208,12 +1197,19 @@ Connection::~Connection()
}
/* Internal stuff */
-void Connection::putEvent(ConnectionEvent &e)
+
+void Connection::putEvent(const ConnectionEvent &e)
{
assert(e.type != CONNEVENT_NONE); // Pre-condition
m_event_queue.push_back(e);
}
+void Connection::putEvent(ConnectionEvent &&e)
+{
+ assert(e.type != CONNEVENT_NONE); // Pre-condition
+ m_event_queue.push_back(std::move(e));
+}
+
void Connection::TriggerSend()
{
m_sendThread->Trigger();
@@ -1299,7 +1295,7 @@ ConnectionEvent Connection::waitEvent(u32 timeout_ms)
}
}
-void Connection::putCommand(ConnectionCommand &c)
+void Connection::putCommand(const ConnectionCommand &c)
{
if (!m_shutting_down) {
m_command_queue.push_back(c);
@@ -1307,6 +1303,14 @@ void Connection::putCommand(ConnectionCommand &c)
}
}
+void Connection::putCommand(ConnectionCommand &&c)
+{
+ if (!m_shutting_down) {
+ m_command_queue.push_back(std::move(c));
+ m_sendThread->Trigger();
+ }
+}
+
void Connection::Serve(Address bind_addr)
{
ConnectionCommand c;
@@ -1408,7 +1412,7 @@ void Connection::Send(session_t peer_id, u8 channelnum,
ConnectionCommand c;
c.send(peer_id, channelnum, pkt, reliable);
- putCommand(c);
+ putCommand(std::move(c));
}
Address Connection::GetPeerAddress(session_t peer_id)
@@ -1508,12 +1512,12 @@ u16 Connection::createPeer(Address& sender, MTProtocols protocol, int fd)
<< "createPeer(): giving peer_id=" << peer_id_new << std::endl);
ConnectionCommand cmd;
- SharedBuffer<u8> reply(4);
+ Buffer<u8> reply(4);
writeU8(&reply[0], PACKET_TYPE_CONTROL);
writeU8(&reply[1], CONTROLTYPE_SET_PEER_ID);
writeU16(&reply[2], peer_id_new);
cmd.createPeer(peer_id_new,reply);
- putCommand(cmd);
+ putCommand(std::move(cmd));
// Create peer addition event
ConnectionEvent e;
@@ -1560,7 +1564,7 @@ void Connection::sendAck(session_t peer_id, u8 channelnum, u16 seqnum)
writeU16(&ack[2], seqnum);
c.ack(peer_id, channelnum, ack);
- putCommand(c);
+ putCommand(std::move(c));
m_sendThread->Trigger();
}
diff --git a/src/network/connection.h b/src/network/connection.h
index 24cd4fe4a..49bb65c3e 100644
--- a/src/network/connection.h
+++ b/src/network/connection.h
@@ -19,7 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once
-#include "irrlichttypes_bloated.h"
+#include "irrlichttypes.h"
#include "peerhandler.h"
#include "socket.h"
#include "constants.h"
@@ -29,7 +29,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "util/numeric.h"
#include "networkprotocol.h"
#include <iostream>
-#include <fstream>
#include <vector>
#include <map>
@@ -242,20 +241,19 @@ public:
BufferedPacket popFirst();
BufferedPacket popSeqnum(u16 seqnum);
- void insert(BufferedPacket &p, u16 next_expected);
+ void insert(const BufferedPacket &p, u16 next_expected);
void incrementTimeouts(float dtime);
- std::list<BufferedPacket> getTimedOuts(float timeout,
- unsigned int max_packets);
+ std::list<BufferedPacket> getTimedOuts(float timeout, u32 max_packets);
void print();
bool empty();
- RPBSearchResult notFound();
u32 size();
private:
RPBSearchResult findPacket(u16 seqnum); // does not perform locking
+ inline RPBSearchResult notFound() { return m_list.end(); }
std::list<BufferedPacket> m_list;
@@ -329,18 +327,6 @@ struct ConnectionCommand
bool raw = false;
ConnectionCommand() = default;
- ConnectionCommand &operator=(const ConnectionCommand &other)
- {
- type = other.type;
- address = other.address;
- peer_id = other.peer_id;
- channelnum = other.channelnum;
- // We must copy the buffer here to prevent race condition
- data = SharedBuffer<u8>(*other.data, other.data.getSize());
- reliable = other.reliable;
- raw = other.raw;
- return *this;
- }
void serve(Address address_)
{
@@ -364,7 +350,7 @@ struct ConnectionCommand
void send(session_t peer_id_, u8 channelnum_, NetworkPacket *pkt, bool reliable_);
- void ack(session_t peer_id_, u8 channelnum_, const SharedBuffer<u8> &data_)
+ void ack(session_t peer_id_, u8 channelnum_, const Buffer<u8> &data_)
{
type = CONCMD_ACK;
peer_id = peer_id_;
@@ -373,7 +359,7 @@ struct ConnectionCommand
reliable = false;
}
- void createPeer(session_t peer_id_, const SharedBuffer<u8> &data_)
+ void createPeer(session_t peer_id_, const Buffer<u8> &data_)
{
type = CONCMD_CREATE_PEER;
peer_id = peer_id_;
@@ -707,7 +693,7 @@ struct ConnectionEvent
ConnectionEvent() = default;
- std::string describe()
+ const char *describe() const
{
switch(type) {
case CONNEVENT_NONE:
@@ -724,7 +710,7 @@ struct ConnectionEvent
return "Invalid ConnectionEvent";
}
- void dataReceived(session_t peer_id_, const SharedBuffer<u8> &data_)
+ void dataReceived(session_t peer_id_, const Buffer<u8> &data_)
{
type = CONNEVENT_DATA_RECEIVED;
peer_id = peer_id_;
@@ -763,7 +749,9 @@ public:
/* Interface */
ConnectionEvent waitEvent(u32 timeout_ms);
- void putCommand(ConnectionCommand &c);
+ // Warning: creates an unnecessary copy, prefer putCommand(T&&) if possible
+ void putCommand(const ConnectionCommand &c);
+ void putCommand(ConnectionCommand &&c);
void SetTimeoutMs(u32 timeout) { m_bc_receive_timeout = timeout; }
void Serve(Address bind_addr);
@@ -802,11 +790,14 @@ protected:
}
UDPSocket m_udpSocket;
+ // Command queue: user -> SendThread
MutexedQueue<ConnectionCommand> m_command_queue;
bool Receive(NetworkPacket *pkt, u32 timeout);
- void putEvent(ConnectionEvent &e);
+ // Warning: creates an unnecessary copy, prefer putEvent(T&&) if possible
+ void putEvent(const ConnectionEvent &e);
+ void putEvent(ConnectionEvent &&e);
void TriggerSend();
@@ -815,6 +806,7 @@ protected:
return getPeerNoEx(PEER_ID_SERVER) != nullptr;
}
private:
+ // Event queue: ReceiveThread -> user
MutexedQueue<ConnectionEvent> m_event_queue;
session_t m_peer_id = 0;
diff --git a/src/network/connectionthreads.cpp b/src/network/connectionthreads.cpp
index 7b62bc792..47678dac5 100644
--- a/src/network/connectionthreads.cpp
+++ b/src/network/connectionthreads.cpp
@@ -174,6 +174,11 @@ void ConnectionSendThread::runTimeouts(float dtime)
std::vector<session_t> timeouted_peers;
std::vector<session_t> peerIds = m_connection->getPeerIDs();
+ const u32 numpeers = m_connection->m_peers.size();
+
+ if (numpeers == 0)
+ return;
+
for (session_t &peerId : peerIds) {
PeerHelper peer = m_connection->getPeerNoEx(peerId);
@@ -209,7 +214,6 @@ void ConnectionSendThread::runTimeouts(float dtime)
float resend_timeout = udpPeer->getResendTimeout();
bool retry_count_exceeded = false;
for (Channel &channel : udpPeer->channels) {
- std::list<BufferedPacket> timed_outs;
// Remove timed out incomplete unreliable split packets
channel.incoming_splits.removeUnreliableTimedOuts(dtime, m_timeout);
@@ -217,13 +221,8 @@ void ConnectionSendThread::runTimeouts(float dtime)
// Increment reliable packet times
channel.outgoing_reliables_sent.incrementTimeouts(dtime);
- unsigned int numpeers = m_connection->m_peers.size();
-
- if (numpeers == 0)
- return;
-
// Re-send timed out outgoing reliables
- timed_outs = channel.outgoing_reliables_sent.getTimedOuts(resend_timeout,
+ auto timed_outs = channel.outgoing_reliables_sent.getTimedOuts(resend_timeout,
(m_max_data_packets_per_iteration / numpeers));
channel.UpdatePacketLossCounter(timed_outs.size());
@@ -231,16 +230,14 @@ void ConnectionSendThread::runTimeouts(float dtime)
m_iteration_packets_avaialble -= timed_outs.size();
- for (std::list<BufferedPacket>::iterator k = timed_outs.begin();
- k != timed_outs.end(); ++k) {
- session_t peer_id = readPeerId(*(k->data));
- u8 channelnum = readChannel(*(k->data));
- u16 seqnum = readU16(&(k->data[BASE_HEADER_SIZE + 1]));
+ for (const auto &k : timed_outs) {
+ session_t peer_id = readPeerId(*k.data);
+ u8 channelnum = readChannel(*k.data);
+ u16 seqnum = readU16(&(k.data[BASE_HEADER_SIZE + 1]));
- channel.UpdateBytesLost(k->data.getSize());
- k->resend_count++;
+ channel.UpdateBytesLost(k.data.getSize());
- if (k->resend_count > MAX_RELIABLE_RETRY) {
+ if (k.resend_count > MAX_RELIABLE_RETRY) {
retry_count_exceeded = true;
timeouted_peers.push_back(peer->id);
/* no need to check additional packets if a single one did timeout*/
@@ -249,14 +246,14 @@ void ConnectionSendThread::runTimeouts(float dtime)
LOG(derr_con << m_connection->getDesc()
<< "RE-SENDING timed-out RELIABLE to "
- << k->address.serializeString()
+ << k.address.serializeString()
<< "(t/o=" << resend_timeout << "): "
<< "from_peer_id=" << peer_id
<< ", channel=" << ((int) channelnum & 0xff)
<< ", seqnum=" << seqnum
<< std::endl);
- rawSend(*k);
+ rawSend(k);
// do not handle rtt here as we can't decide if this packet was
// lost or really takes more time to transmit
@@ -375,7 +372,7 @@ bool ConnectionSendThread::rawSendAsPacket(session_t peer_id, u8 channelnum,
<< " INFO: queueing reliable packet for peer_id: " << peer_id
<< " channel: " << (u32)channelnum
<< " seqnum: " << seqnum << std::endl);
- channel->queued_reliables.push(p);
+ channel->queued_reliables.push(std::move(p));
return false;
}
@@ -717,13 +714,15 @@ void ConnectionSendThread::sendPackets(float dtime)
channel.outgoing_reliables_sent.size()
< channel.getWindowSize() &&
peer->m_increment_packets_remaining > 0) {
- BufferedPacket p = channel.queued_reliables.front();
+ BufferedPacket p = std::move(channel.queued_reliables.front());
channel.queued_reliables.pop();
+
LOG(dout_con << m_connection->getDesc()
<< " INFO: sending a queued reliable packet "
<< " channel: " << i
<< ", seqnum: " << readU16(&p.data[BASE_HEADER_SIZE + 1])
<< std::endl);
+
sendAsPacketReliable(p, &channel);
peer->m_increment_packets_remaining--;
}
@@ -911,7 +910,7 @@ void ConnectionReceiveThread::receive(SharedBuffer<u8> &packetdata,
if (data_left) {
ConnectionEvent e;
e.dataReceived(peer_id, resultdata);
- m_connection->putEvent(e);
+ m_connection->putEvent(std::move(e));
}
}
catch (ProcessedSilentlyException &e) {
@@ -1022,7 +1021,7 @@ void ConnectionReceiveThread::receive(SharedBuffer<u8> &packetdata,
ConnectionEvent e;
e.dataReceived(peer_id, resultdata);
- m_connection->putEvent(e);
+ m_connection->putEvent(std::move(e));
}
catch (ProcessedSilentlyException &e) {
}
diff --git a/src/network/networkpacket.cpp b/src/network/networkpacket.cpp
index a71e26572..6b8b0f703 100644
--- a/src/network/networkpacket.cpp
+++ b/src/network/networkpacket.cpp
@@ -549,14 +549,11 @@ NetworkPacket& NetworkPacket::operator<<(video::SColor src)
return *this;
}
-SharedBuffer<u8> NetworkPacket::oldForgePacket()
+Buffer<u8> NetworkPacket::oldForgePacket()
{
- SharedBuffer<u8> sb(m_datasize + 2);
+ Buffer<u8> sb(m_datasize + 2);
writeU16(&sb[0], m_command);
+ memcpy(&sb[2], m_data.data(), m_datasize);
- u8* datas = getU8Ptr(0);
-
- if (datas != NULL)
- memcpy(&sb[2], datas, m_datasize);
return sb;
}
diff --git a/src/network/networkpacket.h b/src/network/networkpacket.h
index c7ff03b8e..b1c44f055 100644
--- a/src/network/networkpacket.h
+++ b/src/network/networkpacket.h
@@ -115,7 +115,8 @@ public:
NetworkPacket &operator<<(video::SColor src);
// Temp, we remove SharedBuffer when migration finished
- SharedBuffer<u8> oldForgePacket();
+ // ^ this comment has been here for 4 years
+ Buffer<u8> oldForgePacket();
private:
void checkReadOffset(u32 from_offset, u32 field_size);
diff --git a/src/network/networkprotocol.h b/src/network/networkprotocol.h
index 88a5ac177..8214cc5b1 100644
--- a/src/network/networkprotocol.h
+++ b/src/network/networkprotocol.h
@@ -205,6 +205,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
Updated set_sky packet
Adds new sun, moon and stars packets
Minimap modes
+ PROTOCOL VERSION 40:
+ Added 'basic_debug' privilege
+ TOCLIENT_MEDIA_PUSH changed, TOSERVER_HAVE_MEDIA added
*/
#define LATEST_PROTOCOL_VERSION 40
@@ -315,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)
@@ -936,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,
diff --git a/src/network/serveropcodes.cpp b/src/network/serveropcodes.cpp
index aea5d7174..44b65e8da 100644
--- a/src/network/serveropcodes.cpp
+++ b/src/network/serveropcodes.cpp
@@ -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
diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp
index 708ddbf20..4c609644f 100644
--- a/src/network/serverpackethandler.cpp
+++ b/src/network/serverpackethandler.cpp
@@ -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);
@@ -510,10 +509,6 @@ void Server::process_PlayerPos(RemotePlayer *player, PlayerSAO *playersao,
playersao->setWantedRange(wanted_range);
player->keyPressed = keyPressed;
- player->control.up = (keyPressed & (0x1 << 0));
- player->control.down = (keyPressed & (0x1 << 1));
- player->control.left = (keyPressed & (0x1 << 2));
- player->control.right = (keyPressed & (0x1 << 3));
player->control.jump = (keyPressed & (0x1 << 4));
player->control.aux1 = (keyPressed & (0x1 << 5));
player->control.sneak = (keyPressed & (0x1 << 6));
@@ -832,7 +827,6 @@ void Server::handleCommand_Damage(NetworkPacket* pkt)
PlayerHPChangeReason reason(PlayerHPChangeReason::FALL);
playersao->setHP((s32)playersao->getHP() - (s32)damage, reason);
- SendPlayerHPOrDie(playersao, reason);
}
}
@@ -1117,9 +1111,6 @@ void Server::handleCommand_Interact(NetworkPacket *pkt)
float time_from_last_punch =
playersao->resetTimeFromLastPunch();
- u16 src_original_hp = pointed_object->getHP();
- u16 dst_origin_hp = playersao->getHP();
-
u16 wear = pointed_object->punch(dir, &toolcap, playersao,
time_from_last_punch);
@@ -1129,18 +1120,6 @@ void Server::handleCommand_Interact(NetworkPacket *pkt)
if (changed)
playersao->setWieldedItem(selected_item);
- // If the object is a player and its HP changed
- if (src_original_hp != pointed_object->getHP() &&
- pointed_object->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
- SendPlayerHPOrDie((PlayerSAO *)pointed_object,
- PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, playersao));
- }
-
- // If the puncher is a player and its HP changed
- if (dst_origin_hp != playersao->getHP())
- SendPlayerHPOrDie(playersao,
- PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, pointed_object));
-
return;
} // action == INTERACT_START_DIGGING
@@ -1821,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());
+ }
+ }
+}