diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ByteBuffer.cpp | 35 | ||||
-rw-r--r-- | src/Crypto.cpp | 3 | ||||
-rw-r--r-- | src/OSSupport/Socket.cpp | 27 | ||||
-rw-r--r-- | src/OSSupport/Socket.h | 9 | ||||
-rw-r--r-- | src/OSSupport/SocketThreads.cpp | 172 | ||||
-rw-r--r-- | src/OSSupport/SocketThreads.h | 26 | ||||
-rw-r--r-- | src/OSSupport/Timer.cpp | 2 | ||||
-rw-r--r-- | src/Protocol/Protocol17x.cpp | 45 | ||||
-rw-r--r-- | src/Root.cpp | 2 | ||||
-rw-r--r-- | src/StringUtils.cpp | 6 | ||||
-rw-r--r-- | src/WorldStorage/WSSAnvil.cpp | 12 | ||||
-rw-r--r-- | src/main.cpp | 34 |
12 files changed, 279 insertions, 94 deletions
diff --git a/src/ByteBuffer.cpp b/src/ByteBuffer.cpp index e06f63a0e..d2d3beb97 100644 --- a/src/ByteBuffer.cpp +++ b/src/ByteBuffer.cpp @@ -54,6 +54,7 @@ public: { TestRead(); TestWrite(); + TestWrap(); } void TestRead(void) @@ -61,11 +62,11 @@ public: cByteBuffer buf(50); buf.Write("\x05\xac\x02\x00", 4); UInt32 v1; - ASSERT(buf.ReadVarInt(v1) && (v1 == 5)); + assert(buf.ReadVarInt(v1) && (v1 == 5)); UInt32 v2; - ASSERT(buf.ReadVarInt(v2) && (v2 == 300)); + assert(buf.ReadVarInt(v2) && (v2 == 300)); UInt32 v3; - ASSERT(buf.ReadVarInt(v3) && (v3 == 0)); + assert(buf.ReadVarInt(v3) && (v3 == 0)); } void TestWrite(void) @@ -76,9 +77,30 @@ public: buf.WriteVarInt(0); AString All; buf.ReadAll(All); - ASSERT(All.size() == 4); - ASSERT(memcmp(All.data(), "\x05\xac\x02\x00", All.size()) == 0); + assert(All.size() == 4); + assert(memcmp(All.data(), "\x05\xac\x02\x00", All.size()) == 0); } + + void TestWrap(void) + { + cByteBuffer buf(3); + for (int i = 0; i < 1000; i++) + { + int FreeSpace = buf.GetFreeSpace(); + assert(buf.GetReadableSpace() == 0); + assert(FreeSpace > 0); + assert(buf.Write("a", 1)); + assert(buf.CanReadBytes(1)); + assert(buf.GetReadableSpace() == 1); + unsigned char v = 0; + assert(buf.ReadByte(v)); + assert(v == 'a'); + assert(buf.GetReadableSpace() == 0); + buf.CommitRead(); + assert(buf.GetFreeSpace() == FreeSpace); // We're back to normal + } + } + } g_ByteBufferTest; #endif @@ -159,7 +181,7 @@ bool cByteBuffer::Write(const char * a_Bytes, int a_Count) int CurReadableSpace = GetReadableSpace(); int WrittenBytes = 0; - if (GetFreeSpace() < a_Count) + if (CurFreeSpace < a_Count) { return false; } @@ -864,3 +886,4 @@ void cByteBuffer::CheckValid(void) const + diff --git a/src/Crypto.cpp b/src/Crypto.cpp index 2045d0385..540b5cfde 100644 --- a/src/Crypto.cpp +++ b/src/Crypto.cpp @@ -214,7 +214,6 @@ int cRSAPrivateKey::Encrypt(const Byte * a_PlainData, size_t a_PlainLength, Byte ASSERT(!"Invalid a_PlainLength!"); return -1; } - size_t DecryptedLength; int res = rsa_pkcs1_encrypt( &m_Rsa, ctr_drbg_random, &m_Ctr_drbg, RSA_PUBLIC, a_PlainLength, a_PlainData, a_EncryptedData @@ -223,7 +222,7 @@ int cRSAPrivateKey::Encrypt(const Byte * a_PlainData, size_t a_PlainLength, Byte { return -1; } - return (int)DecryptedLength; + return (int)m_Rsa.len; } diff --git a/src/OSSupport/Socket.cpp b/src/OSSupport/Socket.cpp index 4226a7535..6afaceedf 100644 --- a/src/OSSupport/Socket.cpp +++ b/src/OSSupport/Socket.cpp @@ -6,7 +6,8 @@ #ifndef _WIN32 #include <netdb.h> #include <unistd.h> - #include <arpa/inet.h> //inet_ntoa() + #include <arpa/inet.h> // inet_ntoa() + #include <sys/ioctl.h> // ioctl() #else #define socklen_t int #endif @@ -320,7 +321,7 @@ bool cSocket::ConnectIPv4(const AString & a_HostNameOrAddr, unsigned short a_Por -int cSocket::Receive(char* a_Buffer, unsigned int a_Length, unsigned int a_Flags) +int cSocket::Receive(char * a_Buffer, unsigned int a_Length, unsigned int a_Flags) { return recv(m_Socket, a_Buffer, a_Length, a_Flags); } @@ -354,3 +355,25 @@ unsigned short cSocket::GetPort(void) const + +void cSocket::SetNonBlocking(void) +{ + #ifdef _WIN32 + u_long NonBlocking = 1; + int res = ioctlsocket(m_Socket, FIONBIO, &NonBlocking); + #else + int NonBlocking = 1; + int res = ioctl(m_Socket, FIONBIO, (char *)&NonBlocking); + #endif + if (res != 0) + { + LOGERROR("Cannot set socket to non-blocking. This would make the server deadlock later on, aborting.\nErr: %d, %d, %s", + res, GetLastError(), GetLastErrorString().c_str() + ); + abort(); + } +} + + + + diff --git a/src/OSSupport/Socket.h b/src/OSSupport/Socket.h index 4ca3d61f4..bdc2babf5 100644 --- a/src/OSSupport/Socket.h +++ b/src/OSSupport/Socket.h @@ -24,6 +24,12 @@ public: { IPv4 = AF_INET, IPv6 = AF_INET6, + + #ifdef _WIN32 + ErrWouldBlock = WSAEWOULDBLOCK, + #else + ErrWouldBlock = EWOULDBLOCK, + #endif } ; #ifdef _WIN32 @@ -110,6 +116,9 @@ public: unsigned short GetPort(void) const; // Returns 0 on failure const AString & GetIPString(void) const { return m_IPString; } + + /** Sets the socket into non-blocking mode */ + void SetNonBlocking(void); private: xSocket m_Socket; diff --git a/src/OSSupport/SocketThreads.cpp b/src/OSSupport/SocketThreads.cpp index 74932daf8..3e2631733 100644 --- a/src/OSSupport/SocketThreads.cpp +++ b/src/OSSupport/SocketThreads.cpp @@ -175,6 +175,7 @@ void cSocketThreads::cSocketThread::AddClient(const cSocket & a_Socket, cCallbac m_Slots[m_NumSlots].m_Client = a_Client; m_Slots[m_NumSlots].m_Socket = a_Socket; + m_Slots[m_NumSlots].m_Socket.SetNonBlocking(); m_Slots[m_NumSlots].m_Outgoing.clear(); m_Slots[m_NumSlots].m_State = sSlot::ssNormal; m_NumSlots++; @@ -213,7 +214,9 @@ bool cSocketThreads::cSocketThread::RemoveClient(const cCallback * a_Client) else { // Query and queue the last batch of outgoing data: - m_Slots[i].m_Client->GetOutgoingData(m_Slots[i].m_Outgoing); + AString Data; + m_Slots[i].m_Client->GetOutgoingData(Data); + m_Slots[i].m_Outgoing.append(Data); if (m_Slots[i].m_Outgoing.empty()) { // No more outgoing data, shut the socket down immediately: @@ -386,38 +389,28 @@ void cSocketThreads::cSocketThread::Execute(void) // The main thread loop: while (!m_ShouldTerminate) { - // Put all sockets into the Read set: + // Read outgoing data from the clients: + QueueOutgoingData(); + + // Put sockets into the sets fd_set fdRead; + fd_set fdWrite; cSocket::xSocket Highest = m_ControlSocket1.GetSocket(); - - PrepareSet(&fdRead, Highest, false); + PrepareSets(&fdRead, &fdWrite, Highest); // Wait for the sockets: timeval Timeout; Timeout.tv_sec = 5; Timeout.tv_usec = 0; - if (select(Highest + 1, &fdRead, NULL, NULL, &Timeout) == -1) + if (select(Highest + 1, &fdRead, &fdWrite, NULL, &Timeout) == -1) { - LOG("select(R) call failed in cSocketThread: \"%s\"", cSocket::GetLastErrorString().c_str()); + LOG("select() call failed in cSocketThread: \"%s\"", cSocket::GetLastErrorString().c_str()); continue; } + // Perform the IO: ReadFromSockets(&fdRead); - - // Test sockets for writing: - fd_set fdWrite; - Highest = m_ControlSocket1.GetSocket(); - PrepareSet(&fdWrite, Highest, true); - Timeout.tv_sec = 0; - Timeout.tv_usec = 0; - if (select(Highest + 1, NULL, &fdWrite, NULL, &Timeout) == -1) - { - LOG("select(W) call failed in cSocketThread: \"%s\"", cSocket::GetLastErrorString().c_str()); - continue; - } - WriteToSockets(&fdWrite); - CleanUpShutSockets(); } // while (!mShouldTerminate) } @@ -426,10 +419,11 @@ void cSocketThreads::cSocketThread::Execute(void) -void cSocketThreads::cSocketThread::PrepareSet(fd_set * a_Set, cSocket::xSocket & a_Highest, bool a_IsForWriting) +void cSocketThreads::cSocketThread::PrepareSets(fd_set * a_Read, fd_set * a_Write, cSocket::xSocket & a_Highest) { - FD_ZERO(a_Set); - FD_SET(m_ControlSocket1.GetSocket(), a_Set); + FD_ZERO(a_Read); + FD_ZERO(a_Write); + FD_SET(m_ControlSocket1.GetSocket(), a_Read); cCSLock Lock(m_Parent->m_CS); for (int i = m_NumSlots - 1; i >= 0; --i) @@ -444,11 +438,16 @@ void cSocketThreads::cSocketThread::PrepareSet(fd_set * a_Set, cSocket::xSocket continue; } cSocket::xSocket s = m_Slots[i].m_Socket.GetSocket(); - FD_SET(s, a_Set); + FD_SET(s, a_Read); if (s > a_Highest) { a_Highest = s; } + if (!m_Slots[i].m_Outgoing.empty()) + { + // There's outgoing data for the socket, put it in the Write set + FD_SET(s, a_Write); + } } // for i - m_Slots[] } @@ -480,34 +479,37 @@ void cSocketThreads::cSocketThread::ReadFromSockets(fd_set * a_Read) int Received = m_Slots[i].m_Socket.Receive(Buffer, ARRAYCOUNT(Buffer), 0); if (Received <= 0) { - // The socket has been closed by the remote party - switch (m_Slots[i].m_State) + if (cSocket::GetLastError() != cSocket::ErrWouldBlock) { - case sSlot::ssNormal: - { - // Notify the callback that the remote has closed the socket; keep the slot - m_Slots[i].m_Client->SocketClosed(); - m_Slots[i].m_State = sSlot::ssRemoteClosed; - break; - } - case sSlot::ssWritingRestOut: - case sSlot::ssShuttingDown: - case sSlot::ssShuttingDown2: - { - // Force-close the socket and remove the slot: - m_Slots[i].m_Socket.CloseSocket(); - m_Slots[i] = m_Slots[--m_NumSlots]; - break; - } - default: + // The socket has been closed by the remote party + switch (m_Slots[i].m_State) { - LOG("%s: Unexpected socket state: %d (%s)", - __FUNCTION__, m_Slots[i].m_Socket.GetSocket(), m_Slots[i].m_Socket.GetIPString().c_str() - ); - ASSERT(!"Unexpected socket state"); - break; - } - } // switch (m_Slots[i].m_State) + case sSlot::ssNormal: + { + // Notify the callback that the remote has closed the socket; keep the slot + m_Slots[i].m_Client->SocketClosed(); + m_Slots[i].m_State = sSlot::ssRemoteClosed; + break; + } + case sSlot::ssWritingRestOut: + case sSlot::ssShuttingDown: + case sSlot::ssShuttingDown2: + { + // Force-close the socket and remove the slot: + m_Slots[i].m_Socket.CloseSocket(); + m_Slots[i] = m_Slots[--m_NumSlots]; + break; + } + default: + { + LOG("%s: Unexpected socket state: %d (%s)", + __FUNCTION__, m_Slots[i].m_Socket.GetSocket(), m_Slots[i].m_Socket.GetIPString().c_str() + ); + ASSERT(!"Unexpected socket state"); + break; + } + } // switch (m_Slots[i].m_State) + } } else { @@ -539,7 +541,9 @@ void cSocketThreads::cSocketThread::WriteToSockets(fd_set * a_Write) // Request another chunk of outgoing data: if (m_Slots[i].m_Client != NULL) { - m_Slots[i].m_Client->GetOutgoingData(m_Slots[i].m_Outgoing); + AString Data; + m_Slots[i].m_Client->GetOutgoingData(Data); + m_Slots[i].m_Outgoing.append(Data); } if (m_Slots[i].m_Outgoing.empty()) { @@ -553,8 +557,7 @@ void cSocketThreads::cSocketThread::WriteToSockets(fd_set * a_Write) } } // if (outgoing data is empty) - int Sent = m_Slots[i].m_Socket.Send(m_Slots[i].m_Outgoing.data(), m_Slots[i].m_Outgoing.size()); - if (Sent < 0) + if (!SendDataThroughSocket(m_Slots[i].m_Socket, m_Slots[i].m_Outgoing)) { int Err = cSocket::GetLastError(); LOGWARNING("Error %d while writing to client \"%s\", disconnecting. \"%s\"", Err, m_Slots[i].m_Socket.GetIPString().c_str(), GetOSErrorString(Err).c_str()); @@ -565,7 +568,6 @@ void cSocketThreads::cSocketThread::WriteToSockets(fd_set * a_Write) } return; } - m_Slots[i].m_Outgoing.erase(0, Sent); if (m_Slots[i].m_Outgoing.empty() && (m_Slots[i].m_State == sSlot::ssWritingRestOut)) { @@ -590,8 +592,41 @@ void cSocketThreads::cSocketThread::WriteToSockets(fd_set * a_Write) +bool cSocketThreads::cSocketThread::SendDataThroughSocket(cSocket & a_Socket, AString & a_Data) +{ + // Send data in smaller chunks, so that the OS send buffers aren't overflown easily + while (!a_Data.empty()) + { + size_t NumToSend = std::min(a_Data.size(), (size_t)1024); + int Sent = a_Socket.Send(a_Data.data(), NumToSend); + if (Sent < 0) + { + int Err = cSocket::GetLastError(); + if (Err == cSocket::ErrWouldBlock) + { + // The OS send buffer is full, leave the outgoing data for the next time + return true; + } + // An error has occured + return false; + } + if (Sent == 0) + { + a_Socket.CloseSocket(); + return true; + } + a_Data.erase(0, Sent); + } + return true; +} + + + + + void cSocketThreads::cSocketThread::CleanUpShutSockets(void) { + cCSLock Lock(m_Parent->m_CS); for (int i = m_NumSlots - 1; i >= 0; i--) { switch (m_Slots[i].m_State) @@ -617,3 +652,32 @@ void cSocketThreads::cSocketThread::CleanUpShutSockets(void) +void cSocketThreads::cSocketThread::QueueOutgoingData(void) +{ + cCSLock Lock(m_Parent->m_CS); + for (int i = 0; i < m_NumSlots; i++) + { + if (m_Slots[i].m_Client != NULL) + { + AString Data; + m_Slots[i].m_Client->GetOutgoingData(Data); + m_Slots[i].m_Outgoing.append(Data); + } + if (m_Slots[i].m_Outgoing.empty()) + { + // No outgoing data is ready + if (m_Slots[i].m_State == sSlot::ssWritingRestOut) + { + // The socket doesn't want to be kept alive anymore, and doesn't have any remaining data to send. + // Shut it down and then close it after a timeout, or when the other side agrees + m_Slots[i].m_State = sSlot::ssShuttingDown; + m_Slots[i].m_Socket.ShutdownReadWrite(); + } + continue; + } + } +} + + + + diff --git a/src/OSSupport/SocketThreads.h b/src/OSSupport/SocketThreads.h index 9e1947ab6..fcd2ce11f 100644 --- a/src/OSSupport/SocketThreads.h +++ b/src/OSSupport/SocketThreads.h @@ -66,7 +66,8 @@ public: /** Called when data is received from the remote party */ virtual void DataReceived(const char * a_Data, int a_Size) = 0; - /** Called when data can be sent to remote party; the function is supposed to *append* outgoing data to a_Data */ + /** Called when data can be sent to remote party + The function is supposed to *set* outgoing data to a_Data (overwrite) */ virtual void GetOutgoingData(AString & a_Data) = 0; /** Called when the socket has been closed for any reason */ @@ -156,16 +157,27 @@ private: virtual void Execute(void) override; - /** Puts all sockets into the set, along with m_ControlSocket1. - Only sockets that are able to send and receive data are put in the Set. - Is a_IsForWriting is true, the ssWritingRestOut sockets are added as well. */ - void PrepareSet(fd_set * a_Set, cSocket::xSocket & a_Highest, bool a_IsForWriting); + /** Prepares the Read and Write socket sets for select() + Puts all sockets into the read set, along with m_ControlSocket1. + Only sockets that have outgoing data queued on them are put in the write set.*/ + void PrepareSets(fd_set * a_ReadSet, fd_set * a_WriteSet, cSocket::xSocket & a_Highest); - void ReadFromSockets(fd_set * a_Read); // Reads from sockets indicated in a_Read - void WriteToSockets (fd_set * a_Write); // Writes to sockets indicated in a_Write + /** Reads from sockets indicated in a_Read */ + void ReadFromSockets(fd_set * a_Read); + /** Writes to sockets indicated in a_Write */ + void WriteToSockets (fd_set * a_Write); + + /** Sends data through the specified socket, trying to fill the OS send buffer in chunks. + Returns true if there was no error while sending, false if an error has occured. + Modifies a_Data to contain only the unsent data. */ + bool SendDataThroughSocket(cSocket & a_Socket, AString & a_Data); + /** Removes those slots in ssShuttingDown2 state, sets those with ssShuttingDown state to ssShuttingDown2 */ void CleanUpShutSockets(void); + + /** Calls each client's callback to retrieve outgoing data for that client. */ + void QueueOutgoingData(void); } ; typedef std::list<cSocketThread *> cSocketThreadList; diff --git a/src/OSSupport/Timer.cpp b/src/OSSupport/Timer.cpp index ed16f9e3a..fd838dd0d 100644 --- a/src/OSSupport/Timer.cpp +++ b/src/OSSupport/Timer.cpp @@ -28,7 +28,7 @@ long long cTimer::GetNowTime(void) #else struct timeval now; gettimeofday(&now, NULL); - return (long long)(now.tv_sec * 1000 + now.tv_usec / 1000); + return (long long)now.tv_sec * 1000 + (long long)now.tv_usec / 1000; #endif } diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 9bb2cfbf0..0d349de03 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -54,7 +54,7 @@ Implements the 1.7.x protocol classes: // fwd: main.cpp: -extern bool g_ShouldLogComm; +extern bool g_ShouldLogCommIn, g_ShouldLogCommOut; @@ -74,7 +74,7 @@ cProtocol172::cProtocol172(cClientHandle * a_Client, const AString & a_ServerAdd m_IsEncrypted(false) { // Create the comm log file, if so requested: - if (g_ShouldLogComm) + if (g_ShouldLogCommIn || g_ShouldLogCommOut) { cFile::CreateFolder("CommLogs"); AString FileName = Printf("CommLogs/%x__%s.log", (unsigned)time(NULL), a_Client->GetIPString().c_str()); @@ -1083,7 +1083,7 @@ void cProtocol172::SendWindowProperty(const cWindow & a_Window, short a_Property void cProtocol172::AddReceivedData(const char * a_Data, int a_Size) { // Write the incoming data into the comm log file: - if (g_ShouldLogComm) + if (g_ShouldLogCommIn) { if (m_ReceivedData.GetReadableSpace() > 0) { @@ -1092,9 +1092,10 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size) m_ReceivedData.ReadAll(AllData); m_ReceivedData.ResetRead(); m_ReceivedData.SkipRead(m_ReceivedData.GetReadableSpace() - OldReadableSpace); + ASSERT(m_ReceivedData.GetReadableSpace() == OldReadableSpace); AString Hex; CreateHexDump(Hex, AllData.data(), AllData.size(), 16); - m_CommLogFile.Printf("Incoming data, %d (0x%x) bytes unparsed already present in buffer:\n%s\n", + m_CommLogFile.Printf("Incoming data, %d (0x%x) unparsed bytes already present in buffer:\n%s\n", AllData.size(), AllData.size(), Hex.c_str() ); } @@ -1103,6 +1104,7 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size) m_CommLogFile.Printf("Incoming data: %d (0x%x) bytes: \n%s\n", a_Size, a_Size, Hex.c_str() ); + m_CommLogFile.Flush(); } if (!m_ReceivedData.Write(a_Data, a_Size)) @@ -1119,12 +1121,14 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size) if (!m_ReceivedData.ReadVarInt(PacketLen)) { // Not enough data - return; + m_ReceivedData.ResetRead(); + break; } if (!m_ReceivedData.CanReadBytes(PacketLen)) { // The full packet hasn't been received yet - return; + m_ReceivedData.ResetRead(); + break; } cByteBuffer bb(PacketLen + 1); VERIFY(m_ReceivedData.ReadToByteBuffer(bb, (int)PacketLen)); @@ -1137,11 +1141,11 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size) if (!bb.ReadVarInt(PacketType)) { // Not enough data - return; + break; } // Log the packet info into the comm log file: - if (g_ShouldLogComm) + if (g_ShouldLogCommIn) { AString PacketData; bb.ReadAll(PacketData); @@ -1173,7 +1177,7 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size) #endif // _DEBUG // Put a message in the comm log: - if (g_ShouldLogComm) + if (g_ShouldLogCommIn) { m_CommLogFile.Printf("^^^^^^ Unhandled packet ^^^^^^\n\n\n"); } @@ -1189,7 +1193,7 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size) ); // Put a message in the comm log: - if (g_ShouldLogComm) + if (g_ShouldLogCommIn) { m_CommLogFile.Printf("^^^^^^ Wrong number of bytes read for this packet (exp %d left, got %d left) ^^^^^^\n\n\n", 1, bb.GetReadableSpace() @@ -1200,7 +1204,24 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size) ASSERT(!"Read wrong number of bytes!"); m_Client->PacketError(PacketType); } - } // while (true) + } // for(ever) + + // Log any leftover bytes into the logfile: + if (g_ShouldLogCommIn && (m_ReceivedData.GetReadableSpace() > 0)) + { + AString AllData; + int OldReadableSpace = m_ReceivedData.GetReadableSpace(); + m_ReceivedData.ReadAll(AllData); + m_ReceivedData.ResetRead(); + m_ReceivedData.SkipRead(m_ReceivedData.GetReadableSpace() - OldReadableSpace); + ASSERT(m_ReceivedData.GetReadableSpace() == OldReadableSpace); + AString Hex; + CreateHexDump(Hex, AllData.data(), AllData.size(), 16); + m_CommLogFile.Printf("There are %d (0x%x) bytes of non-parse-able data left in the buffer:\n%s", + m_ReceivedData.GetReadableSpace(), m_ReceivedData.GetReadableSpace(), Hex.c_str() + ); + m_CommLogFile.Flush(); + } } @@ -1881,7 +1902,7 @@ cProtocol172::cPacketizer::~cPacketizer() m_Out.CommitRead(); // Log the comm into logfile: - if (g_ShouldLogComm) + if (g_ShouldLogCommOut) { AString Hex; ASSERT(DataToSend.size() > 0); diff --git a/src/Root.cpp b/src/Root.cpp index fa1fdb37a..883bfe76e 100644 --- a/src/Root.cpp +++ b/src/Root.cpp @@ -200,7 +200,7 @@ void cRoot::Start(void) long long finishmseconds = Time.GetNowTime(); finishmseconds -= mseconds; - LOG("Startup complete, took %i ms!", finishmseconds); + LOG("Startup complete, took %lld ms!", finishmseconds); #ifdef _WIN32 EnableMenuItem(hmenu, SC_CLOSE, MF_ENABLED); // Re-enable close button #endif diff --git a/src/StringUtils.cpp b/src/StringUtils.cpp index 0dbd41c12..3fe75d611 100644 --- a/src/StringUtils.cpp +++ b/src/StringUtils.cpp @@ -833,7 +833,8 @@ AString Base64Encode(const AString & a_Input) short GetBEShort(const char * a_Mem) { - return (((short)a_Mem[0]) << 8) | a_Mem[1]; + const Byte * Bytes = (const Byte *)a_Mem; + return (Bytes[0] << 8) | Bytes[1]; } @@ -842,7 +843,8 @@ short GetBEShort(const char * a_Mem) int GetBEInt(const char * a_Mem) { - return (((int)a_Mem[0]) << 24) | (((int)a_Mem[1]) << 16) | (((int)a_Mem[2]) << 8) | a_Mem[3]; + const Byte * Bytes = (const Byte *)a_Mem; + return (Bytes[0] << 24) | (Bytes[1] << 16) | (Bytes[2] << 8) | Bytes[3]; } diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index e2a882f65..a0f9136d8 100644 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -611,12 +611,18 @@ void cWSSAnvil::LoadBlockEntitiesFromNBT(cBlockEntityList & a_BlockEntities, con bool cWSSAnvil::LoadItemFromNBT(cItem & a_Item, const cParsedNBT & a_NBT, int a_TagIdx) { - int ID = a_NBT.FindChildByName(a_TagIdx, "id"); - if ((ID < 0) || (a_NBT.GetType(ID) != TAG_Short)) + int Type = a_NBT.FindChildByName(a_TagIdx, "id"); + if ((Type < 0) || (a_NBT.GetType(Type) != TAG_Short)) { return false; } - a_Item.m_ItemType = (ENUM_ITEM_ID)(a_NBT.GetShort(ID)); + a_Item.m_ItemType = a_NBT.GetShort(Type); + if (a_Item.m_ItemType < 0) + { + LOGD("Encountered an item with negative type (%d). Replacing with an empty item.", a_NBT.GetShort(Type)); + a_Item.Empty(); + return true; + } int Damage = a_NBT.FindChildByName(a_TagIdx, "Damage"); if ((Damage < 0) || (a_NBT.GetType(Damage) != TAG_Short)) diff --git a/src/main.cpp b/src/main.cpp index 06b344c25..c8cd2d4fe 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -19,8 +19,11 @@ bool g_SERVER_TERMINATED = false; // Set to true when the server terminates, so -/** If set to true, the protocols will log each player's communication to a separate logfile */ -bool g_ShouldLogComm; +/** If set to true, the protocols will log each player's incoming (C->S) communication to a per-connection logfile */ +bool g_ShouldLogCommIn; + +/** If set to true, the protocols will log each player's outgoing (S->C) communication to a per-connection logfile */ +bool g_ShouldLogCommOut; @@ -66,11 +69,13 @@ void NonCtrlHandler(int a_Signal) std::signal(a_Signal, SIG_DFL); LOGERROR(" D: | MCServer has encountered an error and needs to close"); LOGERROR("Details | SIGABRT: Server self-terminated due to an internal fault"); + exit(EXIT_FAILURE); break; } + case SIGINT: case SIGTERM: { - std::signal(SIGTERM, SIG_IGN); // Server is shutting down, wait for it... + std::signal(a_Signal, SIG_IGN); // Server is shutting down, wait for it... break; } default: break; @@ -224,6 +229,10 @@ int main( int argc, char **argv ) std::signal(SIGSEGV, NonCtrlHandler); std::signal(SIGTERM, NonCtrlHandler); std::signal(SIGINT, NonCtrlHandler); + std::signal(SIGABRT, NonCtrlHandler); + #ifdef SIGABRT_COMPAT + std::signal(SIGABRT_COMPAT, NonCtrlHandler); + #endif // SIGABRT_COMPAT #endif // DEBUG: test the dumpfile creation: @@ -237,7 +246,24 @@ int main( int argc, char **argv ) (NoCaseCompare(argv[i], "/logcomm") == 0) ) { - g_ShouldLogComm = true; + g_ShouldLogCommIn = true; + g_ShouldLogCommOut = true; + } + if ( + (NoCaseCompare(argv[i], "/commlogin") == 0) || + (NoCaseCompare(argv[i], "/comminlog") == 0) || + (NoCaseCompare(argv[i], "/logcommin") == 0) + ) + { + g_ShouldLogCommIn = true; + } + if ( + (NoCaseCompare(argv[i], "/commlogout") == 0) || + (NoCaseCompare(argv[i], "/commoutlog") == 0) || + (NoCaseCompare(argv[i], "/logcommout") == 0) + ) + { + g_ShouldLogCommOut = true; } } |