Exemple #1
0
        private void SendChangeCipherSpec()
        {
            int size         = 1;
            int responseSize = DTLSRecord.RECORD_OVERHEAD + size;

            byte[]     response = new byte[responseSize];
            DTLSRecord record   = new DTLSRecord
            {
                RecordType     = TRecordType.ChangeCipherSpec,
                Epoch          = _Epoch,
                SequenceNumber = NextSequenceNumber(),
                Fragment       = new byte[size]
            };

            record.Fragment[0] = 1;
            if (_Version != null)
            {
                record.Version = _Version;
            }
            using (MemoryStream stream = new MemoryStream(response))
            {
                record.Serialise(stream);
            }
            SocketAsyncEventArgs parameters = new SocketAsyncEventArgs()
            {
                RemoteEndPoint = _ServerEndPoint
            };

            parameters.SetBuffer(response, 0, responseSize);
            _Socket.SendToAsync(parameters);
            ChangeEpoch();
        }
Exemple #2
0
        private async Task _SendAlertAsync(TAlertLevel alertLevel, TAlertDescription alertDescription, TimeSpan timeout)
        {
            if (this._Socket == null)
            {
                throw new Exception("Soket Cannot be Null");
            }

            var record = new DTLSRecord
            {
                RecordType     = TRecordType.Alert,
                Epoch          = _Epoch,
                SequenceNumber = this._NextSequenceNumber(),
                Version        = this._Version
            };

            var sequenceNumber = ((long)record.Epoch << 48) + record.SequenceNumber;

            var data = new byte[2];

            data[0]         = (byte)alertLevel;
            data[1]         = (byte)alertDescription;
            record.Fragment = this._Cipher == null ? data : this._Cipher.EncodePlaintext(sequenceNumber, (byte)TRecordType.ApplicationData, data, 0, data.Length);
            var recordSize  = DTLSRecord.RECORD_OVERHEAD + record.Fragment.Length;
            var recordBytes = new byte[recordSize];

            using (var stream = new MemoryStream(recordBytes))
            {
                record.Serialise(stream);
            }

            await this._Socket.SendAsync(recordBytes, timeout).ConfigureAwait(false);
        }
        private void SendResponseEnd(Session session, IHandshakeMessage handshakeMessage, ushort messageSequence)
        {
            int size           = handshakeMessage.CalculateSize(session.Version);
            int maxPayloadSize = _MaxPacketSize - DTLSRecord.RECORD_OVERHEAD + HandshakeRecord.RECORD_OVERHEAD;

            if (size > maxPayloadSize)
            {
            }
            else
            {
                DTLSRecord record = CreateRecord(session, handshakeMessage, messageSequence);
                session.Handshake.MessageSequence++;
                DTLSRecord recordEnd = CreateRecord(session, new ServerHelloDone(), session.Handshake.MessageSequence);
                session.Handshake.MessageSequence++;
                int responseSize = DTLSRecord.RECORD_OVERHEAD + record.Fragment.Length + DTLSRecord.RECORD_OVERHEAD + recordEnd.Fragment.Length;

                byte[] response = new byte[responseSize];
                using (MemoryStream stream = new MemoryStream(response))
                {
                    record.Serialise(stream);
                    recordEnd.Serialise(stream);
                }
                SocketAsyncEventArgs parameters = new SocketAsyncEventArgs()
                {
                    RemoteEndPoint = session.RemoteEndPoint
                };
                parameters.SetBuffer(response, 0, responseSize);
                _Socket.SendToAsync(parameters);
            }
        }
