aboutsummaryrefslogtreecommitdiff
path: root/src/network
diff options
context:
space:
mode:
Diffstat (limited to 'src/network')
-rw-r--r--src/network/networkexceptions.h8
-rw-r--r--src/network/networkpacket.cpp49
-rw-r--r--src/network/networkpacket.h2
-rw-r--r--src/network/serverpackethandler.cpp40
4 files changed, 56 insertions, 43 deletions
diff --git a/src/network/networkexceptions.h b/src/network/networkexceptions.h
index f4913928c..58a3bb490 100644
--- a/src/network/networkexceptions.h
+++ b/src/network/networkexceptions.h
@@ -56,12 +56,6 @@ public:
InvalidIncomingDataException(const char *s) : BaseException(s) {}
};
-class InvalidOutgoingDataException : public BaseException
-{
-public:
- InvalidOutgoingDataException(const char *s) : BaseException(s) {}
-};
-
class NoIncomingDataException : public BaseException
{
public:
@@ -103,4 +97,4 @@ class SendFailedException : public BaseException
{
public:
SendFailedException(const std::string &s) : BaseException(s) {}
-}; \ No newline at end of file
+};
diff --git a/src/network/networkpacket.cpp b/src/network/networkpacket.cpp
index 6d0abb12c..a71e26572 100644
--- a/src/network/networkpacket.cpp
+++ b/src/network/networkpacket.cpp
@@ -50,7 +50,7 @@ void NetworkPacket::checkReadOffset(u32 from_offset, u32 field_size)
}
}
-void NetworkPacket::putRawPacket(u8 *data, u32 datasize, session_t peer_id)
+void NetworkPacket::putRawPacket(const u8 *data, u32 datasize, session_t peer_id)
{
// If a m_command is already set, we are rewriting on same packet
// This is not permitted
@@ -145,6 +145,8 @@ void NetworkPacket::putLongString(const std::string &src)
putRawString(src.c_str(), msgsize);
}
+static constexpr bool NEED_SURROGATE_CODING = sizeof(wchar_t) > 2;
+
NetworkPacket& NetworkPacket::operator>>(std::wstring& dst)
{
checkReadOffset(m_read_offset, 2);
@@ -160,9 +162,16 @@ NetworkPacket& NetworkPacket::operator>>(std::wstring& dst)
checkReadOffset(m_read_offset, strLen * 2);
dst.reserve(strLen);
- for(u16 i=0; i<strLen; i++) {
- wchar_t c16 = readU16(&m_data[m_read_offset]);
- dst.append(&c16, 1);
+ for (u16 i = 0; i < strLen; i++) {
+ wchar_t c = readU16(&m_data[m_read_offset]);
+ if (NEED_SURROGATE_CODING && c >= 0xD800 && c < 0xDC00 && i+1 < strLen) {
+ i++;
+ m_read_offset += sizeof(u16);
+
+ wchar_t c2 = readU16(&m_data[m_read_offset]);
+ c = 0x10000 + ( ((c & 0x3ff) << 10) | (c2 & 0x3ff) );
+ }
+ dst.push_back(c);
m_read_offset += sizeof(u16);
}
@@ -175,15 +184,37 @@ NetworkPacket& NetworkPacket::operator<<(const std::wstring &src)
throw PacketError("String too long");
}
- u16 msgsize = src.size();
+ if (!NEED_SURROGATE_CODING || src.size() == 0) {
+ *this << static_cast<u16>(src.size());
+ for (u16 i = 0; i < src.size(); i++)
+ *this << static_cast<u16>(src[i]);
- *this << msgsize;
+ return *this;
+ }
- // Write string
- for (u16 i=0; i<msgsize; i++) {
- *this << (u16) src[i];
+ // write dummy value, to be overwritten later
+ const u32 len_offset = m_read_offset;
+ u32 written = 0;
+ *this << static_cast<u16>(0xfff0);
+
+ for (u16 i = 0; i < src.size(); i++) {
+ wchar_t c = src[i];
+ if (c > 0xffff) {
+ // Encode high code-points as surrogate pairs
+ u32 n = c - 0x10000;
+ *this << static_cast<u16>(0xD800 | (n >> 10))
+ << static_cast<u16>(0xDC00 | (n & 0x3ff));
+ written += 2;
+ } else {
+ *this << static_cast<u16>(c);
+ written++;
+ }
}
+ if (written > WIDE_STRING_MAX_LEN)
+ throw PacketError("String too long");
+ writeU16(&m_data[len_offset], written);
+
return *this;
}
diff --git a/src/network/networkpacket.h b/src/network/networkpacket.h
index e77bfb744..c7ff03b8e 100644
--- a/src/network/networkpacket.h
+++ b/src/network/networkpacket.h
@@ -34,7 +34,7 @@ public:
~NetworkPacket();
- void putRawPacket(u8 *data, u32 datasize, session_t peer_id);
+ void putRawPacket(const u8 *data, u32 datasize, session_t peer_id);
void clear();
// Getters
diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp
index c636d01e1..270b8e01f 100644
--- a/src/network/serverpackethandler.cpp
+++ b/src/network/serverpackethandler.cpp
@@ -56,12 +56,12 @@ void Server::handleCommand_Init(NetworkPacket* pkt)
session_t peer_id = pkt->getPeerId();
RemoteClient *client = getClient(peer_id, CS_Created);
+ Address addr;
std::string addr_s;
try {
- Address address = getPeerAddress(peer_id);
- addr_s = address.serializeString();
- }
- catch (con::PeerNotFoundException &e) {
+ addr = m_con->GetPeerAddress(peer_id);
+ addr_s = addr.serializeString();
+ } catch (con::PeerNotFoundException &e) {
/*
* no peer for this packet found
* most common reason is peer timeout, e.g. peer didn't
@@ -73,13 +73,14 @@ void Server::handleCommand_Init(NetworkPacket* pkt)
return;
}
- // If net_proto_version is set, this client has already been handled
if (client->getState() > CS_Created) {
verbosestream << "Server: Ignoring multiple TOSERVER_INITs from " <<
addr_s << " (peer_id=" << peer_id << ")" << std::endl;
return;
}
+ client->setCachedAddress(addr);
+
verbosestream << "Server: Got TOSERVER_INIT from " << addr_s <<
" (peer_id=" << peer_id << ")" << std::endl;
@@ -437,18 +438,20 @@ void Server::handleCommand_GotBlocks(NetworkPacket* pkt)
u8 count;
*pkt >> count;
- RemoteClient *client = getClient(pkt->getPeerId());
-
if ((s16)pkt->getSize() < 1 + (int)count * 6) {
throw con::InvalidIncomingDataException
("GOTBLOCKS length is too short");
}
+ m_clients.lock();
+ RemoteClient *client = m_clients.lockedGetClientNoEx(pkt->getPeerId());
+
for (u16 i = 0; i < count; i++) {
v3s16 p;
*pkt >> p;
client->GotBlock(p);
}
+ m_clients.unlock();
}
void Server::process_PlayerPos(RemotePlayer *player, PlayerSAO *playersao,
@@ -749,21 +752,8 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt)
void Server::handleCommand_ChatMessage(NetworkPacket* pkt)
{
- /*
- u16 command
- u16 length
- wstring message
- */
- u16 len;
- *pkt >> len;
-
std::wstring message;
- for (u16 i = 0; i < len; i++) {
- u16 tmp_wchar;
- *pkt >> tmp_wchar;
-
- message += (wchar_t)tmp_wchar;
- }
+ *pkt >> message;
session_t peer_id = pkt->getPeerId();
RemotePlayer *player = m_env->getPlayer(peer_id);
@@ -775,15 +765,13 @@ void Server::handleCommand_ChatMessage(NetworkPacket* pkt)
return;
}
- // Get player name of this client
std::string name = player->getName();
- std::wstring wname = narrow_to_wide(name);
- std::wstring answer_to_sender = handleChat(name, wname, message, true, player);
+ std::wstring answer_to_sender = handleChat(name, message, true, player);
if (!answer_to_sender.empty()) {
// Send the answer to sender
- SendChatMessage(peer_id, ChatMessage(CHATMESSAGE_TYPE_NORMAL,
- answer_to_sender, wname));
+ SendChatMessage(peer_id, ChatMessage(CHATMESSAGE_TYPE_SYSTEM,
+ answer_to_sender));
}
}