/// <summary> /// CTKEPacket primary constructor /// </summary> /// /// <param name="PacketType">The <see cref="DtmPacketTypes"/> message type; describes the packet classification</param> /// <param name="PayloadLength">The length of the payload contained in the packet</param> /// <param name="Sequence">The packet sequence number</param> /// <param name="Sequence">The <see cref="DtmServiceFlags"/> exchange state; indicates the exchange state position</param> /// <param name="OptionFlag">The packet header option flag</param> public DtmPacket(DtmPacketTypes PacketType, long PayloadLength, long Sequence, short PacketFlag, long OptionFlag = 0) { this.PacketType = PacketType; this.PayloadLength = PayloadLength; this.Sequence = Sequence; this.PacketFlag = PacketFlag; this.OptionFlag = OptionFlag; }
/// <summary> /// Frame and Transmit the packet to the remote client /// </summary> /// /// <param name="PacketType">The packet class</param> /// <param name="PacketFlag">The packet message type flag</param> /// <param name="OptionFlag">The option flag</param> /// <param name="Payload">The packet payload flag</param> /// <param name="Blocking">Blocking or Async transmit</param> private void Transmit(DtmPacketTypes PacketType, short PacketFlag, long OptionFlag = 0, MemoryStream Payload = null, bool Blocking = false) { lock (_sendLock) { long pldLen = Payload == null ? 0 : Payload.Length; // create a new packet: packet flag, payload size, sequence, and state flag MemoryStream pktStm = new DtmPacket(PacketType, pldLen, _sndSequence, PacketFlag, OptionFlag).ToStream(); // add payload if (Payload != null) { // store total encrypted bytes sent if (_isEstablished) _bytesSent += Payload.Length; // copy to output pktStm.Seek(0, SeekOrigin.End); Payload.WriteTo(pktStm); pktStm.Seek(0, SeekOrigin.Begin); } // service requests are not buffered if (PacketType != DtmPacketTypes.Service) { // store in the packet buffer _sndBuffer.Push(_sndSequence, pktStm); } // increment send counter _sndSequence++; // transmit to remote client if (_clientSocket.IsConnected) { if (Blocking) { try { _clientSocket.SendAsync(pktStm); } catch (CryptoSocketException ce) { SocketException se = ce.InnerException as SocketException; if (se.SocketErrorCode == SocketError.WouldBlock || se.SocketErrorCode == SocketError.IOPending || se.SocketErrorCode == SocketError.NoBufferSpaceAvailable) { // buffer is full, slow down Throttle(pktStm); } else if (se.SocketErrorCode != SocketError.Success) { // possible connection dropped, alert app if (SessionError != null) { DtmErrorEventArgs args = new DtmErrorEventArgs(ce, DtmErrorSeverity.Connection); SessionError(this, args); if (args.Cancel == true) Disconnect(); } } } } else { try { pktStm.WriteTo(_clientSocket.TcpStream); } catch (Exception ex) { // internal error, alert app if (SessionError != null) { DtmErrorEventArgs args = new DtmErrorEventArgs(ex, DtmErrorSeverity.Critical); SessionError(this, args); if (args.Cancel == true) Disconnect(); } } } // notify app if (PacketSent != null) PacketSent(this, new DtmPacketEventArgs((short)_exchangeState, pldLen)); } else { // possible connection dropped, alert app if (SessionError != null) { DtmErrorEventArgs args = new DtmErrorEventArgs(new SocketException((int)SocketError.ConnectionReset), DtmErrorSeverity.Connection); SessionError(this, args); if (args.Cancel == true) Disconnect(); } } } }
/// <summary> /// Creates a serialized request packet (DtmPacket) /// </summary> private MemoryStream CreateRequest(DtmPacketTypes Message, short State, int Sequence = 0) { return new DtmPacket(Message, 0, 0, State).ToStream(); }
private void Transmit(DtmPacketTypes PacketType, short PacketFlag, long OptionFlag = 0, MemoryStream Payload = null) { lock (_sndLock) { long pldLen = Payload == null ? 0 : Payload.Length; // create a new packet: packet flag, payload size, sequence, and state flag MemoryStream pktStm = new DtmPacket(PacketType, pldLen, _sndSequence, PacketFlag, OptionFlag).ToStream(); // add payload if (Payload != null) { // copy to output pktStm.Seek(0, SeekOrigin.End); Payload.WriteTo(pktStm); pktStm.Seek(0, SeekOrigin.Begin); } // store in the file packet buffer _sndBuffer.Push(_sndSequence, pktStm); // increment file send counter _sndSequence++; // transmit to remote client if (_clientSocket.IsConnected) { try { _clientSocket.SendAsync(pktStm); } catch (CryptoSocketException ce) { SocketException se = ce.InnerException as SocketException; if (se.SocketErrorCode == SocketError.WouldBlock || se.SocketErrorCode == SocketError.IOPending || se.SocketErrorCode == SocketError.NoBufferSpaceAvailable) { // buffer is full, throttle down Throttle(pktStm); } else { // possible connection dropped, alert app if (SessionError != null) { DtmErrorEventArgs args = new DtmErrorEventArgs(ce, DtmErrorSeverity.Connection); SessionError(this, args); } } } catch (Exception) { } // notify app if (PacketSent != null) PacketSent(this, new DtmPacketEventArgs((short)DtmTransferFlags.DataChunk, pldLen)); } } }
/// <summary> /// Creates a serialized request packet (DtmPacket) /// </summary> private MemoryStream CreateRequest(DtmPacketTypes Message, short State) { MemoryStream ret = new DtmPacket(Message, 0, 0, State).ToStream(); ret.Seek(0, SeekOrigin.Begin); return ret; }
/// <summary> /// Extracts a DtmPacket from a Stream /// </summary> /// /// <param name="PacketStream">The Stream containing the DtmPacket structure</param> public DtmPacket(Stream PacketStream) { BinaryReader reader = new BinaryReader(PacketStream); PacketType = (DtmPacketTypes)reader.ReadByte(); PayloadLength = reader.ReadInt64(); Sequence = reader.ReadInt64(); PacketFlag = (short)reader.ReadByte(); OptionFlag = reader.ReadInt64(); }
/// <summary> /// Reset all struct members /// </summary> public void Reset() { PacketType = 0; PayloadLength = 0; Sequence = 0; PacketFlag = 0; OptionFlag = 0; }