Exemple #4
0
        private void SendHandshakeMessage(IHandshakeMessage handshakeMessage, bool encrypt)
        {
            int size           = handshakeMessage.CalculateSize(_Version);
            int maxPayloadSize = _MaxPacketSize - DTLSRecord.RECORD_OVERHEAD + HandshakeRecord.RECORD_OVERHEAD;

            if (size > maxPayloadSize)
            {
            }
            else
            {
                DTLSRecord record = new DTLSRecord
                {
                    RecordType     = TRecordType.Handshake,
                    Epoch          = _Epoch,
                    SequenceNumber = NextSequenceNumber(),
                    Fragment       = new byte[HandshakeRecord.RECORD_OVERHEAD + size]
                };
                if (_Version != null)
                {
                    record.Version = _Version;
                }
                HandshakeRecord handshakeRecord = new HandshakeRecord
                {
                    MessageType = handshakeMessage.MessageType,
                    MessageSeq  = _MessageSequence
                };
                _MessageSequence++;
                handshakeRecord.Length         = (uint)size;
                handshakeRecord.FragmentLength = (uint)size;
                using (MemoryStream stream = new MemoryStream(record.Fragment))
                {
                    handshakeRecord.Serialise(stream);
                    handshakeMessage.Serialise(stream, _Version);
                }
                if (handshakeMessage.MessageType != THandshakeType.HelloVerifyRequest)
                {
                    _HandshakeInfo.UpdateHandshakeHash(record.Fragment);
                }
                int responseSize = DTLSRecord.RECORD_OVERHEAD + HandshakeRecord.RECORD_OVERHEAD + size;
                if ((_Cipher != null) && encrypt)
                {
                    long sequenceNumber = ((long)record.Epoch << 48) + record.SequenceNumber;
                    record.Fragment = _Cipher.EncodePlaintext(sequenceNumber, (byte)TRecordType.Handshake, record.Fragment, 0, record.Fragment.Length);
                    responseSize    = DTLSRecord.RECORD_OVERHEAD + record.Fragment.Length;
                }
                byte[] response = new byte[responseSize];
                using (MemoryStream stream = new MemoryStream(response))
                {
                    record.Serialise(stream);
                }
                SocketAsyncEventArgs parameters = new SocketAsyncEventArgs()
                {
                    RemoteEndPoint = _ServerEndPoint
                };
                parameters.SetBuffer(response, 0, responseSize);
                _Socket.SendToAsync(parameters);
            }
        }
        private void SendResponse(Session session, IHandshakeMessage handshakeMessage, ushort messageSequence)
        {
            int size           = handshakeMessage.CalculateSize(session.Version);
            int maxPayloadSize = _MaxPacketSize - DTLSRecord.RECORD_OVERHEAD + HandshakeRecord.RECORD_OVERHEAD;

            if (size > maxPayloadSize)
            {
            }
            else
            {
                DTLSRecord record = new DTLSRecord();
                record.RecordType     = TRecordType.Handshake;
                record.Epoch          = session.Epoch;
                record.SequenceNumber = session.NextSequenceNumber();
                record.Fragment       = new byte[HandshakeRecord.RECORD_OVERHEAD + size];
                if (session.Version != null)
                {
                    record.Version = session.Version;
                }
                HandshakeRecord handshakeRecord = new HandshakeRecord();
                handshakeRecord.MessageType    = handshakeMessage.MessageType;
                handshakeRecord.MessageSeq     = messageSequence;
                handshakeRecord.Length         = (uint)size;
                handshakeRecord.FragmentLength = (uint)size;
                using (MemoryStream stream = new MemoryStream(record.Fragment))
                {
                    handshakeRecord.Serialise(stream);
                    handshakeMessage.Serialise(stream, session.Version);
                }
                if (handshakeMessage.MessageType != THandshakeType.HelloVerifyRequest)
                {
                    session.Handshake.UpdateHandshakeHash(record.Fragment);
                }
                int responseSize = DTLSRecord.RECORD_OVERHEAD + HandshakeRecord.RECORD_OVERHEAD + size;
                if (session.Cipher != null)
                {
                    long sequenceNumber = ((long)record.Epoch << 48) + record.SequenceNumber;
                    record.Fragment = session.Cipher.EncodePlaintext(sequenceNumber, (byte)TRecordType.Handshake, record.Fragment, 0, record.Fragment.Length);
                    responseSize    = DTLSRecord.RECORD_OVERHEAD + record.Fragment.Length;
                }
                byte[] response = new byte[responseSize];
                using (MemoryStream stream = new MemoryStream(response))
                {
                    record.Serialise(stream);
                }
                SocketAsyncEventArgs parameters = new SocketAsyncEventArgs()
                {
                    RemoteEndPoint = session.RemoteEndPoint
                };
                parameters.SetBuffer(response, 0, responseSize);
                _Socket.SendToAsync(parameters);
            }
        }
