/// <inheritdoc />
        public override void ReverseProcessDataStream(System.IO.Stream inStream, System.IO.Stream outStream, Dictionary <string, string> options, out long writtenBytes)
        {
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }
            else if (!options.ContainsKey(PasswordOption))
            {
                throw new ArgumentException("Options must contain encryption key", "options");
            }

            if (outStream == null)
            {
                throw new ArgumentNullException("outStream");
            }

            Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(options[PasswordOption], SALT);

            using (var transform = encrypter.CreateDecryptor(pdb.GetBytes(32), pdb.GetBytes(16)))
            {
                using (MemoryStream internalStream = new MemoryStream())
                {
                    using (CryptoStream csDecrypt = new CryptoStream(internalStream, transform, CryptoStreamMode.Write))
                    {
                        AsyncStreamCopier.CopyStreamTo(inStream, csDecrypt);
                        inStream.Flush();
                        csDecrypt.FlushFinalBlock();

                        internalStream.Seek(0, 0);
                        AsyncStreamCopier.CopyStreamTo(internalStream, outStream);
                        writtenBytes = outStream.Position;
                    }
                }
            }
        }
示例#2
0
        /// <summary>
        /// Copy contents of source into destination
        /// </summary>
        /// <param name="source"></param>
        /// <param name="destination"></param>
        public static void CopyStreamTo(Stream source, Stream destination)
        {
            var completedEvent = new ManualResetEvent(false);

            // copy as usual but listen for completion
            var copier = new AsyncStreamCopier();

            copier.Completed += (s, e) => completedEvent.Set();
            copier.Start(source, destination);

            completedEvent.WaitOne();
        }
