Esempio n. 1
0
        internal override bool SendOutgoingCommands()
        {
            if (base.peerConnectionState == ConnectionStateValue.Disconnected)
            {
                return(false);
            }
            if (!base.PhotonSocket.Connected)
            {
                return(false);
            }
            base.timeInt = SupportClass.GetTickCount() - base.timeBase;
            base.timeLastSendOutgoing = base.timeInt;
            if (base.peerConnectionState == ConnectionStateValue.Connected && Math.Abs(SupportClass.GetTickCount() - this.lastPingResult) > base.timePingInterval)
            {
                this.SendPing();
            }
            List <StreamBuffer> obj = this.outgoingStream;

            lock (obj)
            {
                for (int i = 0; i < this.outgoingStream.Count; i++)
                {
                    StreamBuffer streamBuffer = this.outgoingStream[i];
                    this.SendData(streamBuffer.GetBuffer(), streamBuffer.IntLength);
                    PeerBase.MessageBufferPoolPut(streamBuffer);
                }
                this.outgoingStream.Clear();
                base.outgoingCommandsInStream = 0;
            }
            return(false);
        }
Esempio n. 2
0
        internal override StreamBuffer SerializeOperationToMessage(byte opCode, Dictionary <byte, object> parameters, EgMessageType messageType, bool encrypt)
        {
            StreamBuffer streamBuffer = PeerBase.MessageBufferPoolGet();

            streamBuffer.SetLength(0L);
            if (!encrypt)
            {
                streamBuffer.Write(this.messageHeader, 0, this.messageHeader.Length);
            }
            base.SerializationProtocol.SerializeOperationRequest(streamBuffer, opCode, parameters, false);
            if (encrypt)
            {
                byte[] array = base.CryptoProvider.Encrypt(streamBuffer.GetBuffer(), 0, streamBuffer.IntLength);
                streamBuffer.SetLength(0L);
                streamBuffer.Write(this.messageHeader, 0, this.messageHeader.Length);
                streamBuffer.Write(array, 0, array.Length);
            }
            byte[] buffer = streamBuffer.GetBuffer();
            if (messageType != EgMessageType.Operation)
            {
                buffer[this.messageHeader.Length - 1] = (byte)messageType;
            }
            if (encrypt)
            {
                buffer[this.messageHeader.Length - 1] = (byte)(buffer[this.messageHeader.Length - 1] | 0x80);
            }
            if (this.DoFraming)
            {
                int num = 1;
                Protocol.Serialize(streamBuffer.IntLength, buffer, ref num);
            }
            return(streamBuffer);
        }
Esempio n. 3
0
        internal void SendPing()
        {
            int num = this.lastPingResult = SupportClass.GetTickCount();

            if (!this.DoFraming)
            {
                SendOptions sendOptions = new SendOptions()
                {
                    DeliveryMode = DeliveryMode.Reliable
                };
                StreamBuffer streamBuffer = this.SerializeOperationToMessage(PhotonCodes.Ping, new Dictionary <byte, object>
                {
                    {
                        (byte)1,
                        (object)num
                    }
                }, EgMessageType.InternalOperationRequest, sendOptions.Encrypt);
                if (base.TrafficStatsEnabled)
                {
                    base.TrafficStatsOutgoing.CountControlCommand(streamBuffer.IntLength);
                }
                this.SendData(streamBuffer.GetBuffer(), streamBuffer.IntLength);
                PeerBase.MessageBufferPoolPut(streamBuffer);
            }
            else
            {
                int num2 = 1;
                Protocol.Serialize(num, this.pingRequest, ref num2);
                if (base.TrafficStatsEnabled)
                {
                    base.TrafficStatsOutgoing.CountControlCommand(this.pingRequest.Length);
                }
                this.SendData(this.pingRequest, this.pingRequest.Length);
            }
        }
Esempio n. 4
0
 // Token: 0x0600B8AF RID: 47279 RVA: 0x00437D7C File Offset: 0x00435F7C
 public SocketUdp(PeerBase npeer) : base(npeer)
 {
     if (base.ReportDebugOfLevel(DebugLevel.ALL))
     {
         base.Listener.DebugReturn(DebugLevel.ALL, "CSharpSocket: UDP, Unity3d.");
     }
     this.PollReceive = false;
 }