Exemple #6
0
        public void Send(EndPoint remoteEndPoint, byte[] data)
        {
            SocketAddress address = remoteEndPoint.Serialize();
            Session       session = _Sessions.GetSession(address);

            if (session != null)
            {
                try
                {
                    DTLSRecord record = new DTLSRecord
                    {
                        RecordType     = TRecordType.ApplicationData,
                        Epoch          = session.Epoch,
                        SequenceNumber = session.NextSequenceNumber()
                    };
                    if (session.Version != null)
                    {
                        record.Version = session.Version;
                    }
                    long sequenceNumber = ((long)record.Epoch << 48) + record.SequenceNumber;
                    record.Fragment = session.Cipher.EncodePlaintext(sequenceNumber, (byte)TRecordType.ApplicationData, data, 0, data.Length);
                    int    responseSize = DTLSRecord.RECORD_OVERHEAD + record.Fragment.Length;
                    byte[] response     = new byte[responseSize];
                    using (MemoryStream stream = new MemoryStream(response))
                    {
                        record.Serialise(stream);
                    }
                    SocketAsyncEventArgs parameters = new SocketAsyncEventArgs()
                    {
                        RemoteEndPoint = session.RemoteEndPoint
                    };
                    parameters.SetBuffer(response, 0, responseSize);
                    _Socket.SendToAsync(parameters);
                }
#if DEBUG
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                    StackFrame callStack = new StackFrame(1, true);
                    Console.WriteLine($"Exception! Type: { ex.GetType()}\n\tData: { ex.Data.Count}\n\tMessage: { ex.Message}\n\tSource: { ex.Source}\n\t" +
                                      $"StackTrace: { ex.StackTrace}\n\tFile: {callStack.GetFileName()}\n\t" +
                                      $"Line: {callStack.GetFileLineNumber()}");
#else
                catch
                {
#endif
                }
            }
        }
Exemple #7
0
        private void SendAlert(Session session, SocketAddress address, TAlertLevel alertLevel, TAlertDescription alertDescription)
        {
#if DEBUG
            Console.WriteLine($"Alert! {alertDescription}");
#endif
            if (session != null)
            {
                DTLSRecord record = new DTLSRecord
                {
                    RecordType     = TRecordType.Alert,
                    Epoch          = session.Epoch,
                    SequenceNumber = session.NextSequenceNumber()
                };
                if (session.Version != null)
                {
                    record.Version = session.Version;
                }
                long sequenceNumber = ((long)record.Epoch << 48) + record.SequenceNumber;

                byte[] data = new byte[2];
                data[0] = (byte)alertLevel;
                data[1] = (byte)alertDescription;
                if (session.Cipher == null)
                {
                    record.Fragment = data;
                }
                else
                {
                    record.Fragment = session.Cipher.EncodePlaintext(sequenceNumber, (byte)TRecordType.ApplicationData, data, 0, data.Length);
                }
                int    responseSize = DTLSRecord.RECORD_OVERHEAD + record.Fragment.Length;
                byte[] response     = new byte[responseSize];
                using (MemoryStream stream = new MemoryStream(response))
                {
                    record.Serialise(stream);
                }
                SocketAsyncEventArgs parameters = new SocketAsyncEventArgs()
                {
                    RemoteEndPoint = session.RemoteEndPoint
                };
                parameters.SetBuffer(response, 0, responseSize);
                _Socket.SendToAsync(parameters);
            }
        }