示例#3
0
        /// <summary>
        /// Deserializes data object held as compressed bytes in receivedObjectBytes using compressor if desired type is an array of primitives
        /// </summary>
        /// <param name="inputStream">Byte array containing serialized and compressed object</param>
        /// <param name="dataProcessors">Compression provider to use</param>
        /// <param name="objType">The <see cref="System.Type"/> of the <see cref="object"/> to be returned</param>
        /// <param name="options">Options to be used during deserialization and processing of data</param>
        /// <returns>The deserialized object if it is an array, otherwise null</returns>
        public static unsafe object DeserialiseArrayObject(MemoryStream inputStream, Type objType, List <DataProcessor> dataProcessors, Dictionary <string, string> options)
        {
            if (objType.IsArray)
            {
                var elementType = objType.GetElementType();

                //No need to do anything for a byte array
                if (elementType == typeof(byte) && (dataProcessors == null || dataProcessors.Count == 0))
                {
                    try
                    {
                        return((object)inputStream.GetBuffer());
                    }
                    catch (UnauthorizedAccessException)
                    {
                        return((object)inputStream.ToArray());
                    }
                }

                if (elementType.IsPrimitive)
                {
                    int numElements;

                    if (dataProcessors == null || dataProcessors.Count == 0)
                    {
                        numElements = (int)(inputStream.Length / Marshal.SizeOf(elementType));
                    }
                    else
                    {
                        byte[] temp = new byte[sizeof(int)];
                        inputStream.Seek(inputStream.Length - sizeof(int), SeekOrigin.Begin);
                        inputStream.Read(temp, 0, sizeof(int));
                        numElements = (int)(BitConverter.ToUInt32(temp, 0));
                    }

                    Array    resultArray = Array.CreateInstance(elementType, numElements);
                    GCHandle arrayHandle = GCHandle.Alloc(resultArray, GCHandleType.Pinned);

                    try
                    {
                        IntPtr safePtr      = Marshal.UnsafeAddrOfPinnedArrayElement(resultArray, 0);
                        long   writtenBytes = 0;

                        using (System.IO.UnmanagedMemoryStream finalOutputStream = new System.IO.UnmanagedMemoryStream((byte *)safePtr, resultArray.Length * Marshal.SizeOf(elementType), resultArray.Length * Marshal.SizeOf(elementType), System.IO.FileAccess.ReadWrite))
                        {
                            MemoryStream inputBytesStream = null;
                            try
                            {
                                //We hope that the buffer is publicly accessible as otherwise it defeats the point of having a special serializer for arrays
                                inputBytesStream = new MemoryStream(inputStream.GetBuffer(), 0, (int)(inputStream.Length - ((dataProcessors == null || dataProcessors.Count == 0) ? 0 : sizeof(int))));
                            }
                            catch (UnauthorizedAccessException)
                            {
                                inputBytesStream = new MemoryStream(inputStream.ToArray(), 0, (int)(inputStream.Length - ((dataProcessors == null || dataProcessors.Count == 0) ? 0 : sizeof(int))));
                            }

                            using (inputBytesStream)
                            {
                                if (dataProcessors != null && dataProcessors.Count > 1)
                                {
                                    using (MemoryStream tempStream1 = new MemoryStream())
                                    {
                                        dataProcessors[dataProcessors.Count - 1].ReverseProcessDataStream(inputBytesStream, tempStream1, options, out writtenBytes);

                                        if (dataProcessors.Count > 2)
                                        {
                                            using (MemoryStream tempStream2 = new MemoryStream())
                                            {
                                                for (int i = dataProcessors.Count - 2; i > 0; i -= 2)
                                                {
                                                    tempStream1.Seek(0, 0); tempStream1.SetLength(writtenBytes);
                                                    tempStream2.Seek(0, 0);
                                                    dataProcessors[i].ReverseProcessDataStream(tempStream1, tempStream2, options, out writtenBytes);

                                                    if (i - 1 > 0)
                                                    {
                                                        tempStream1.Seek(0, 0);
                                                        tempStream2.Seek(0, 0); tempStream2.SetLength(writtenBytes);
                                                        dataProcessors[i - 1].ReverseProcessDataStream(tempStream2, tempStream1, options, out writtenBytes);
                                                    }
                                                }

                                                if (dataProcessors.Count % 2 == 0)
                                                {
                                                    tempStream1.Seek(0, 0); tempStream1.SetLength(writtenBytes);
                                                    dataProcessors[0].ReverseProcessDataStream(tempStream1, finalOutputStream, options, out writtenBytes);
                                                }
                                                else
                                                {
                                                    tempStream2.Seek(0, 0); tempStream2.SetLength(writtenBytes);
                                                    dataProcessors[0].ReverseProcessDataStream(tempStream2, finalOutputStream, options, out writtenBytes);
                                                }
                                            }
                                        }
                                        else
                                        {
                                            tempStream1.Seek(0, 0); tempStream1.SetLength(writtenBytes);
                                            dataProcessors[0].ReverseProcessDataStream(tempStream1, finalOutputStream, options, out writtenBytes);
                                        }
                                    }
                                }
                                else
                                {
                                    if (dataProcessors != null && dataProcessors.Count == 1)
                                    {
                                        dataProcessors[0].ReverseProcessDataStream(inputBytesStream, finalOutputStream, options, out writtenBytes);
                                    }
                                    else
                                    {
                                        AsyncStreamCopier.CopyStreamTo(inputBytesStream, finalOutputStream);
                                    }
                                }
                            }
                        }
                    }
                    finally
                    {
                        arrayHandle.Free();
                    }

                    return((object)resultArray);
                }
            }

            return(null);
        }
