private void Constructor(string sendingPacketTypeStr, string requestReturnPacketTypeStr, object packetObject, SendReceiveOptions options) { if (sendingPacketTypeStr == null || sendingPacketTypeStr == "") { throw new ArgumentNullException("sendingPacketTypeStr", "The provided string can not be null or zero length."); } if (options == null) { throw new ArgumentNullException("options", "The provided SendReceiveOptions cannot be null."); } if (packetObject == null) { this.packetData = new StreamSendWrapper(new ThreadSafeStream(new MemoryStream(new byte[0], 0, 0, false, true), true)); } else { if (options.DataSerializer == null) { throw new ArgumentNullException("options", "The provided SendReceiveOptions.DataSerializer cannot be null."); } this.packetData = options.DataSerializer.SerialiseDataObject(packetObject, options.DataProcessors, options.Options); } //We only calculate the checkSum if we are going to use it string hashStr = null; if (NetworkComms.EnablePacketCheckSumValidation) { hashStr = NetworkComms.MD5Bytes(packetData.ThreadSafeStream.ToArray(packetData.Start, packetData.Length)); } this.packetHeader = new PacketHeader(sendingPacketTypeStr, packetData.Length, requestReturnPacketTypeStr, options.Options.ContainsKey("ReceiveConfirmationRequired"), hashStr, options.Options.ContainsKey("IncludePacketConstructionTime")); //Add an identifier specifying the serializers and processors we have used this.packetHeader.SetOption(PacketHeaderLongItems.SerializerProcessors, DPSManager.CreateSerializerDataProcessorIdentifier(options.DataSerializer, options.DataProcessors)); if (NetworkComms.LoggingEnabled) { NetworkComms.Logger.Trace(" ... creating comms packet. PacketObject data size is " + packetData.Length.ToString() + " bytes"); } }
private void Constructor <payloadObjectType>(string sendingPacketTypeStr, string requestReturnPacketTypeStr, payloadObjectType payloadObject, SendReceiveOptions options, bool isNested) { if (sendingPacketTypeStr == null || sendingPacketTypeStr == "") { throw new ArgumentNullException("sendingPacketTypeStr", "The provided string can not be null or zero length."); } if (options == null) { throw new ArgumentNullException("options", "The provided SendReceiveOptions cannot be null."); } if (options.DataSerializer == null) { throw new ArgumentNullException("options", "The provided SendReceiveOptions.DataSerializer cannot be null. Consider using NullSerializer instead."); } //Check for security critical data processors //There may be performance issues here bool containsSecurityCritialDataProcessors = false; if (!options.Options.ContainsKey("UseNestedPacketType") && //We only need to perform this check if we are not already using a nested packet !isNested) //We do not perform this check within a nested packet { foreach (DataProcessor processor in options.DataProcessors) { if (processor.IsSecurityCritical) { containsSecurityCritialDataProcessors = true; break; } } } //By default the object to serialise will be the payloadObject object objectToSerialise = payloadObject; bool objectToSerialiseIsNull = false; //We only replace the null with an empty stream if this is either in the nested packet //or we will not be nesting if (objectToSerialise == null && ((!options.Options.ContainsKey("UseNestedPacketType") && !containsSecurityCritialDataProcessors) || isNested)) { #if NETFX_CORE var emptyStream = new MemoryStream(new byte[0], 0, 0, false); #else var emptyStream = new MemoryStream(new byte[0], 0, 0, false, true); #endif //If the sending object is null we set objectToSerialiseIsNull and create a zero length StreamSendWrapper //The zero length StreamSendWrapper can then be passed to any data serializers objectToSerialiseIsNull = true; objectToSerialise = new StreamTools.StreamSendWrapper(new StreamTools.ThreadSafeStream(emptyStream, true)); } //If we need to nest this packet if ((containsSecurityCritialDataProcessors || options.Options.ContainsKey("UseNestedPacketType")) && !isNested) { //We set the objectToSerialise to a nested packet objectToSerialise = new Packet(sendingPacketTypeStr, requestReturnPacketTypeStr, payloadObject, options, true); } else if (isNested) { //Serialise the payload object into byte[] //We do not use any data processors at this stage as the object will be processed again one level higher. #if NETFX_CORE _payloadObjectBytes = options.DataSerializer.SerialiseDataObject(payloadObject).ThreadSafeStream.ToArray(); _payloadSize = _payloadObjectBytes.Length; #else NetworkCommsDotNet.Tools.StreamTools.ThreadSafeStream tempStream = options.DataSerializer.SerialiseDataObject(objectToSerialise).ThreadSafeStream; _payloadObjectBytes = tempStream.GetBuffer(); _payloadSize = (int)tempStream.Length; #endif //Set the packet header //THe nulls represent internal SendReceiveOptions and no checksum this._packetHeader = new PacketHeader(sendingPacketTypeStr, _payloadSize, null, requestReturnPacketTypeStr, null); //Set the deserialiser information in the nested packet header, excluding data processors this._packetHeader.SetOption(PacketHeaderLongItems.SerializerProcessors, DPSManager.CreateSerializerDataProcessorIdentifier(options.DataSerializer, null)); } //If we are at the top level packet we can finish off the serialisation if (!isNested) { //Set the payload stream data. if (objectToSerialiseIsNull && options.DataProcessors.Count == 0) { //Only if there are no data processors can we use a zero length array for nulls //This ensures that should there be any required padding we can include it this.payloadStream = (StreamTools.StreamSendWrapper)objectToSerialise; } else { if (objectToSerialise is Packet) { //We have to use the internal explicit serializer for nested packets (the nested data is already byte[]) this.payloadStream = NetworkComms.InternalFixedSendReceiveOptions.DataSerializer.SerialiseDataObject(objectToSerialise, options.DataProcessors, options.Options); } else { this.payloadStream = options.DataSerializer.SerialiseDataObject(objectToSerialise, options.DataProcessors, options.Options); } } //We only calculate the checkSum if we are going to use it string hashStr = null; if (NetworkComms.EnablePacketCheckSumValidation) { hashStr = StreamTools.MD5(payloadStream.ThreadSafeStream.ToArray(payloadStream.Start, payloadStream.Length)); } //Choose the sending and receiving packet type depending on if it is being used with a nested packet string _sendingPacketTypeStr; string _requestReturnPacketTypeStr = null; if (containsSecurityCritialDataProcessors || options.Options.ContainsKey("UseNestedPacketType")) { _sendingPacketTypeStr = Enum.GetName(typeof(ReservedPacketType), ReservedPacketType.NestedPacket); } else { _sendingPacketTypeStr = sendingPacketTypeStr; _requestReturnPacketTypeStr = requestReturnPacketTypeStr; } this._packetHeader = new PacketHeader(_sendingPacketTypeStr, payloadStream.Length, options, _requestReturnPacketTypeStr, hashStr); //Add an identifier specifying the serialisers and processors we have used if (objectToSerialise is Packet) { this._packetHeader.SetOption(PacketHeaderLongItems.SerializerProcessors, DPSManager.CreateSerializerDataProcessorIdentifier(NetworkComms.InternalFixedSendReceiveOptions.DataSerializer, options.DataProcessors)); } else { this._packetHeader.SetOption(PacketHeaderLongItems.SerializerProcessors, DPSManager.CreateSerializerDataProcessorIdentifier(options.DataSerializer, options.DataProcessors)); } } //Set the null data header section if required if (objectToSerialiseIsNull && ((!containsSecurityCritialDataProcessors && !options.Options.ContainsKey("UseNestedPacketType")) || isNested)) { this._packetHeader.SetOption(PacketHeaderStringItems.NullDataSection, ""); } if (NetworkComms.LoggingEnabled) { if (isNested) { NetworkComms.Logger.Trace(" ... created nested packet of type " + sendingPacketTypeStr); } else { NetworkComms.Logger.Trace(" ... created packet of type " + sendingPacketTypeStr + ". PacketObject data size is " + payloadStream.Length.ToString() + " bytes"); } } }