Exemple #8
0
        public void Send(EndPoint remoteEndPoint, byte[] data)
        {
            SocketAddress address = remoteEndPoint.Serialize();
            Session       session = _Sessions.GetSession(address);

            if (session != null)
            {
                try
                {
                    DTLSRecord record = new DTLSRecord();
                    record.RecordType     = TRecordType.ApplicationData;
                    record.Epoch          = session.Epoch;
                    record.SequenceNumber = session.NextSequenceNumber();
                    if (session.Version != null)
                    {
                        record.Version = session.Version;
                    }
                    long sequenceNumber = ((long)record.Epoch << 48) + record.SequenceNumber;
                    record.Fragment = session.Cipher.EncodePlaintext(sequenceNumber, (byte)TRecordType.ApplicationData, data, 0, data.Length);
                    int    responseSize = DTLSRecord.RECORD_OVERHEAD + record.Fragment.Length;
                    byte[] response     = new byte[responseSize];
                    using (MemoryStream stream = new MemoryStream(response))
                    {
                        record.Serialise(stream);
                    }
                    SocketAsyncEventArgs parameters = new SocketAsyncEventArgs()
                    {
                        RemoteEndPoint = session.RemoteEndPoint
                    };
                    parameters.SetBuffer(response, 0, responseSize);
                    _Socket.SendToAsync(parameters);
                }
#if DEBUG
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
#else
                catch
                {
#endif
                }
            }
        }
Exemple #9
0
        private byte[] _GetChangeCipherSpec()
        {
            var size         = 1;
            var responseSize = DTLSRecord.RECORD_OVERHEAD + size;
            var response     = new byte[responseSize];
            var record       = new DTLSRecord
            {
                RecordType     = TRecordType.ChangeCipherSpec,
                Epoch          = _Epoch,
                SequenceNumber = this._NextSequenceNumber(),
                Fragment       = new byte[size],
                Version        = this._Version
            };

            record.Fragment[0] = 1;
            using (var stream = new MemoryStream(response))
            {
                record.Serialise(stream);
            }
            return(response);
        }
Exemple #10
0
        private void SendAlert(TAlertLevel alertLevel, TAlertDescription alertDescription)
        {
            DTLSRecord record = new DTLSRecord();

            record.RecordType     = TRecordType.Alert;
            record.Epoch          = _Epoch;
            record.SequenceNumber = NextSequenceNumber();
            if (_Version != null)
            {
                record.Version = _Version;
            }
            long sequenceNumber = ((long)record.Epoch << 48) + record.SequenceNumber;

            byte[] data = new byte[2];
            data[0] = (byte)alertLevel;
            data[1] = (byte)alertDescription;
            if (_Cipher == null)
            {
                record.Fragment = data;
            }
            else
            {
                record.Fragment = _Cipher.EncodePlaintext(sequenceNumber, (byte)TRecordType.ApplicationData, data, 0, data.Length);
            }
            int responseSize = DTLSRecord.RECORD_OVERHEAD + record.Fragment.Length;

            byte[] response = new byte[responseSize];
            using (MemoryStream stream = new MemoryStream(response))
            {
                record.Serialise(stream);
            }
            SocketAsyncEventArgs parameters = new SocketAsyncEventArgs()
            {
                RemoteEndPoint = _ServerEndPoint
            };

            parameters.SetBuffer(response, 0, responseSize);
            _Socket.SendToAsync(parameters);
        }