示例#4
0
        /// <summary>
        /// Serializes objectToSerialize to a byte array using compression provided by compressor if T is an array of primitives.  Otherwise returns default value for T.  Override
        /// to serialize other types
        /// </summary>
        /// <param name="objectToSerialise">Object to serialize</param>
        /// <param name="dataProcessors">The compression provider to use</param>
        /// <param name="options">Options to be used during serialization and processing of data</param>
        /// <returns>The serialized and compressed bytes of objectToSerialize</returns>
        public static unsafe StreamSendWrapper SerialiseArrayObject(object objectToSerialise, List <DataProcessor> dataProcessors, Dictionary <string, string> options)
        {
            Type objType = objectToSerialise.GetType();

            if (objType.IsArray)
            {
                var elementType = objType.GetElementType();

                //No need to do anything for a byte array
                if (elementType == typeof(byte) && (dataProcessors == null || dataProcessors.Count == 0))
                {
                    byte[] bytesToSerialise = objectToSerialise as byte[];
                    //return objectToSerialise as byte[];
                    return(new StreamSendWrapper(new ThreadSafeStream(new MemoryStream(bytesToSerialise, 0, bytesToSerialise.Length, false, true), true)));
                }
                else if (elementType.IsPrimitive)
                {
                    var      asArray     = objectToSerialise as Array;
                    GCHandle arrayHandle = GCHandle.Alloc(asArray, GCHandleType.Pinned);

                    try
                    {
                        IntPtr safePtr      = Marshal.UnsafeAddrOfPinnedArrayElement(asArray, 0);
                        long   writtenBytes = 0;

                        MemoryStream tempStream1 = new System.IO.MemoryStream();

                        using (UnmanagedMemoryStream inputDataStream = new System.IO.UnmanagedMemoryStream((byte *)safePtr, asArray.Length * Marshal.SizeOf(elementType)))
                        {
                            if (dataProcessors == null || dataProcessors.Count == 0)
                            {
                                AsyncStreamCopier.CopyStreamTo(inputDataStream, tempStream1);
                                //return tempStream1.ToArray();
                                return(new StreamSendWrapper(new ThreadSafeStream(tempStream1, true)));
                            }

                            dataProcessors[0].ForwardProcessDataStream(inputDataStream, tempStream1, options, out writtenBytes);
                        }

                        if (dataProcessors.Count > 1)
                        {
                            MemoryStream tempStream2 = new MemoryStream();

                            for (int i = 1; i < dataProcessors.Count; i += 2)
                            {
                                tempStream1.Seek(0, 0); tempStream1.SetLength(writtenBytes);
                                tempStream2.Seek(0, 0);
                                dataProcessors[i].ForwardProcessDataStream(tempStream1, tempStream2, options, out writtenBytes);

                                if (i + 1 < dataProcessors.Count)
                                {
                                    tempStream1.Seek(0, 0);
                                    tempStream2.Seek(0, 0); tempStream2.SetLength(writtenBytes);
                                    dataProcessors[i].ForwardProcessDataStream(tempStream2, tempStream1, options, out writtenBytes);
                                }
                            }

                            if (dataProcessors.Count % 2 == 0)
                            {
                                tempStream2.SetLength(writtenBytes + 4);
                                tempStream2.Seek(writtenBytes, 0);
                                tempStream2.Write(BitConverter.GetBytes(asArray.Length), 0, sizeof(int));
                                //return tempStream2.ToArray();
                                tempStream1.Dispose();
                                return(new StreamSendWrapper(new ThreadSafeStream(tempStream2, true)));
                            }
                            else
                            {
                                tempStream1.SetLength(writtenBytes + 4);
                                tempStream1.Seek(writtenBytes, 0);
                                tempStream1.Write(BitConverter.GetBytes(asArray.Length), 0, sizeof(int));
                                //return tempStream1.ToArray();
                                tempStream2.Dispose();
                                return(new StreamSendWrapper(new ThreadSafeStream(tempStream1, true)));
                            }
                        }
                        else
                        {
                            tempStream1.SetLength(writtenBytes + 4);
                            tempStream1.Seek(writtenBytes, 0);
                            tempStream1.Write(BitConverter.GetBytes(asArray.Length), 0, sizeof(int));
                            //return tempStream1.ToArray();
                            return(new StreamSendWrapper(new ThreadSafeStream(tempStream1, true)));
                        }
                    }
                    finally
                    {
                        arrayHandle.Free();
                    }
                }
            }

            return(null);
        }