Esempio n. 5
0
 public void FreePayload()
 {
     if (this.Payload != null)
     {
         PeerBase.MessageBufferPoolPut(this.Payload);
     }
     this.Payload = null;
 }
Esempio n. 6
0
 public IPhotonSocket(PeerBase peerBase)
 {
     if (peerBase == null)
     {
         throw new Exception("Can't init without peer");
     }
     this.peerBase = peerBase;
 }
Esempio n. 7
0
        public SocketUdpAsync(PeerBase npeer) : base(npeer)
        {
            bool flag = base.ReportDebugOfLevel(DebugLevel.INFO);

            if (flag)
            {
                base.Listener.DebugReturn(DebugLevel.INFO, "SocketUdpAsync: UDP, Unity3d.");
            }
            this.PollReceive = false;
        }
Esempio n. 8
0
 public SocketTcp(PeerBase npeer)
     : base(npeer)
 {
     if (this.ReportDebugOfLevel(DebugLevel.ALL))
     {
         this.Listener.DebugReturn(DebugLevel.ALL, "SocketTcp: TCP, DotNet, Unity.");
     }
     this.Protocol    = ConnectionProtocol.Tcp;
     this.PollReceive = false;
 }
Esempio n. 9
0
 public SocketWeb(PeerBase npeer) : base(npeer)
 {
     this.ServerAddress = npeer.ServerAddress;
     if (this.ReportDebugOfLevel(DebugLevel.INFO))
     {
         this.Listener.DebugReturn(DebugLevel.INFO, "new SocketWeb() for Unity. Server: " + this.ServerAddress);
     }
     SerializationProtocol = "GpBinaryV1" + npeer.SerializationProtocol.VersionBytes[1].ToString();
     this.PollReceive      = false;
 }
Esempio n. 10
0
 public SocketUdp(PeerBase npeer) : base(npeer)
 {
     this.syncer = new object();
     if (base.ReportDebugOfLevel(DebugLevel.ALL))
     {
         base.Listener.DebugReturn(DebugLevel.ALL, "CSharpSocket: UDP, Unity3d.");
     }
     base.Protocol    = ConnectionProtocol.Udp;
     base.PollReceive = false;
 }
Esempio n. 11
0
        public SocketUdp(PeerBase npeer) : base(npeer)
        {
            if (this.ReportDebugOfLevel(DebugLevel.ALL))
            {
                this.Listener.DebugReturn(DebugLevel.ALL, "CSharpSocket: UDP, Unity3d.");
            }

            //this.Protocol = ConnectionProtocol.Udp;
            this.PollReceive = false;
        }
Esempio n. 12
0
        public SocketTcpAsync(PeerBase npeer) : base(npeer)
        {
            bool flag = base.ReportDebugOfLevel(DebugLevel.ALL);

            if (flag)
            {
                base.Listener.DebugReturn(DebugLevel.ALL, "SocketTcpAsync: TCP, DotNet, Unity.");
            }
            this.PollReceive = false;
        }
Esempio n. 13
0
        public SocketUdpNativeDllImport(PeerBase npeer) : base(npeer)
        {
            if (this.ReportDebugOfLevel(DebugLevel.ALL))
            {
                this.Listener.DebugReturn(DebugLevel.ALL, "SocketWrapper: UDP, Unity Android Native.");
            }

            this.Protocol    = ConnectionProtocol.Udp;
            this.PollReceive = false;
        }
Esempio n. 14
0
        public IPhotonSocket(PeerBase peerBase)
        {
            bool flag = peerBase == null;

            if (flag)
            {
                throw new Exception("Can't init without peer");
            }
            this.peerBase = peerBase;
        }
Esempio n. 15
0
        public SocketWebTcp(PeerBase npeer) : base(npeer)
        {
            this.ServerAddress = npeer.ServerAddress;
            if (this.ReportDebugOfLevel(DebugLevel.INFO))
            {
                this.Listener.DebugReturn(DebugLevel.INFO, "new SocketWebTcp() for Unity. Server: " + this.ServerAddress);
            }

            //this.Protocol = ConnectionProtocol.WebSocket;
            this.PollReceive = false;
        }
Esempio n. 16
0
        public IPhotonSocket(PeerBase peerBase)
        {
            bool flag = peerBase == null;

            if (flag)
            {
                throw new Exception("Can't init without peer");
            }
            this.Protocol = peerBase.usedTransportProtocol;
            this.peerBase = peerBase;
        }