Exemple #11
0
        public async Task SendAsync(byte[] data, TimeSpan timeout)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }

            if (this._Socket == null)
            {
                throw new Exception("Socket Cannot be Null");
            }

            if (this._Cipher == null)
            {
                throw new Exception("Cipher Cannot be Null");
            }

            var record = new DTLSRecord
            {
                RecordType     = TRecordType.ApplicationData,
                Epoch          = _Epoch,
                SequenceNumber = this._NextSequenceNumber(),
                Version        = this._Version
            };

            var sequenceNumber = ((long)record.Epoch << 48) + record.SequenceNumber;

            record.Fragment = this._Cipher.EncodePlaintext(sequenceNumber, (byte)TRecordType.ApplicationData, data, 0, data.Length);

            var recordSize  = DTLSRecord.RECORD_OVERHEAD + record.Fragment.Length;
            var recordBytes = new byte[recordSize];

            using (var stream = new MemoryStream(recordBytes))
            {
                record.Serialise(stream);
            }

            await this._Socket.SendAsync(recordBytes, timeout).ConfigureAwait(false);
        }
        private void SendChangeCipherSpec(Session session)
        {
            if (session == null)
            {
                throw new ArgumentNullException(nameof(session));
            }

            var size         = 1;
            var responseSize = DTLSRecord.RECORD_OVERHEAD + size;
            var response     = new byte[responseSize];
            var record       = new DTLSRecord
            {
                RecordType     = TRecordType.ChangeCipherSpec,
                Epoch          = session.Epoch,
                SequenceNumber = session.NextSequenceNumber(),
                Fragment       = new byte[size]
            };

            record.Fragment[0] = 1;
            if (session.Version != null)
            {
                record.Version = session.Version;
            }

            using (var stream = new MemoryStream(response))
            {
                record.Serialise(stream);
            }
            var parameters = new SocketAsyncEventArgs()
            {
                RemoteEndPoint = session.RemoteEndPoint
            };

            parameters.SetBuffer(response, 0, responseSize);
            this._Socket.SendToAsync(parameters);
            session.ChangeEpoch();
        }
