private void ReceivePackets(double now) { int networkResets = 0; int connectionResets = 0; int availableData = 0; try { for (;;) { try { if (m_socket == null) { return; } availableData = m_socket.availableData; if (availableData <= 0) { return; } m_receiveBuffer.Reset(); double localTimeRecv; int bytesReceived = m_socket.ReceivePacket(m_receiveBuffer.Data, 0, m_receiveBuffer.Data.Length, out m_senderRemote, out localTimeRecv); if (bytesReceived <= 0) { continue; } m_statistics.CountPacketReceived(bytesReceived); m_receiveBuffer.LengthBits = bytesReceived * 8; var ipsender = (NetworkEndPoint)m_senderRemote; if (localTimeRecv == 0) { localTimeRecv = NetTime.Now; } // lookup the endpoint (if we have a connection) var sender = GetConnection(ipsender); if (sender != null) { sender.m_statistics.CountPacketReceived(bytesReceived, localTimeRecv); sender.m_lastPongReceived = localTimeRecv; // TODO: fulhack! } // try parsing the packet try { // create messages from packet while (m_receiveBuffer.PositionBits < m_receiveBuffer.LengthBits) { int beginPosition = m_receiveBuffer.PositionBits; // read message header var msg = CreateIncomingMessage(); msg.m_sender = sender; if (!msg.ReadFrom(m_receiveBuffer, ipsender)) { break; } // statistics if (sender != null) { sender.m_statistics.CountMessageReceived(msg.m_type, msg.m_sequenceChannel, (m_receiveBuffer.PositionBits - beginPosition) / 8, now); } // handle message HandleReceivedMessage(msg, ipsender, localTimeRecv); } } catch (Exception e) // silent exception handlers make debugging impossible, comment out when you wonder "WTF is happening???" { // TODO: fix so logging doesn't allocate an argument array (for using params object[]). // Enabling us to hopefully do to log calls without overhead, if the log level isn't on. #if DEBUG // NOTE: in production it might not be desirable to log bad packets, because of targeted DoS attacks. Log.Error(LogFlags.Socket, "Failed parsing an incoming packet from ", ipsender, ": ", e); #endif } } catch (SocketException sex) { if (sex.ErrorCode == 10040 || sex.SocketErrorCode == SocketError.MessageSize) { int bufferSize = m_receiveBuffer.Data.Length; Log.Error(LogFlags.Socket, "Failed to read available data (", availableData, " bytes) because it's larger than the receive buffer (", bufferSize, " bytes). This might indicate that the socket receive buffer size is not correctly configured: ", sex); } if (sex.ErrorCode == 10052 || sex.SocketErrorCode == SocketError.NetworkReset) { networkResets++; if (networkResets > 2000) { break; } } else if (sex.ErrorCode == 10054 || sex.SocketErrorCode == SocketError.ConnectionReset) { connectionResets++; if (connectionResets > 2000) { break; } } else { throw; } } } } catch (SocketException sex) { if (sex.ErrorCode == 10035 || sex.SocketErrorCode == SocketError.WouldBlock) { // NOTE: add independent ability to log warnings instead of this hack. Log.Warning(LogFlags.Socket, "Receive Buffer is empty, ignore error: ", sex.Message); return; } throw new NetException(NetTime.Now + " (" + DateTime.Now + "): Could not receive packet", sex); } catch (Exception ex) { throw new NetException(NetTime.Now + " (" + DateTime.Now + "): Could not receive packet", ex); } finally { if (networkResets > 0) { Log.Debug(LogFlags.Socket, NetTime.Now, " (", DateTime.Now, "): Ignored number of socket network reset errors: ", networkResets); } if (connectionResets > 0) { Log.Debug(LogFlags.Socket, NetTime.Now, " (", DateTime.Now, "): Ignored number of socket connection reset errors: ", connectionResets); } } }