Esempio n. 17
0
 internal bool StartConnection()
 {
     if (this.isRunning)
     {
         if (this.peer.debugOut >= DebugLevel.ERROR)
         {
             this.peer.Listener.DebugReturn(DebugLevel.ERROR, "StartConnection() failed: connection still open.");
         }
         return(false);
     }
     try
     {
         this.serverEndPoint = PeerBase.GetEndpoint(this.peer.ServerAddress);
         if (this.serverEndPoint == null)
         {
             if (this.peer.debugOut >= DebugLevel.ERROR)
             {
                 this.peer.Listener.DebugReturn(DebugLevel.ERROR, "StartConnection() failed. Address must be 'address:port'. Is: " + this.peer.ServerAddress);
             }
             return(false);
         }
         this.obsolete  = false;
         this.isRunning = true;
         SocketAsyncEventArgs socketArguments = new SocketAsyncEventArgs();
         socketArguments.Completed     += new EventHandler <SocketAsyncEventArgs>(this.SocketCompletedEvent);
         socketArguments.RemoteEndPoint = this.serverEndPoint;
         byte[] udpPacketBuffer = new byte[(this.peer.mtu < 0x240) ? 0x240 : this.peer.mtu];
         socketArguments.SetBuffer(udpPacketBuffer, 0, udpPacketBuffer.Length);
         this.sock.Blocking = false;
         this.sock.Connect(this.serverEndPoint);
         this.ProcessConnect(socketArguments);
     }
     catch (SecurityException se)
     {
         if (this.peer.debugOut >= DebugLevel.ERROR)
         {
             this.peer.Listener.DebugReturn(DebugLevel.ERROR, "Connect() failed: " + se.ToString());
         }
         this.peer.Listener.OnStatusChanged(StatusCode.SecurityExceptionOnConnect);
         this.peer.Listener.OnStatusChanged(StatusCode.Disconnect);
         return(false);
     }
     catch (Exception se)
     {
         if (this.peer.debugOut >= DebugLevel.ERROR)
         {
             this.peer.Listener.DebugReturn(DebugLevel.ERROR, "Connect() failed: " + se.ToString());
         }
         this.peer.Listener.OnStatusChanged(StatusCode.ExceptionOnConnect);
         this.peer.Listener.OnStatusChanged(StatusCode.Disconnect);
         return(false);
     }
     return(true);
 }
Esempio n. 18
0
        public SocketWebTcp(PeerBase npeer) : base(npeer)
        {
            ServerAddress = npeer.ServerAddress;
            if (this.ReportDebugOfLevel(DebugLevel.INFO))
            {
                Listener.DebugReturn(DebugLevel.INFO, "new SocketWebTcp() " + ServerAddress);
            }

            Protocol    = ConnectionProtocol.Tcp;
            PollReceive = false;
        }
        public SocketWebTcpCoroutine(PeerBase npeer) : base(npeer)
        {
            if (this.ReportDebugOfLevel(DebugLevel.INFO))
            {
                Listener.DebugReturn(DebugLevel.INFO, "new SocketWebTcpCoroutine(). Server: " + this.ConnectAddress + " protocol: " + this.Protocol);
            }

            switch (this.Protocol)
            {
            case ConnectionProtocol.WebSocket:
                break;

            case ConnectionProtocol.WebSocketSecure:
                break;

            default:
                throw new Exception("Protocol '" + this.Protocol + "' not supported by WebSocket");
            }

            this.PollReceive = false;
        }
Esempio n. 20
0
 protected internal PhotonPeer(ConnectionProtocol protocolType)
 {
     this.SendOutgoingLockObject = new object();
     this.DispatchLockObject     = new object();
     this.EnqueueLock            = new object();
     if (protocolType == ConnectionProtocol.Tcp)
     {
         this.peerBase = new TPeer();
         this.peerBase.usedProtocol = protocolType;
     }
     else if (protocolType == ConnectionProtocol.Udp)
     {
         this.peerBase = new EnetPeer();
         this.peerBase.usedProtocol = protocolType;
     }
     else if (protocolType == ConnectionProtocol.RHttp)
     {
         this.peerBase = new HttpBase3();
         this.peerBase.usedProtocol = protocolType;
     }
 }