Exemple #13
0
        private IEnumerable <byte[]> _GetBytes(IHandshakeMessage handshakeMessage, bool encrypt)
        {
            if (handshakeMessage == null)
            {
                throw new ArgumentNullException(nameof(handshakeMessage));
            }

            var size           = handshakeMessage.CalculateSize(this._Version);
            var maxPayloadSize = _MaxPacketSize - DTLSRecord.RECORD_OVERHEAD + HandshakeRecord.RECORD_OVERHEAD;

            if (size > maxPayloadSize)
            {
                var wholeMessage = new List <byte[]>();

                var record = new DTLSRecord
                {
                    RecordType = TRecordType.Handshake,
                    Epoch      = _Epoch,
                    Version    = this._Version
                };

                var handshakeRecord = new HandshakeRecord
                {
                    MessageType = handshakeMessage.MessageType,
                    MessageSeq  = _MessageSequence
                };

                if (!(handshakeMessage.MessageType == THandshakeType.HelloVerifyRequest ||
                      (handshakeMessage.MessageType == THandshakeType.ClientHello && (handshakeMessage as ClientHello).Cookie == null)))
                {
                    record.Fragment                = new byte[HandshakeRecord.RECORD_OVERHEAD + size];
                    handshakeRecord.Length         = (uint)size;
                    handshakeRecord.FragmentLength = (uint)size;
                    handshakeRecord.FragmentOffset = 0u;
                    using (var stream = new MemoryStream(record.Fragment))
                    {
                        handshakeRecord.Serialise(stream);
                        handshakeMessage.Serialise(stream, this._Version);
                    }

                    this._HandshakeInfo.UpdateHandshakeHash(record.Fragment);
                }

                var dataMessage = new byte[size];
                using (var stream = new MemoryStream(dataMessage))
                {
                    handshakeMessage.Serialise(stream, this._Version);
                }

                var dataMessageFragments = dataMessage.ChunkBySize(maxPayloadSize);
                handshakeRecord.FragmentOffset = 0U;
                dataMessageFragments.ForEach(x =>
                {
                    handshakeRecord.Length         = (uint)size;
                    handshakeRecord.FragmentLength = (uint)x.Count();
                    record.SequenceNumber          = this._NextSequenceNumber();

                    var baseMessage = new byte[HandshakeRecord.RECORD_OVERHEAD];
                    using (var stream = new MemoryStream(baseMessage))
                    {
                        handshakeRecord.Serialise(stream);
                    }

                    record.Fragment = baseMessage.Concat(x).ToArray();

                    var responseSize = DTLSRecord.RECORD_OVERHEAD + HandshakeRecord.RECORD_OVERHEAD + x.Count();
                    if ((this._Cipher != null) && encrypt)
                    {
                        var sequenceNumber = ((long)record.Epoch << 48) + record.SequenceNumber;
                        record.Fragment    = this._Cipher.EncodePlaintext(sequenceNumber, (byte)TRecordType.Handshake, record.Fragment, 0, record.Fragment.Length);
                        responseSize       = DTLSRecord.RECORD_OVERHEAD + record.Fragment.Length;
                    }
                    var response = new byte[responseSize];
                    using (var stream = new MemoryStream(response))
                    {
                        record.Serialise(stream);
                    }

                    wholeMessage.Add(response);
                    handshakeRecord.FragmentOffset += (uint)x.Count();
                });

                this._MessageSequence++;
                return(wholeMessage);
            }
            else
            {
                var record = new DTLSRecord
                {
                    RecordType     = TRecordType.Handshake,
                    Epoch          = _Epoch,
                    SequenceNumber = this._NextSequenceNumber(),
                    Fragment       = new byte[HandshakeRecord.RECORD_OVERHEAD + size],
                    Version        = this._Version
                };

                var handshakeRecord = new HandshakeRecord
                {
                    MessageType = handshakeMessage.MessageType,
                    MessageSeq  = _MessageSequence
                };
                this._MessageSequence++;
                handshakeRecord.Length         = (uint)size;
                handshakeRecord.FragmentLength = (uint)size;
                using (var stream = new MemoryStream(record.Fragment))
                {
                    handshakeRecord.Serialise(stream);
                    handshakeMessage.Serialise(stream, this._Version);
                }

                if (!(handshakeMessage.MessageType == THandshakeType.HelloVerifyRequest ||
                      (handshakeMessage.MessageType == THandshakeType.ClientHello && (handshakeMessage as ClientHello).Cookie == null)))
                {
                    this._HandshakeInfo.UpdateHandshakeHash(record.Fragment);
                }

                var responseSize = DTLSRecord.RECORD_OVERHEAD + HandshakeRecord.RECORD_OVERHEAD + size;
                if ((this._Cipher != null) && encrypt)
                {
                    var sequenceNumber = ((long)record.Epoch << 48) + record.SequenceNumber;
                    record.Fragment = this._Cipher.EncodePlaintext(sequenceNumber, (byte)TRecordType.Handshake, record.Fragment, 0, record.Fragment.Length);
                    responseSize    = DTLSRecord.RECORD_OVERHEAD + record.Fragment.Length;
                }

                var response = new byte[responseSize];
                using (var stream = new MemoryStream(response))
                {
                    record.Serialise(stream);
                }

                return(new List <byte[]>()
                {
                    response
                });
            }
        }
		private void SendChangeCipherSpec(Session session)
		{
			int size = 1;
			int responseSize = DTLSRecord.RECORD_OVERHEAD + size;
			byte[] response = new byte[responseSize];
			DTLSRecord record = new DTLSRecord();
			record.RecordType = TRecordType.ChangeCipherSpec;
			record.Epoch = session.Epoch;
			record.SequenceNumber = session.NextSequenceNumber();
			record.Fragment = new byte[size];
			record.Fragment[0] = 1;
			if (session.Version != null)
				record.Version = session.Version;
			using (MemoryStream stream = new MemoryStream(response))
			{
				record.Serialise(stream);
			}
            SocketAsyncEventArgs parameters = new SocketAsyncEventArgs()
            {
                RemoteEndPoint = session.RemoteEndPoint
            };
            parameters.SetBuffer(response, 0, responseSize);
            _Socket.SendToAsync(parameters);
            session.ChangeEpoch();
		}
