using System; using System.Collections; using System.IO; using System.Runtime.InteropServices; using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities; using Cpp2IlInjected; using Hjg.Pngcs; namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Tls { // Token: 0x0200154C RID: 5452 [Token(Token = "0x200154C")] [StructLayout(3)] internal class DtlsReliableHandshake { // Token: 0x06009127 RID: 37159 RVA: 0x00203084 File Offset: 0x00201284 [Token(Token = "0x6009127")] [Address(RVA = "0x1E84B10", Offset = "0x1E83510", VA = "0x181E84B10")] internal DtlsReliableHandshake(TlsContext context, DtlsRecordLayer transport) { /* An exception occurred when decompiling this method (06009127) ICSharpCode.Decompiler.DecompilerException: Error decompiling System.Void BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Tls.DtlsReliableHandshake::.ctor(BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Tls.TlsContext,BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Tls.DtlsRecordLayer) ---> System.Exception: Basic block has to end with unconditional control flow. { Block_0: stloc:IDictionary(var_1_07, call:IDictionary(Platform::CreateHashtable)) stfld:IDictionary(DtlsReliableHandshake::mCurrentInboundFlight, ldloc:DtlsReliableHandshake(this), ldloc:IDictionary(var_1_07)) stloc:IList(var_3_16, call:IList(Platform::CreateArrayList)) stfld:IList(DtlsReliableHandshake::mOutboundFlight, ldloc:DtlsReliableHandshake(this), ldloc:IList(var_3_16)) stfld:bool(DtlsReliableHandshake::mSending, ldloc:DtlsReliableHandshake(this), ldc.i4:bool(1)) call:void(object::.ctor, ldloc:DtlsReliableHandshake[exp:object](this)) stfld:DtlsRecordLayer(DtlsReliableHandshake::mRecordLayer, ldloc:DtlsReliableHandshake(this), ldloc:DtlsRecordLayer(transport)) stloc:DeferredHash(var_4_37, newobj:DeferredHash(DeferredHash::.ctor)) stloc:DigestInputBuffer(var_5_3E, newobj:DigestInputBuffer(DigestInputBuffer::.ctor)) stfld:DigestInputBuffer(DeferredHash::mBuf, ldloc:DeferredHash(var_4_37), ldloc:DigestInputBuffer(var_5_3E)) stloc:IDictionary(var_7_51, call:IDictionary(Platform::CreateHashtable)) stfld:IDictionary(DeferredHash::mHashes, ldloc:DeferredHash(var_4_37), ldloc:IDictionary(var_7_51)) stfld:int32(DeferredHash::mPrfHashAlgorithm, ldloc:DeferredHash(var_4_37), conv.u8:uint64[exp:int32](ldc.i8:int64[exp:uint64](4294967295))) stfld:TlsHandshakeHash(DtlsReliableHandshake::mHandshakeHash, ldloc:DtlsReliableHandshake(this), ldloc:DeferredHash[exp:TlsHandshakeHash](var_4_37)) } at ICSharpCode.Decompiler.ILAst.ILAstOptimizer.FlattenBasicBlocks(ILNode node) in D:\a\dnSpy\dnSpy\Extensions\ILSpy.Decompiler\ICSharpCode.Decompiler\ICSharpCode.Decompiler\ILAst\ILAstOptimizer.cs:line 1852 at ICSharpCode.Decompiler.ILAst.ILAstOptimizer.Optimize(DecompilerContext context, ILBlock method, AutoPropertyProvider autoPropertyProvider, StateMachineKind& stateMachineKind, MethodDef& inlinedMethod, AsyncMethodDebugInfo& asyncInfo, ILAstOptimizationStep abortBeforeStep) in D:\a\dnSpy\dnSpy\Extensions\ILSpy.Decompiler\ICSharpCode.Decompiler\ICSharpCode.Decompiler\ILAst\ILAstOptimizer.cs:line 355 at ICSharpCode.Decompiler.Ast.AstMethodBodyBuilder.CreateMethodBody(IEnumerable`1 parameters, MethodDebugInfoBuilder& builder) in D:\a\dnSpy\dnSpy\Extensions\ILSpy.Decompiler\ICSharpCode.Decompiler\ICSharpCode.Decompiler\Ast\AstMethodBodyBuilder.cs:line 123 at ICSharpCode.Decompiler.Ast.AstMethodBodyBuilder.CreateMethodBody(MethodDef methodDef, DecompilerContext context, AutoPropertyProvider autoPropertyProvider, IEnumerable`1 parameters, Boolean valueParameterIsKeyword, StringBuilder sb, MethodDebugInfoBuilder& stmtsBuilder) in D:\a\dnSpy\dnSpy\Extensions\ILSpy.Decompiler\ICSharpCode.Decompiler\ICSharpCode.Decompiler\Ast\AstMethodBodyBuilder.cs:line 88 --- End of inner exception stack trace --- at ICSharpCode.Decompiler.Ast.AstMethodBodyBuilder.CreateMethodBody(MethodDef methodDef, DecompilerContext context, AutoPropertyProvider autoPropertyProvider, IEnumerable`1 parameters, Boolean valueParameterIsKeyword, StringBuilder sb, MethodDebugInfoBuilder& stmtsBuilder) in D:\a\dnSpy\dnSpy\Extensions\ILSpy.Decompiler\ICSharpCode.Decompiler\ICSharpCode.Decompiler\Ast\AstMethodBodyBuilder.cs:line 92 at ICSharpCode.Decompiler.Ast.AstBuilder.AddMethodBody(EntityDeclaration methodNode, EntityDeclaration& updatedNode, MethodDef method, IEnumerable`1 parameters, Boolean valueParameterIsKeyword, MethodKind methodKind) in D:\a\dnSpy\dnSpy\Extensions\ILSpy.Decompiler\ICSharpCode.Decompiler\ICSharpCode.Decompiler\Ast\AstBuilder.cs:line 1663 */; } // Token: 0x06009128 RID: 37160 RVA: 0x00203108 File Offset: 0x00201308 [Token(Token = "0x6009128")] [Address(RVA = "0x1E83770", Offset = "0x1E82170", VA = "0x181E83770")] internal void NotifyHelloComplete() { TlsHandshakeHash tlsHandshakeHash = this.mHandshakeHash; } // Token: 0x17001768 RID: 5992 // (get) Token: 0x06009129 RID: 37161 RVA: 0x00203124 File Offset: 0x00201324 [Token(Token = "0x17001768")] internal TlsHandshakeHash HandshakeHash { [Token(Token = "0x6009129")] [Address(RVA = "0x3C1240", Offset = "0x3BFC40", VA = "0x1803C1240")] get { return this.mHandshakeHash; } } // Token: 0x0600912A RID: 37162 RVA: 0x00203138 File Offset: 0x00201338 [Token(Token = "0x600912A")] [Address(RVA = "0x1E83800", Offset = "0x1E82200", VA = "0x181E83800")] internal TlsHandshakeHash PrepareToFinish() { return this.mHandshakeHash; } // Token: 0x0600912B RID: 37163 RVA: 0x00203154 File Offset: 0x00201354 [Token(Token = "0x600912B")] [Address(RVA = "0x1E84580", Offset = "0x1E82F80", VA = "0x181E84580")] internal void SendMessage(byte msg_type, byte[] body) { TlsUtilities.CheckUint24(body.Length); if (!this.mSending) { this.CheckInboundFlight(); IList list = this.mOutboundFlight; this.mSending = true; } int num = this.mMessageSeq; int num2 = num + 1; this.mMessageSeq = num2; DtlsReliableHandshake.Message message; message.mMessageSeq = num; message.mMsgType = msg_type; message.mBody = body; IList list2 = this.mOutboundFlight; this.WriteMessage(message); DtlsReliableHandshake.Message message2 = this.UpdateHandshakeMessagesDigest(message); } // Token: 0x0600912C RID: 37164 RVA: 0x002031D0 File Offset: 0x002013D0 [Token(Token = "0x600912C")] [Address(RVA = "0x1E83C10", Offset = "0x1E82610", VA = "0x181E83C10")] internal byte[] ReceiveMessageBody(byte msg_type) { DtlsReliableHandshake.Message message; do { message = this.ReceiveMessage(); } while (message.mMsgType != msg_type); return message.mBody; } // Token: 0x0600912D RID: 37165 RVA: 0x002031FC File Offset: 0x002013FC [Token(Token = "0x600912D")] [Address(RVA = "0x1E83C90", Offset = "0x1E82690", VA = "0x181E83C90")] internal DtlsReliableHandshake.Message ReceiveMessage() { if (this.mSending) { this.mSending = false; IDictionary dictionary = Platform.CreateHashtable(); DtlsReliableHandshake.ResetAll(this.mCurrentInboundFlight); IDictionary dictionary2 = this.mCurrentInboundFlight; this.mPreviousInboundFlight = dictionary2; this.mCurrentInboundFlight = dictionary; } int num = 0; IDictionary dictionary3 = this.mCurrentInboundFlight; int num2 = this.mNextReceiveSeq; if (num2 != 0) { int num3 = 0; if (num2 == 0) { throw new NullReferenceException(); } if (num3 == 0) { this.mPreviousInboundFlight = num; int num4 = this.mNextReceiveSeq; int num5 = num4 + 1; this.mNextReceiveSeq = num5; DtlsReliableHandshake.Message message; message.mMessageSeq = num4; DtlsReliableHandshake.Message message2 = this.UpdateHandshakeMessagesDigest(message); if (message2 != 0) { return message2; } } } this.mRecordLayer.ResetWriteEpoch(); if (num != 0) { } byte[] array = new byte[0]; int sendLimit = this.mRecordLayer.GetSendLimit(); DtlsRecordLayer dtlsRecordLayer = this.mRecordLayer; bool flag; while (!flag) { } this.ResendOutboundFlight(); throw new NullReferenceException(); } // Token: 0x0600912E RID: 37166 RVA: 0x002032FC File Offset: 0x002014FC [Token(Token = "0x600912E")] [Address(RVA = "0x1E83550", Offset = "0x1E81F50", VA = "0x181E83550")] internal void Finish() { int num = 0; if ((this.mSending ? 1 : 0) != num) { DtlsReliableHandshake.ResetAll(this.mCurrentInboundFlight); IDictionary dictionary = this.mCurrentInboundFlight; this.mPreviousInboundFlight = dictionary; this.mCurrentInboundFlight = num; if (dictionary == 0) { goto IL_3C; } DtlsReliableHandshake.Retransmit retransmit; retransmit.mOuter = this; } this.CheckInboundFlight(); IL_3C: int receiveLimit = ((DatagramTransport)this.mRecordLayer).GetReceiveLimit(); } // Token: 0x0600912F RID: 37167 RVA: 0x00203358 File Offset: 0x00201558 [Token(Token = "0x600912F")] [Address(RVA = "0x1E84530", Offset = "0x1E82F30", VA = "0x181E84530")] internal void ResetHandshakeMessagesDigest() { TlsHandshakeHash tlsHandshakeHash = this.mHandshakeHash; throw new NullReferenceException(); } // Token: 0x06009130 RID: 37168 RVA: 0x00203374 File Offset: 0x00201574 [Token(Token = "0x6009130")] [Address(RVA = "0x1E830D0", Offset = "0x1E81AD0", VA = "0x181E830D0")] private int BackOff(int timeoutMillis) { int num; return num; } // Token: 0x06009131 RID: 37169 RVA: 0x00203384 File Offset: 0x00201584 [Token(Token = "0x6009131")] [Address(RVA = "0x1E833B0", Offset = "0x1E81DB0", VA = "0x181E833B0")] private void CheckInboundFlight() { int num; do { num = 0; IDictionary dictionary = this.mCurrentInboundFlight; num += num; num++; num++; num += 19; if (num != 0) { } if (num != -1) { } } while (num != 0); } // Token: 0x06009132 RID: 37170 RVA: 0x002033C0 File Offset: 0x002015C0 [Token(Token = "0x6009132")] [Address(RVA = "0x1E835F0", Offset = "0x1E81FF0", VA = "0x181E835F0")] private DtlsReliableHandshake.Message GetPendingMessage() { int num; do { num = this.mNextReceiveSeq; IDictionary dictionary = this.mCurrentInboundFlight; if (num == 0) { goto IL_49; } } while (num == 0); if (num == 0) { int num2 = this.mNextReceiveSeq; int num3 = num2 + 1; this.mNextReceiveSeq = num3; DtlsReliableHandshake.Message message; message.mMessageSeq = num2; message.mMsgType = (byte)num; return this.UpdateHandshakeMessagesDigest(message); } IL_49: throw new NullReferenceException(); } // Token: 0x06009133 RID: 37171 RVA: 0x00203420 File Offset: 0x00201620 [Token(Token = "0x6009133")] [Address(RVA = "0x1E837C0", Offset = "0x1E821C0", VA = "0x181E837C0")] private void PrepareInboundFlight(IDictionary nextFlight) { DtlsReliableHandshake.ResetAll(this.mCurrentInboundFlight); IDictionary dictionary = this.mCurrentInboundFlight; this.mPreviousInboundFlight = dictionary; this.mCurrentInboundFlight = nextFlight; } // Token: 0x06009134 RID: 37172 RVA: 0x00203450 File Offset: 0x00201650 [Token(Token = "0x6009134")] [Address(RVA = "0x1E83860", Offset = "0x1E82260", VA = "0x181E83860")] private bool ProcessRecord(int windowSize, int epoch, byte[] buf, int off, int len) { int num = TlsUtilities.ReadUint24(buf, windowSize); int num2 = TlsUtilities.ReadUint24(buf, windowSize); int num3 = TlsUtilities.ReadUint24(buf, windowSize); bool flag = num3 == 20; num2 = num3; int num4 = this.mNextReceiveSeq; if (num2 >= num4 || (this.mPreviousInboundFlight != 0 && num4 != 0)) { IDictionary dictionary = this.mCurrentInboundFlight; if (num4 == 0) { DtlsReassembler dtlsReassembler = new DtlsReassembler((byte)num3, num2); } } if (DtlsReliableHandshake.CheckAll(this.mPreviousInboundFlight)) { this.ResendOutboundFlight(); DtlsReliableHandshake.ResetAll(this.mPreviousInboundFlight); } throw new NullReferenceException(); } // Token: 0x06009135 RID: 37173 RVA: 0x002034D8 File Offset: 0x002016D8 [Token(Token = "0x6009135")] [Address(RVA = "0x1E84040", Offset = "0x1E82A40", VA = "0x181E84040")] private void ResendOutboundFlight() { int num; do { DtlsRecordLayer dtlsRecordLayer = this.mRecordLayer; IList list = this.mOutboundFlight; num = 0; num += num; num++; IList list2 = this.mOutboundFlight; uint num2; if (num < (int)num2) { num += num; num++; } if (num == 0) { num += num; num++; num += 19; num += num; num += 19; } } while (num == 0); this.WriteMessage(num); IList list3 = this.mOutboundFlight; num++; } // Token: 0x06009136 RID: 37174 RVA: 0x0020354C File Offset: 0x0020174C [Token(Token = "0x6009136")] [Address(RVA = "0x1E846B0", Offset = "0x1E830B0", VA = "0x181E846B0")] private DtlsReliableHandshake.Message UpdateHandshakeMessagesDigest(DtlsReliableHandshake.Message message) { byte[] mBody = message.mBody; byte[] array = new byte[12]; byte mMsgType = message.mMsgType; int num = 0; TlsUtilities.WriteUint8(mMsgType, array, num); TlsUtilities.WriteUint24(mBody.Length, array, 1); PngHelperInternal.WriteInt2tobytes(message.mMessageSeq, array, 4); TlsUtilities.WriteUint24(0, array, 6); TlsUtilities.WriteUint24(mBody.Length, array, 9); TlsHandshakeHash tlsHandshakeHash = this.mHandshakeHash; int length = array.Length; TlsHandshakeHash tlsHandshakeHash2 = this.mHandshakeHash; int length2 = mBody.Length; return message; } // Token: 0x06009137 RID: 37175 RVA: 0x002035D4 File Offset: 0x002017D4 [Token(Token = "0x6009137")] [Address(RVA = "0x1E849E0", Offset = "0x1E833E0", VA = "0x181E849E0")] private void WriteMessage(DtlsReliableHandshake.Message message) { int receiveLimit = this.mRecordLayer.GetReceiveLimit(); byte[] mBody = message.mBody; int num = 0; int num2 = mBody.Length; num2 -= num; int num3; this.WriteHandshakeFragment(message, num, num3); num += num3; } // Token: 0x06009138 RID: 37176 RVA: 0x00203618 File Offset: 0x00201818 [Token(Token = "0x6009138")] [Address(RVA = "0x1E84820", Offset = "0x1E83220", VA = "0x181E84820")] private void WriteHandshakeFragment(DtlsReliableHandshake.Message message, int fragment_offset, int fragment_length) { DtlsReliableHandshake.RecordLayerBuffer recordLayerBuffer; TlsUtilities.WriteUint8(message.mMsgType, recordLayerBuffer); TlsUtilities.WriteUint24(message.mBody.Length, recordLayerBuffer); int num = message.mMessageSeq; TlsUtilities.WriteUint16(num, recordLayerBuffer); TlsUtilities.WriteUint24(fragment_offset, recordLayerBuffer); TlsUtilities.WriteUint24(fragment_length, recordLayerBuffer); int num2 = recordLayerBuffer.ReadByte(); DtlsRecordLayer dtlsRecordLayer = this.mRecordLayer; bool canWrite = recordLayerBuffer.CanWrite; Platform.Dispose(recordLayerBuffer); } // Token: 0x06009139 RID: 37177 RVA: 0x00203684 File Offset: 0x00201884 [Token(Token = "0x6009139")] [Address(RVA = "0x1E83130", Offset = "0x1E81B30", VA = "0x181E83130")] private static bool CheckAll(IDictionary inboundFlight) { int num; do { num = 0; int num2 = 0; if (num2 == 0) { } if (num2 != 0) { } if (num != -1) { if (typeof(IDisposable).TypeHandle == (ulong)65L) { } if (typeof(IDisposable).TypeHandle == (ulong)63L) { break; } } } while (num != 0); return true; } // Token: 0x0600913A RID: 37178 RVA: 0x002036D8 File Offset: 0x002018D8 [Token(Token = "0x600913A")] [Address(RVA = "0x1E84240", Offset = "0x1E82C40", VA = "0x181E84240")] private static void ResetAll(IDictionary inboundFlight) { int num; do { num = 0; num += num; num++; num++; num += 19; ulong num2; num = (int)((ulong)num + num2); if (num == 0 || num == 0) { goto IL_4B; } DtlsReassembler.Range range; range.mStart = num; if (range != 0) { } if (num != -1) { } } while (num != 0); return; IL_4B: throw new NullReferenceException(); } // Token: 0x04006051 RID: 24657 [Token(Token = "0x4006051")] private const int MaxReceiveAhead = 16; // Token: 0x04006052 RID: 24658 [Token(Token = "0x4006052")] private const int MessageHeaderLength = 12; // Token: 0x04006053 RID: 24659 [global::Cpp2IlInjected.FieldOffset(Offset = "0x10")] [Token(Token = "0x4006053")] private readonly DtlsRecordLayer mRecordLayer; // Token: 0x04006054 RID: 24660 [global::Cpp2IlInjected.FieldOffset(Offset = "0x18")] [Token(Token = "0x4006054")] private TlsHandshakeHash mHandshakeHash; // Token: 0x04006055 RID: 24661 [global::Cpp2IlInjected.FieldOffset(Offset = "0x20")] [Token(Token = "0x4006055")] private IDictionary mCurrentInboundFlight; // Token: 0x04006056 RID: 24662 [global::Cpp2IlInjected.FieldOffset(Offset = "0x28")] [Token(Token = "0x4006056")] private IDictionary mPreviousInboundFlight; // Token: 0x04006057 RID: 24663 [global::Cpp2IlInjected.FieldOffset(Offset = "0x30")] [Token(Token = "0x4006057")] private IList mOutboundFlight; // Token: 0x04006058 RID: 24664 [global::Cpp2IlInjected.FieldOffset(Offset = "0x38")] [Token(Token = "0x4006058")] private bool mSending; // Token: 0x04006059 RID: 24665 [global::Cpp2IlInjected.FieldOffset(Offset = "0x3C")] [Token(Token = "0x4006059")] private int mMessageSeq; // Token: 0x0400605A RID: 24666 [global::Cpp2IlInjected.FieldOffset(Offset = "0x40")] [Token(Token = "0x400605A")] private int mNextReceiveSeq; // Token: 0x0200154D RID: 5453 [Token(Token = "0x200154D")] internal class Message { // Token: 0x0600913B RID: 37179 RVA: 0x0020373C File Offset: 0x0020193C [Token(Token = "0x600913B")] [Address(RVA = "0xC27C20", Offset = "0xC26620", VA = "0x180C27C20")] internal Message(int message_seq, byte msg_type, byte[] body) { this.mMessageSeq = message_seq; this.mMsgType = msg_type; this.mBody = body; } // Token: 0x17001769 RID: 5993 // (get) Token: 0x0600913C RID: 37180 RVA: 0x00203764 File Offset: 0x00201964 [Token(Token = "0x17001769")] public int Seq { [Token(Token = "0x600913C")] [Address(RVA = "0x3C1C50", Offset = "0x3C0650", VA = "0x1803C1C50")] get { return this.mMessageSeq; } } // Token: 0x1700176A RID: 5994 // (get) Token: 0x0600913D RID: 37181 RVA: 0x00203778 File Offset: 0x00201978 [Token(Token = "0x1700176A")] public byte Type { [Token(Token = "0x600913D")] [Address(RVA = "0x4F5380", Offset = "0x4F3D80", VA = "0x1804F5380")] get { return this.mMsgType; } } // Token: 0x1700176B RID: 5995 // (get) Token: 0x0600913E RID: 37182 RVA: 0x0020378C File Offset: 0x0020198C [Token(Token = "0x1700176B")] public byte[] Body { [Token(Token = "0x600913E")] [Address(RVA = "0x3C1240", Offset = "0x3BFC40", VA = "0x1803C1240")] get { return this.mBody; } } // Token: 0x0400605B RID: 24667 [global::Cpp2IlInjected.FieldOffset(Offset = "0x10")] [Token(Token = "0x400605B")] private readonly int mMessageSeq; // Token: 0x0400605C RID: 24668 [global::Cpp2IlInjected.FieldOffset(Offset = "0x14")] [Token(Token = "0x400605C")] private readonly byte mMsgType; // Token: 0x0400605D RID: 24669 [global::Cpp2IlInjected.FieldOffset(Offset = "0x18")] [Token(Token = "0x400605D")] private readonly byte[] mBody; } // Token: 0x0200154E RID: 5454 [Token(Token = "0x200154E")] internal class RecordLayerBuffer : MemoryStream { // Token: 0x0600913F RID: 37183 RVA: 0x002037A0 File Offset: 0x002019A0 [Token(Token = "0x600913F")] [Address(RVA = "0x1E874A0", Offset = "0x1E85EA0", VA = "0x181E874A0")] internal RecordLayerBuffer(int size) : base(size) { } // Token: 0x06009140 RID: 37184 RVA: 0x002037B4 File Offset: 0x002019B4 [Token(Token = "0x6009140")] [Address(RVA = "0x1E873E0", Offset = "0x1E85DE0", VA = "0x181E873E0")] internal void SendToRecordLayer(DtlsRecordLayer recordLayer) { bool canWrite = this.CanWrite; Platform.Dispose(this); } } // Token: 0x0200154F RID: 5455 [Token(Token = "0x200154F")] internal class Retransmit : DtlsHandshakeRetransmit { // Token: 0x06009141 RID: 37185 RVA: 0x002037D4 File Offset: 0x002019D4 [Token(Token = "0x6009141")] [Address(RVA = "0x3C3A30", Offset = "0x3C2430", VA = "0x1803C3A30")] internal Retransmit(DtlsReliableHandshake outer) { this.mOuter = outer; } // Token: 0x06009142 RID: 37186 RVA: 0x002037F0 File Offset: 0x002019F0 [Token(Token = "0x6009142")] [Address(RVA = "0x1E874B0", Offset = "0x1E85EB0", VA = "0x181E874B0", Slot = "4")] public void ReceivedHandshakeRecord(int epoch, byte[] buf, int off, int len) { DtlsReliableHandshake dtlsReliableHandshake = this.mOuter; } // Token: 0x0400605E RID: 24670 [global::Cpp2IlInjected.FieldOffset(Offset = "0x10")] [Token(Token = "0x400605E")] private readonly DtlsReliableHandshake mOuter; } } }