private void ProcessBinaryMeasurements(IEnumerable <IBinaryMeasurement> measurements, long frameLevelTimestamp, bool useCompactMeasurementFormat, bool usePayloadCompression)
        {
            // Create working buffer
            using (BlockAllocatedMemoryStream workingBuffer = new BlockAllocatedMemoryStream())
            {
                // Serialize data packet flags into response
                DataPacketFlags flags = DataPacketFlags.Synchronized;

                if (useCompactMeasurementFormat)
                {
                    flags |= DataPacketFlags.Compact;
                }

                workingBuffer.WriteByte((byte)flags);

                // Serialize frame timestamp into data packet - this only occurs in synchronized data packets,
                // unsynchronized subscriptions always include timestamps in the serialized measurements
                workingBuffer.Write(BigEndian.GetBytes(frameLevelTimestamp), 0, 8);

                // Serialize total number of measurement values to follow
                workingBuffer.Write(BigEndian.GetBytes(measurements.Count()), 0, 4);

                if (usePayloadCompression && m_compressionModes.HasFlag(CompressionModes.TSSC))
                {
                    throw new InvalidOperationException("TSSC must be processed at the frame level. Please check call stack - this is considered an error.");
                }

                // Attempt compression when requested - encoding of compressed buffer only happens if size would be smaller than normal serialization
                if (!usePayloadCompression || !measurements.Cast <CompactMeasurement>().CompressPayload(workingBuffer, m_compressionStrength, false, ref flags))
                {
                    // Serialize measurements to data buffer
                    foreach (IBinaryMeasurement measurement in measurements)
                    {
                        measurement.CopyBinaryImageToStream(workingBuffer);
                    }
                }

                // Update data packet flags if it has updated compression flags
                if ((flags & DataPacketFlags.Compressed) > 0)
                {
                    workingBuffer.Seek(0, SeekOrigin.Begin);
                    workingBuffer.WriteByte((byte)flags);
                }

                // Publish data packet to client
                if ((object)m_parent != null)
                {
                    m_parent.SendClientResponse(m_clientID, ServerResponse.DataPacket, ServerCommand.Subscribe, workingBuffer.ToArray());
                }
            }
        }
        private void ProcessBinaryMeasurements(IEnumerable <IBinaryMeasurement> measurements, bool useCompactMeasurementFormat, bool usePayloadCompression)
        {
            // Create working buffer
            using (BlockAllocatedMemoryStream workingBuffer = new BlockAllocatedMemoryStream())
            {
                // Serialize data packet flags into response
                DataPacketFlags flags = DataPacketFlags.NoFlags; // No flags means bit is cleared, i.e., unsynchronized

                if (useCompactMeasurementFormat)
                {
                    flags |= DataPacketFlags.Compact;
                }

                workingBuffer.WriteByte((byte)flags);

                // No frame level timestamp is serialized into the data packet since all data is unsynchronized and essentially
                // published upon receipt, however timestamps are optionally included in the serialized measurements.

                // Serialize total number of measurement values to follow
                workingBuffer.Write(BigEndian.GetBytes(measurements.Count()), 0, 4);

                // Attempt compression when requested - encoding of compressed buffer only happens if size would be smaller than normal serialization
                if (!usePayloadCompression || !measurements.Cast <CompactMeasurement>().CompressPayload(workingBuffer, m_compressionStrength, m_includeTime, ref flags))
                {
                    // Serialize measurements to data buffer
                    foreach (IBinaryMeasurement measurement in measurements)
                    {
                        measurement.CopyBinaryImageToStream(workingBuffer);
                    }
                }

                // Update data packet flags if it has updated compression flags
                if ((flags & DataPacketFlags.Compressed) > 0)
                {
                    workingBuffer.Seek(0, SeekOrigin.Begin);
                    workingBuffer.WriteByte((byte)flags);
                }

                // Publish data packet to client
                if ((object)m_parent != null)
                {
                    m_parent.SendClientResponse(m_clientID, ServerResponse.DataPacket, ServerCommand.Subscribe, workingBuffer.ToArray());
                }

                // Track last publication time
                m_lastPublishTime = DateTime.UtcNow.Ticks;
            }
        }