Exemple #15
0
        private void SendAlert(TAlertLevel alertLevel, TAlertDescription alertDescription)
        {
            DTLSRecord record = new DTLSRecord();
            record.RecordType = TRecordType.Alert;
            record.Epoch = _Epoch;
            record.SequenceNumber = NextSequenceNumber();
            if (_Version != null)
                record.Version = _Version;
            long sequenceNumber = ((long)record.Epoch << 48) + record.SequenceNumber;

            byte[] data = new byte[2];
            data[0] = (byte)alertLevel;
            data[1] = (byte)alertDescription;
            if (_Cipher == null)
                record.Fragment = data;
            else
                record.Fragment = _Cipher.EncodePlaintext(sequenceNumber, (byte)TRecordType.ApplicationData, data, 0, data.Length);
            int responseSize = DTLSRecord.RECORD_OVERHEAD + record.Fragment.Length;
            byte[] response = new byte[responseSize];
            using (MemoryStream stream = new MemoryStream(response))
            {
                record.Serialise(stream);
            }
            SocketAsyncEventArgs parameters = new SocketAsyncEventArgs()
            {
                RemoteEndPoint = _ServerEndPoint
            };
            parameters.SetBuffer(response, 0, responseSize);
            _Socket.SendToAsync(parameters);
        }