Esempio n. 21
0
 protected internal PhotonPeer(ConnectionProtocol protocolType)
 {
     if (protocolType == ConnectionProtocol.Tcp)
     {
         this.peerBase = (PeerBase) new TPeer();
         this.peerBase.usedProtocol = protocolType;
     }
     else if (protocolType == ConnectionProtocol.Udp)
     {
         this.peerBase = (PeerBase) new EnetPeer();
         this.peerBase.usedProtocol = protocolType;
     }
     else
     {
         if (protocolType != ConnectionProtocol.RHttp)
         {
             return;
         }
         this.peerBase = (PeerBase) new HttpBase3();
         this.peerBase.usedProtocol = protocolType;
     }
 }
Esempio n. 22
0
        private void CreatePeerBase()
        {
            bool flag = this.SocketImplementationConfig == null;

            if (flag)
            {
                this.SocketImplementationConfig = new Dictionary <ConnectionProtocol, Type>(5);
                this.SocketImplementationConfig.Add(ConnectionProtocol.Udp, typeof(SocketUdp));
                this.SocketImplementationConfig.Add(ConnectionProtocol.Tcp, typeof(SocketTcp));
            }
            switch (this.TransportProtocol)
            {
            case ConnectionProtocol.Tcp:
                this.peerBase = new TPeer();
                goto IL_9D;

            case ConnectionProtocol.WebSocket:
            case ConnectionProtocol.WebSocketSecure:
                this.peerBase = new TPeer
                {
                    DoFraming = false
                };
                goto IL_9D;
            }
            this.peerBase = new EnetPeer();
IL_9D:
            bool flag2 = this.peerBase == null;

            if (flag2)
            {
                throw new Exception("No PeerBase");
            }
            this.peerBase.ppeer        = this;
            this.peerBase.usedProtocol = this.TransportProtocol;
            Type socketImplementation = null;

            this.SocketImplementationConfig.TryGetValue(this.TransportProtocol, out socketImplementation);
            this.SocketImplementation = socketImplementation;
        }
Esempio n. 23
0
        internal StreamBuffer SerializeMessageToMessage(object message, bool encrypt, byte[] messageHeader, bool writeLength = true)
        {
            StreamBuffer streamBuffer = PeerBase.MessageBufferPoolGet();

            streamBuffer.SetLength(0L);
            if (!encrypt)
            {
                streamBuffer.Write(messageHeader, 0, messageHeader.Length);
            }
            if (message is byte[])
            {
                byte[] array = message as byte[];
                streamBuffer.Write(array, 0, array.Length);
            }
            else
            {
                this.SerializationProtocol.SerializeMessage(streamBuffer, message);
            }
            if (encrypt)
            {
                byte[] array2 = this.CryptoProvider.Encrypt(streamBuffer.GetBuffer(), 0, streamBuffer.IntLength);
                streamBuffer.SetLength(0L);
                streamBuffer.Write(messageHeader, 0, messageHeader.Length);
                streamBuffer.Write(array2, 0, array2.Length);
            }
            byte[] buffer = streamBuffer.GetBuffer();
            buffer[messageHeader.Length - 1] = (byte)((message is byte[]) ? 9 : 8);
            if (encrypt)
            {
                buffer[messageHeader.Length - 1] = (byte)(buffer[messageHeader.Length - 1] | 0x80);
            }
            if (writeLength)
            {
                int num = 1;
                Protocol.Serialize(streamBuffer.IntLength, buffer, ref num);
            }
            return(streamBuffer);
        }
Esempio n. 24
0
 [Preserve]         // 0x00000001800D4E50-0x00000001800D4E60
 public SocketUdp(PeerBase npeer)
 {
 }                                           // 0x0000000180A175F0-0x0000000180A176D0
Esempio n. 25
0
 [Preserve]         // 0x00000001800D4E50-0x00000001800D4E60
 public SocketUdpAsync(PeerBase npeer)
 {
 }                                                // 0x0000000180A15DF0-0x0000000180A15EB0
