/// <summary> /// Append a CRC checksum and encrypt data in place using XTEA /// </summary> internal void EncryptSymmetric(NetBuffer buffer) { //string plain = Convert.ToBase64String(buffer.Data, 0, buffer.LengthBytes); int bufferLen = buffer.LengthBytes; // calculate number of pad bits int dataBits = buffer.LengthBits; int bitsNeeded = dataBits + 24; // 24 extra for crc and num-pad-bits int totalBits = bitsNeeded + (64 - (bitsNeeded % 64)); int padBits = totalBits - bitsNeeded; // write to ensure zeroes in buffer (crc and num-pad-bits space) buffer.Write((uint)0, 24); if (padBits > 0) { buffer.Write((ulong)0, padBits); } int writePadBitsPosition = buffer.LengthBits - 8; // write crc ushort crc = Checksum.Adler16(buffer.Data, 0, buffer.LengthBytes); buffer.ResetWritePointer(dataBits); buffer.Write(crc); // write num-pad-bits in LAST byte buffer.ResetWritePointer(writePadBitsPosition); buffer.Write((byte)padBits); // encrypt in place int ptr = 0; bufferLen = buffer.LengthBytes; while (ptr < bufferLen) { m_xtea.EncryptBlock(buffer.Data, ptr, buffer.Data, ptr); ptr += 8; } return; }
// unsequenced packets only, returns number of bytes sent internal int SendSingleMessageAtOnce(NetMessage msg, NetConnection connection, IPEndPoint endpoint) { m_sendBuffer.ResetWritePointer(); msg.Encode(connection, m_sendBuffer); if (connection != null) { return(ExecuteSend(m_sendBuffer, connection, connection.RemoteEndpoint)); } else { return(ExecuteSend(m_sendBuffer, null, endpoint)); } }
/// <summary> /// Decrypt using XTEA algo and verify CRC /// </summary> /// <returns>true for success, false for failure</returns> internal bool DecryptSymmetric(NetBuffer buffer) { int bufLen = buffer.LengthBytes; if (bufLen % 8 != 0) { if (NetBase.CurrentContext != null && NetBase.CurrentContext.Log != null) { NetBase.CurrentContext.Log.Info("Bad buffer size in DecryptSymmetricInPlace()"); } return(false); } //NetBase.CurrentContext.Log.Debug.Debug("Decrypting using key: " + Convert.ToBase64String(m_xtea.Key)); // decrypt for (int i = 0; i < bufLen; i += 8) { m_xtea.DecryptBlock(buffer.Data, i, buffer.Data, i); } int numPadBits = buffer.Data[bufLen - 1]; buffer.Data[bufLen - 1] = 0; // zap for correct crc calculation int dataBits = (bufLen * 8) - (24 + numPadBits); // include pad and crc buffer.ResetReadPointer(dataBits); ushort statedCrc = buffer.ReadUInt16(); // zap crc to be able to compare buffer.ResetWritePointer(dataBits); buffer.Write((ushort)0); ushort dataCrc = Checksum.Adler16(buffer.Data, 0, bufLen); //NetBase.CurrentContext.Log.Debug("Plain (len " + bufLen + "): " + Convert.ToBase64String(buffer.Data, 0, bufLen) + " Stated CRC: " + statedCrc + " Calc: " + realCrc); if (statedCrc != dataCrc) { if (NetBase.CurrentContext != null && NetBase.CurrentContext.Log != null) { NetBase.CurrentContext.Log.Warning("CRC failure; expected " + dataCrc + " found " + statedCrc + " dropping packet!"); } return(false); } // clean up buffer.LengthBits = dataBits; buffer.ResetReadPointer(); return(true); }
internal void SendUnsentMessages(bool forceAcks, double frameLength) { if (m_unsentMessages.Count < 1 && !forceAcks) { if (m_status == NetConnectionStatus.Disconnecting) { SetStatus(NetConnectionStatus.Disconnected, m_pendingDisconnectedReason); } return; // nothing to send } //if (m_unsentMessages.Count < 1 && forceAcks) // m_parent.Log.Debug("FORCING EXPLICIT ACK"); float sendBytesAllowed = (float)frameLength * (float)Configuration.ThrottleBytesPerSecond; if (m_throttleDebt > sendBytesAllowed) { // NetBase.CurrentContext.Log.Debug("Working off debt: " + m_throttleDebt + " bytes by " + sendBytesAllowed"); m_throttleDebt -= sendBytesAllowed; return; } else if (m_throttleDebt > 0) { sendBytesAllowed -= m_throttleDebt; m_throttleDebt = 0; } NetBuffer sendBuffer = m_parent.m_sendBuffer; sendBuffer.ResetWritePointer(); int mtu = m_parent.Configuration.MaximumTransmissionUnit; float now = (float)NetTime.Now; int pktMsgAdded = 0; int ackMsgAdded = 0; int usrMsgAdded = 0; NetMessage msg; // TODO: make ack bitfield if possible while (m_unsentAcknowledges.Count > 0 && sendBytesAllowed > 0) { msg = m_unsentAcknowledges.Dequeue(); m_reusedAckMessage.SequenceChannel = msg.SequenceChannel; m_reusedAckMessage.SequenceNumber = msg.SequenceNumber; if (sendBuffer.LengthBytes + 3 > mtu) { // send buffer m_parent.ExecuteSend(sendBuffer, this, m_remoteEndpoint); sendBytesAllowed -= sendBuffer.LengthBytes; Statistics.PacketsSent++; Statistics.MessagesSent += pktMsgAdded; Statistics.AckMessagesSent += ackMsgAdded; Statistics.BytesSent += sendBuffer.LengthBytes; sendBuffer.ResetWritePointer(); pktMsgAdded = 0; ackMsgAdded = 0; } //m_parent.Log.Debug("Sending ack " + msg.SequenceChannel + "|" + msg.SequenceNumber); m_reusedAckMessage.Encode(this, sendBuffer); pktMsgAdded++; ackMsgAdded++; } // no unsent acks left! m_forceExplicitAckTime = 0.0; while (m_unsentMessages.Count > 0 && sendBytesAllowed > 0) { msg = m_unsentMessages.Dequeue(); // make pessimistic estimate of message length int estMsgLen = msg.EstimateEncodedLength(); if (sendBuffer.LengthBytes + estMsgLen > mtu) { if (pktMsgAdded < 1) { throw new NetException("Message too large to send: " + estMsgLen + " bytes: " + msg); } // send buffer m_parent.ExecuteSend(sendBuffer, this, m_remoteEndpoint); sendBytesAllowed -= sendBuffer.LengthBytes; Statistics.PacketsSent++; Statistics.MessagesSent += pktMsgAdded; Statistics.UserMessagesSent += usrMsgAdded; Statistics.AckMessagesSent += ackMsgAdded; Statistics.BytesSent += sendBuffer.LengthBytes; sendBuffer.ResetWritePointer(); pktMsgAdded = 0; ackMsgAdded = 0; } msg.Encode(this, sendBuffer); if (msg.m_type == NetMessageType.User || msg.m_type == NetMessageType.UserFragmented) { usrMsgAdded++; } pktMsgAdded++; // store until acknowledged if (msg.SequenceChannel >= NetChannel.ReliableUnordered) { float nextResend = now + (msg.m_numResends < 1 ? Configuration.ResendFirstUnacknowledgedDelay : Configuration.ResendSubsequentUnacknowledgedDelay); msg.m_nextResendTime = nextResend; //m_parent.Log.Debug("Storing " + msg.SequenceChannel + "|" + msg.SequenceNumber + " @ " + now + " first resend: " + nextResend); int seqChan = (int)msg.SequenceChannel; if (m_savedReliableMessages[seqChan] == null) { m_savedReliableMessages[seqChan] = new List <NetMessage>(); } m_savedReliableMessages[seqChan].Add(msg); } } if (pktMsgAdded > 0) { m_parent.ExecuteSend(sendBuffer, this, m_remoteEndpoint); sendBytesAllowed -= sendBuffer.LengthBytes; Statistics.PacketsSent++; Statistics.MessagesSent += pktMsgAdded; Statistics.UserMessagesSent += usrMsgAdded; Statistics.AckMessagesSent += ackMsgAdded; Statistics.BytesSent += sendBuffer.LengthBytes; } Debug.Assert(m_throttleDebt == 0); if (sendBytesAllowed < 0) { m_throttleDebt = -sendBytesAllowed; } }
/// <summary> /// Decrypt using XTEA algo and verify CRC /// </summary> /// <returns>true for success, false for failure</returns> internal bool DecryptSymmetric(NetBuffer buffer) { int bufLen = buffer.LengthBytes; if (bufLen % 8 != 0) { if (NetBase.CurrentContext != null && NetBase.CurrentContext.Log != null) NetBase.CurrentContext.Log.Info("Bad buffer size in DecryptSymmetricInPlace()"); return false; } //NetBase.CurrentContext.Log.Debug.Debug("Decrypting using key: " + Convert.ToBase64String(m_xtea.Key)); // decrypt for (int i = 0; i < bufLen; i += 8) m_xtea.DecryptBlock(buffer.Data, i, buffer.Data, i); int numPadBits = buffer.Data[bufLen - 1]; buffer.Data[bufLen - 1] = 0; // zap for correct crc calculation int dataBits = (bufLen * 8) - (24 + numPadBits); // include pad and crc buffer.ResetReadPointer(dataBits); ushort statedCrc = buffer.ReadUInt16(); // zap crc to be able to compare buffer.ResetWritePointer(dataBits); buffer.Write((ushort)0); ushort dataCrc = Checksum.Adler16(buffer.Data, 0, bufLen); //NetBase.CurrentContext.Log.Debug("Plain (len " + bufLen + "): " + Convert.ToBase64String(buffer.Data, 0, bufLen) + " Stated CRC: " + statedCrc + " Calc: " + realCrc); if (statedCrc != dataCrc) { if (NetBase.CurrentContext != null && NetBase.CurrentContext.Log != null) NetBase.CurrentContext.Log.Warning("CRC failure; expected " + dataCrc + " found " + statedCrc + " dropping packet!"); return false; } // clean up buffer.LengthBits = dataBits; buffer.ResetReadPointer(); return true; }
/// <summary> /// Append a CRC checksum and encrypt data in place using XTEA /// </summary> internal void EncryptSymmetric(NetBuffer buffer) { //string plain = Convert.ToBase64String(buffer.Data, 0, buffer.LengthBytes); int bufferLen = buffer.LengthBytes; // calculate number of pad bits int dataBits = buffer.LengthBits; int bitsNeeded = dataBits + 24; // 24 extra for crc and num-pad-bits int totalBits = bitsNeeded + (64 - (bitsNeeded % 64)); int padBits = totalBits - bitsNeeded; // write to ensure zeroes in buffer (crc and num-pad-bits space) buffer.Write((uint)0, 24); if (padBits > 0) buffer.Write((ulong)0, padBits); int writePadBitsPosition = buffer.LengthBits - 8; // write crc ushort crc = Checksum.Adler16(buffer.Data, 0, buffer.LengthBytes); buffer.ResetWritePointer(dataBits); buffer.Write(crc); // write num-pad-bits in LAST byte buffer.ResetWritePointer(writePadBitsPosition); buffer.Write((byte)padBits); // encrypt in place int ptr = 0; bufferLen = buffer.LengthBytes; while (ptr < bufferLen) { m_xtea.EncryptBlock(buffer.Data, ptr, buffer.Data, ptr); ptr += 8; } return; }