Exemple #16
0
        public void Send(byte[] data)
        {
            try
            {
                DTLSRecord record = new DTLSRecord();
                record.RecordType = TRecordType.ApplicationData;
                record.Epoch = _Epoch;
                record.SequenceNumber = NextSequenceNumber();
                if (_Version != null)
                    record.Version = _Version;
                long sequenceNumber = ((long)record.Epoch << 48) + record.SequenceNumber;
                record.Fragment = _Cipher.EncodePlaintext(sequenceNumber, (byte)TRecordType.ApplicationData, data, 0, data.Length);
                int responseSize = DTLSRecord.RECORD_OVERHEAD + record.Fragment.Length;
                byte[] response = new byte[responseSize];
                using (MemoryStream stream = new MemoryStream(response))
                {
                    record.Serialise(stream);
                }
                SocketAsyncEventArgs parameters = new SocketAsyncEventArgs()
                {
                    RemoteEndPoint = _ServerEndPoint
                };
                parameters.SetBuffer(response, 0, responseSize);
                if (_Socket != null)
                    _Socket.SendToAsync(parameters);
            }
#if DEBUG
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
#else
            catch
            {
#endif

            }
        }
		private void SendResponse(Session session, IHandshakeMessage handshakeMessage, ushort messageSequence)
		{
			int size = handshakeMessage.CalculateSize(session.Version);
			int maxPayloadSize = _MaxPacketSize - DTLSRecord.RECORD_OVERHEAD + HandshakeRecord.RECORD_OVERHEAD;
			if (size > maxPayloadSize)
			{

			}
			else
			{
				
				DTLSRecord record = new DTLSRecord();
				record.RecordType = TRecordType.Handshake;
				record.Epoch = session.Epoch;
				record.SequenceNumber = session.NextSequenceNumber();
				record.Fragment = new byte[HandshakeRecord.RECORD_OVERHEAD + size];
				if (session.Version != null)
					record.Version = session.Version;
				HandshakeRecord handshakeRecord = new HandshakeRecord();
				handshakeRecord.MessageType = handshakeMessage.MessageType;
				handshakeRecord.MessageSeq = messageSequence;
				handshakeRecord.Length = (uint)size;
				handshakeRecord.FragmentLength = (uint)size;
				using (MemoryStream stream = new MemoryStream(record.Fragment))
				{
					handshakeRecord.Serialise(stream);
					handshakeMessage.Serialise(stream, session.Version);
				}
                if (handshakeMessage.MessageType != THandshakeType.HelloVerifyRequest)
                {
                    session.Handshake.UpdateHandshakeHash(record.Fragment);
                }
                int responseSize = DTLSRecord.RECORD_OVERHEAD + HandshakeRecord.RECORD_OVERHEAD + size;
                if (session.Cipher != null)
                {
                   long sequenceNumber = ((long)record.Epoch << 48) + record.SequenceNumber;                   
                   record.Fragment = session.Cipher.EncodePlaintext(sequenceNumber, (byte)TRecordType.Handshake, record.Fragment, 0, record.Fragment.Length);
                   responseSize = DTLSRecord.RECORD_OVERHEAD + record.Fragment.Length;
                }
                byte[] response = new byte[responseSize];
				using (MemoryStream stream = new MemoryStream(response))
				{
					record.Serialise(stream);
				}
                SocketAsyncEventArgs parameters = new SocketAsyncEventArgs()
                {
                    RemoteEndPoint = session.RemoteEndPoint
                };
                parameters.SetBuffer(response, 0, responseSize);
                _Socket.SendToAsync(parameters);
			}


		}
        private void SendResponse(Session session, IHandshakeMessage handshakeMessage, ushort messageSequence)
        {
            if (session == null)
            {
                throw new ArgumentNullException(nameof(session));
            }

            if (handshakeMessage == null)
            {
                throw new ArgumentNullException(nameof(handshakeMessage));
            }

            var size           = handshakeMessage.CalculateSize(session.Version);
            var maxPayloadSize = this._MaxPacketSize - DTLSRecord.RECORD_OVERHEAD + HandshakeRecord.RECORD_OVERHEAD;

            if (size > maxPayloadSize)
            {
                //fragments
                return;
            }

            var record = new DTLSRecord
            {
                RecordType     = TRecordType.Handshake,
                Epoch          = session.Epoch,
                SequenceNumber = session.NextSequenceNumber(),
                Fragment       = new byte[HandshakeRecord.RECORD_OVERHEAD + size]
            };

            if (session.Version != null)
            {
                record.Version = session.Version;
            }

            var handshakeRecord = new HandshakeRecord
            {
                MessageType    = handshakeMessage.MessageType,
                MessageSeq     = messageSequence,
                Length         = (uint)size,
                FragmentLength = (uint)size
            };

            using (var stream = new MemoryStream(record.Fragment))
            {
                handshakeRecord.Serialise(stream);
                handshakeMessage.Serialise(stream, session.Version);
            }

            if (handshakeMessage.MessageType != THandshakeType.HelloVerifyRequest)
            {
                session.Handshake.UpdateHandshakeHash(record.Fragment);
            }

            var responseSize = DTLSRecord.RECORD_OVERHEAD + HandshakeRecord.RECORD_OVERHEAD + size;

            if (session.Cipher != null)
            {
                var sequenceNumber = ((long)record.Epoch << 48) + record.SequenceNumber;
                record.Fragment = session.Cipher.EncodePlaintext(sequenceNumber, (byte)TRecordType.Handshake, record.Fragment, 0, record.Fragment.Length);
                responseSize    = DTLSRecord.RECORD_OVERHEAD + record.Fragment.Length;
            }

            var response = new byte[responseSize];

            using (var stream = new MemoryStream(response))
            {
                record.Serialise(stream);
            }
            var parameters = new SocketAsyncEventArgs()
            {
                RemoteEndPoint = session.RemoteEndPoint
            };

            parameters.SetBuffer(response, 0, responseSize);
            this._Socket.SendToAsync(parameters);
        }