Esempio n. 26
0
 public void Run()
 {
     try
     {
         this.serverEndPoint = PeerBase.GetEndpoint(this.peer.ServerAddress);
         if (this.serverEndPoint == null)
         {
             if (this.peer.debugOut >= DebugLevel.ERROR)
             {
                 this.peer.Listener.DebugReturn(DebugLevel.ERROR, "StartConnection() failed. Address must be 'address:port'. Is: " + this.peer.ServerAddress);
             }
             return;
         }
         this.socketConnection.Connect(this.serverEndPoint);
     }
     catch (SecurityException se)
     {
         if (this.peer.debugOut >= DebugLevel.INFO)
         {
             this.peer.Listener.DebugReturn(DebugLevel.INFO, "Connect() failed: " + se.ToString());
         }
         if (this.socketConnection != null)
         {
             this.socketConnection.Close();
         }
         this.isRunning = false;
         this.obsolete  = true;
         this.peer.EnqueueStatusCallback(StatusCode.ExceptionOnConnect);
         this.peer.EnqueueActionForDispatch(delegate
         {
             this.peer.Disconnected();
         });
         return;
     }
     catch (SocketException se)
     {
         if (this.peer.debugOut >= DebugLevel.INFO)
         {
             this.peer.Listener.DebugReturn(DebugLevel.INFO, "Connect() failed: " + se.ToString());
         }
         if (this.socketConnection != null)
         {
             this.socketConnection.Close();
         }
         this.isRunning = false;
         this.obsolete  = true;
         this.peer.EnqueueStatusCallback(StatusCode.ExceptionOnConnect);
         this.peer.EnqueueActionForDispatch(delegate
         {
             this.peer.Disconnected();
         });
         return;
     }
     this.obsolete  = false;
     this.isRunning = true;
     while (!this.obsolete)
     {
         MemoryStream opCollectionStream = new MemoryStream(0x100);
         try
         {
             int    bytesRead = 0;
             byte[] inBuff    = new byte[9];
             while (bytesRead < 9)
             {
                 bytesRead += this.socketConnection.Receive(inBuff, bytesRead, 9 - bytesRead, SocketFlags.None);
                 if (bytesRead == 0)
                 {
                     this.peer.SendPing();
                     Thread.Sleep(100);
                 }
             }
             if (inBuff[0] == 240)
             {
                 if (this.peer.TrafficStatsEnabled)
                 {
                     this.peer.TrafficStatsIncoming.CountControlCommand(inBuff.Length);
                 }
                 if (this.peer.NetworkSimulationSettings.IsSimulationEnabled)
                 {
                     this.peer.ReceiveNetworkSimulated(delegate
                     {
                         this.peer.ReceiveIncomingCommands(inBuff, inBuff.Length);
                     });
                 }
                 else
                 {
                     this.peer.ReceiveIncomingCommands(inBuff, inBuff.Length);
                 }
                 continue;
             }
             int length = (((inBuff[1] << 0x18) | (inBuff[2] << 0x10)) | (inBuff[3] << 8)) | inBuff[4];
             if (this.peer.TrafficStatsEnabled)
             {
                 if (inBuff[5] == 0)
                 {
                     this.peer.TrafficStatsIncoming.CountReliableOpCommand(length);
                 }
                 else
                 {
                     this.peer.TrafficStatsIncoming.CountUnreliableOpCommand(length);
                 }
             }
             if (this.peer.debugOut >= DebugLevel.ALL)
             {
                 this.peer.EnqueueDebugReturn(DebugLevel.ALL, "message length: " + length);
             }
             opCollectionStream.Write(inBuff, 7, bytesRead - 7);
             bytesRead = 0;
             length   -= 9;
             inBuff    = new byte[length];
             while (bytesRead < length)
             {
                 bytesRead += this.socketConnection.Receive(inBuff, bytesRead, length - bytesRead, SocketFlags.None);
             }
             opCollectionStream.Write(inBuff, 0, bytesRead);
             if (opCollectionStream.Length > 0L)
             {
                 if (this.peer.NetworkSimulationSettings.IsSimulationEnabled)
                 {
                     this.peer.ReceiveNetworkSimulated(delegate
                     {
                         this.peer.ReceiveIncomingCommands(opCollectionStream.ToArray(), (int)opCollectionStream.Length);
                     });
                 }
                 else
                 {
                     this.peer.ReceiveIncomingCommands(opCollectionStream.ToArray(), (int)opCollectionStream.Length);
                 }
             }
             if (this.peer.debugOut >= DebugLevel.ALL)
             {
                 this.peer.EnqueueDebugReturn(DebugLevel.ALL, "TCP < " + opCollectionStream.Length);
             }
         }
         catch (SocketException e)
         {
             if (!this.obsolete)
             {
                 this.obsolete = true;
                 if (this.peer.debugOut >= DebugLevel.ERROR)
                 {
                     this.peer.EnqueueDebugReturn(DebugLevel.ERROR, "Receiving failed. SocketException: " + e.SocketErrorCode);
                 }
                 switch (e.SocketErrorCode)
                 {
                 case SocketError.ConnectionAborted:
                 case SocketError.ConnectionReset:
                     this.peer.EnqueueStatusCallback(StatusCode.DisconnectByServer);
                     continue;
                 }
                 this.peer.EnqueueStatusCallback(StatusCode.Exception);
             }
         }
         catch (Exception e)
         {
             if (!this.obsolete && (this.peer.debugOut >= DebugLevel.ERROR))
             {
                 this.peer.EnqueueDebugReturn(DebugLevel.ERROR, "Receiving failed. Exception: " + e.ToString());
             }
         }
     }
     if (this.socketConnection != null)
     {
         this.socketConnection.Close();
     }
     this.isRunning = false;
     this.obsolete  = true;
     this.peer.EnqueueActionForDispatch(delegate
     {
         this.peer.Disconnected();
     });
 }