Esempio n. 3
0
        private void ProcessBinaryMeasurements(IEnumerable <IBinaryMeasurement> measurements, long frameLevelTimestamp, bool useCompactMeasurementFormat, bool usePayloadCompression)
        {
            // Reset working buffer
            m_workingBuffer.SetLength(0);

            // Serialize data packet flags into response
            DataPacketFlags flags = DataPacketFlags.Synchronized;

            if (useCompactMeasurementFormat)
            {
                flags |= DataPacketFlags.Compact;
            }

            m_workingBuffer.WriteByte((byte)flags);

            // Serialize frame timestamp into data packet - this only occurs in synchronized data packets,
            // unsynchronized subscriptions always include timestamps in the serialized measurements
            m_workingBuffer.Write(BigEndian.GetBytes(frameLevelTimestamp), 0, 8);

            // Serialize total number of measurement values to follow
            m_workingBuffer.Write(BigEndian.GetBytes(measurements.Count()), 0, 4);

            // Attempt compression when requested - encoding of compressed buffer only happens if size would be smaller than normal serialization
            if (!usePayloadCompression || !measurements.Cast <CompactMeasurement>().CompressPayload(m_workingBuffer, m_compressionStrength, false, ref flags))
            {
                // Serialize measurements to data buffer
                foreach (IBinaryMeasurement measurement in measurements)
                {
                    measurement.CopyBinaryImageToStream(m_workingBuffer);
                }
            }

            // Update data packet flags if it has updated compression flags
            if ((flags & DataPacketFlags.Compressed) > 0)
            {
                m_workingBuffer.Seek(0, SeekOrigin.Begin);
                m_workingBuffer.WriteByte((byte)flags);
            }

            // Publish data packet to client
            if ((object)m_parent != null)
            {
                m_parent.SendClientResponse(m_workingBuffer, m_clientID, ServerResponse.DataPacket, ServerCommand.Subscribe, m_workingBuffer.ToArray());
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Rotates or initializes the crypto keys for this <see cref="ClientConnection"/>.
        /// </summary>
        public bool RotateCipherKeys()
        {
            // Make sure at least a second has passed before next key rotation
            if ((DateTime.UtcNow.Ticks - m_lastCipherKeyUpdateTime).ToMilliseconds() >= 1000.0D)
            {
                try
                {
                    // Since this function cannot be not called more than once per second there
                    // is no real benefit to maintaining these memory streams at a member level
                    using (BlockAllocatedMemoryStream response = new BlockAllocatedMemoryStream())
                    {
                        byte[] bytes, bufferLen;

                        // Create or update cipher keys and initialization vectors
                        UpdateKeyIVs();

                        // Add current cipher index to response
                        response.WriteByte((byte)m_cipherIndex);

                        // Serialize new keys
                        using (BlockAllocatedMemoryStream buffer = new BlockAllocatedMemoryStream())
                        {
                            // Write even key
                            bufferLen = BigEndian.GetBytes(m_keyIVs[EvenKey][KeyIndex].Length);
                            buffer.Write(bufferLen, 0, bufferLen.Length);
                            buffer.Write(m_keyIVs[EvenKey][KeyIndex], 0, m_keyIVs[EvenKey][KeyIndex].Length);

                            // Write even initialization vector
                            bufferLen = BigEndian.GetBytes(m_keyIVs[EvenKey][IVIndex].Length);
                            buffer.Write(bufferLen, 0, bufferLen.Length);
                            buffer.Write(m_keyIVs[EvenKey][IVIndex], 0, m_keyIVs[EvenKey][IVIndex].Length);

                            // Write odd key
                            bufferLen = BigEndian.GetBytes(m_keyIVs[OddKey][KeyIndex].Length);
                            buffer.Write(bufferLen, 0, bufferLen.Length);
                            buffer.Write(m_keyIVs[OddKey][KeyIndex], 0, m_keyIVs[OddKey][KeyIndex].Length);

                            // Write odd initialization vector
                            bufferLen = BigEndian.GetBytes(m_keyIVs[OddKey][IVIndex].Length);
                            buffer.Write(bufferLen, 0, bufferLen.Length);
                            buffer.Write(m_keyIVs[OddKey][IVIndex], 0, m_keyIVs[OddKey][IVIndex].Length);

                            // Get bytes from serialized buffer
                            bytes = buffer.ToArray();
                        }

                        // Encrypt keys using private keys known only to current client and server
                        if (m_authenticated && !string.IsNullOrWhiteSpace(m_sharedSecret))
                        {
                            bytes = bytes.Encrypt(m_sharedSecret, CipherStrength.Aes256);
                        }

                        // Add serialized key response
                        response.Write(bytes, 0, bytes.Length);

                        // Send cipher key updates
                        m_parent.SendClientResponse(m_clientID, ServerResponse.UpdateCipherKeys, ServerCommand.Subscribe, response.ToArray());
                    }

                    // Send success message
                    m_parent.SendClientResponse(m_clientID, ServerResponse.Succeeded, ServerCommand.RotateCipherKeys, "New cipher keys established.");
                    m_parent.OnStatusMessage(MessageLevel.Info, $"{ConnectionID} cipher keys rotated.");
                    return(true);
                }
                catch (Exception ex)
                {
                    // Send failure message
                    m_parent.SendClientResponse(m_clientID, ServerResponse.Failed, ServerCommand.RotateCipherKeys, "Failed to establish new cipher keys: " + ex.Message);
                    m_parent.OnStatusMessage(MessageLevel.Warning, $"Failed to establish new cipher keys for {ConnectionID}: {ex.Message}");
                    return(false);
                }
            }

            m_parent.SendClientResponse(m_clientID, ServerResponse.Failed, ServerCommand.RotateCipherKeys, "Cipher key rotation skipped, keys were already rotated within last second.");
            m_parent.OnStatusMessage(MessageLevel.Warning, $"Cipher key rotation skipped for {ConnectionID}, keys were already rotated within last second.");
            return(false);
        }