Esempio n. 27
0
 [Preserve]         // 0x00000001800D4E50-0x00000001800D4E60
 public SocketNative(PeerBase npeer)
 {
 }                                              // 0x0000000180A0FCD0-0x0000000180A0FE90
Esempio n. 28
0
        internal NCommand(EnetPeer peer, byte[] inBuff, ref int readingOffset)
        {
            this.commandType      = inBuff[readingOffset++];
            this.commandChannelID = inBuff[readingOffset++];
            this.commandFlags     = inBuff[readingOffset++];
            this.reservedByte     = inBuff[readingOffset++];
            Protocol.Deserialize(out this.Size, inBuff, ref readingOffset);
            Protocol.Deserialize(out this.reliableSequenceNumber, inBuff, ref readingOffset);
            peer.bytesIn += this.Size;
            int num = 0;

            switch (this.commandType)
            {
            case 1:
            case 16:
                Protocol.Deserialize(out this.ackReceivedReliableSequenceNumber, inBuff, ref readingOffset);
                Protocol.Deserialize(out this.ackReceivedSentTime, inBuff, ref readingOffset);
                break;

            case 6:
            case 14:
                num = this.Size - 12;
                break;

            case 7:
                Protocol.Deserialize(out this.unreliableSequenceNumber, inBuff, ref readingOffset);
                num = this.Size - 16;
                break;

            case 11:
                Protocol.Deserialize(out this.unsequencedGroupNumber, inBuff, ref readingOffset);
                num = this.Size - 16;
                break;

            case 8:
            case 15:
                Protocol.Deserialize(out this.startSequenceNumber, inBuff, ref readingOffset);
                Protocol.Deserialize(out this.fragmentCount, inBuff, ref readingOffset);
                Protocol.Deserialize(out this.fragmentNumber, inBuff, ref readingOffset);
                Protocol.Deserialize(out this.totalLength, inBuff, ref readingOffset);
                Protocol.Deserialize(out this.fragmentOffset, inBuff, ref readingOffset);
                num = this.Size - 32;
                this.fragmentsRemaining = this.fragmentCount;
                break;

            case 3:
            {
                short peerID = default(short);
                Protocol.Deserialize(out peerID, inBuff, ref readingOffset);
                readingOffset += 30;
                if (peer.peerID == -1 || peer.peerID == -2)
                {
                    peer.peerID = peerID;
                }
                break;
            }
            }
            if (num != 0)
            {
                StreamBuffer streamBuffer = PeerBase.MessageBufferPoolGet();
                streamBuffer.Write(inBuff, readingOffset, num);
                this.Payload             = streamBuffer;
                this.Payload.IntPosition = 0;
                readingOffset           += num;
            }
        }
Esempio n. 29
0
 public SocketUdpNativeStatic(PeerBase peerBase) : base(peerBase)
 {
 }
 public SocketUdpNativeDynamic(PeerBase peerBase) : base(peerBase)
 {
 }