示例#1
0
        internal static void Send(TcpState e)
        {
            var      startMsg  = new StartMsg();
            PoolTask poolCache = GetFreeMinerTask();

            var startCmd = PoolCommand.CreateCommand(CommandNames.Start, poolCache.CurrentStartMsg);
        }
示例#2
0
        //===================// Methods //===================//

        /**
         * Method: SendPoolCommand
         * Access: public
         * Description: Receive Commands from Interfaces and pass to S+ via TriggerSendCommand delegate
         */
        public void SendPoolCommand(PoolCommand _cmd, ushort _state, string _text)
        {
            if (TriggerSendCommand != null)
            {
                TriggerSendCommand((ushort)_cmd, _state, _text);
            }
        }
示例#3
0
        internal static void Receive(TcpReceiveState e, PoolCommand cmd)
        {
            var msg   = new NonceDataMsg();
            int index = 0;

            msg.Deserialize(cmd.Payload, ref index);

            var miner = PoolCache.WorkingMiners.FirstOrDefault(m => m.ClientAddress == e.Address);

            if (miner == null)
            {
                RejectCommand.Send(e);
                return;
            }

            var data = POC.CalculateScoopData(miner.WalletAddress, msg.MaxNonce, miner.CheckScoopNumber);

            if (Base16.Encode(data) == Base16.Encode(msg.ScoopData))
            {
                miner.IsConnected         = true;
                miner.ConnectedTime       = Time.EpochTime;
                miner.LatestHeartbeatTime = Time.EpochTime;
                LoginCommand.SendLoginResult(e, true);
                LogHelper.Info(miner.ClientAddress + " login success");

                StartCommand.Send(e);
            }
            else
            {
                LoginCommand.SendLoginResult(e, false);
                RejectCommand.Send(e);
                LogHelper.Info(miner.ClientAddress + " login fail");
            }
        }
示例#4
0
        internal static void Send(TcpState e, StartMsg startMsg)
        {
            var startCmd = PoolCommand.CreateCommand(CommandNames.Start, startMsg);

            if (PoolJob.TcpServer != null)
            {
                PoolJob.TcpServer.SendCommand(e, startCmd);
            }
        }
示例#5
0
 internal static void SendLoginResult(TcpState e, bool result)
 {
     if (PoolJob.TcpServer != null)
     {
         var msg = new LoginResultMsg();
         msg.Result = result;
         var cmd = PoolCommand.CreateCommand(CommandNames.LoginResult, msg);
         PoolJob.TcpServer.SendCommand(e, cmd);
     }
 }
示例#6
0
        /// <summary>
        /// 发送Reject命令
        /// 创建命令,发送命令,关闭连接
        /// </summary>
        /// <param name="e"></param>
        internal static void Send(TcpState e)
        {
            var rejectCmd = PoolCommand.CreateCommand(CommandNames.Reject, null);

            if (PoolJob.TcpServer != null)
            {
                PoolJob.TcpServer.SendCommand(e, rejectCmd);
                PoolJob.TcpServer.CloseSocket(e);
            }
        }
示例#7
0
 public void SendCommand(AsyncSocketUserToken token, PoolCommand command)
 {
     try
     {
         var buffer = command.GetBytes();
         this.SendAsyncEvent(token.ConnectSocket, token.SendEventArgs, buffer, 0, buffer.Length);
     }
     catch (Exception ex)
     {
         LogHelper.Error(ex.Message, ex);
         this.CloseSocket(token);
     }
 }
示例#8
0
        public void SendCommand(TcpState state, PoolCommand command)
        {
            tcpClientSend.Set();
            try
            {
                var buffer = command.GetBytes();
                state.Stream.BeginWrite(buffer, 0, buffer.Length, new AsyncCallback(processSend), state);
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex.Message, ex);
                this.CloseSocket(state);
            }

            tcpClientSend.WaitOne();
        }
示例#9
0
        private void receivedCommand(TcpReceiveState state, PoolCommand cmd)
        {
            switch (cmd.CommandName)
            {
            case CommandNames.Login:
                Commands.LoginCommand.Receive(state, cmd);
                break;

            case CommandNames.NonceData:
                Commands.NonceDataCommand.Receive(state, cmd);
                break;

            case CommandNames.ScoopData:
                Commands.ScoopDataCommand.Received(state, cmd);
                break;

            case CommandNames.Heartbeat:
                Commands.HeartbeatCommand.Receive(state, cmd);
                break;

            default:
                break;
            }
        }
示例#10
0
        internal static void Received(TcpReceiveState e, PoolCommand cmd)
        {
            var miner = PoolCache.WorkingMiners.FirstOrDefault(m => m.ClientAddress == e.Address && m.IsConnected);

            if (miner == null)
            {
                LogHelper.Info("Received invalid scoop data from " + e.Address);
                LogHelper.Info("Miner logout");
                PoolJob.TcpServer.CloseSocket(e);
                return;
            }

            if (PoolCache.CurrentTask == null || PoolCache.CurrentTask.State != MiningState.Mining)
            {
                return;
            }

            var msg   = new ScoopDataMsg();
            int index = 0;

            msg.Deserialize(cmd.Payload, ref index);


            PoolCache.CurrentTask.LastReceiveTime = Time.EpochTime;

            var minerinfo = PoolCache.CurrentTask.MinerEfforts.FirstOrDefault(x => x.Account == miner.WalletAddress);

            if (minerinfo == null)
            {
                PoolCache.CurrentTask.MinerEfforts.Add(new Models.MinerEffort {
                    Account = miner.WalletAddress, Effort = 1
                });
            }
            else
            {
                if (minerinfo.Effort == Setting.MaxNonceCount)
                {
                    RejectCommand.Send(e);
                    return;
                }
                minerinfo.Effort++;
            }

            if (msg.BlockHeight != PoolCache.CurrentTask.CurrentBlockHeight)
            {
                LogHelper.Info("Received invalid scoop data from " + e.Address + ", nonce is " + msg.Nonce + ", height is " + msg.BlockHeight);
                LogHelper.Info("Block Height invalid , Stop and Send StartMsg");

                var stopMsg = new StopMsg
                {
                    BlockHeight = msg.BlockHeight,
                    Result      = false,
                    StartTime   = Time.EpochTime,
                    StopTime    = Time.EpochTime
                };
                StopCommand.Send(e, stopMsg);
                Task.Delay(1000).Wait();
                var startMsg = PoolCache.CurrentTask.CurrentStartMsg;
                if (startMsg != null)
                {
                    StartCommand.Send(e, startMsg);
                }
                return;
            }

            LogHelper.Info("Received scoop data from " + miner.ClientAddress + ", nonce is " + msg.Nonce + ", scoop number is " + msg.ScoopNumber + ", block height is " + msg.BlockHeight);

            if (msg.ScoopNumber != PoolCache.CurrentTask.CurrentScoopNumber)
            {
                LogHelper.Info("Received invalid scoop data from " + e.Address + ", nonce is " + msg.Nonce + ", ScoopNumber is " + PoolCache.CurrentTask.CurrentScoopNumber + "/" + msg.ScoopNumber);
                LogHelper.Info("Scoop Number invalid");
                return;
            }

            var verResult = POC.Verify(PoolCache.CurrentTask.BaseTarget, msg.Target);

            LogHelper.Debug("Bits:" + POC.ConvertBitsToBigInt(PoolCache.CurrentTask.BaseTarget).ToString("X").PadLeft(64, '0'));
            LogHelper.Debug("Hash:" + Base16.Encode(msg.Target));
            LogHelper.Debug("Verify Result is " + verResult);

            if (!verResult)
            {
                return;
            }

            ForgeMsg forgeMsg = new ForgeMsg();

            forgeMsg.Account    = msg.WalletAddress;
            forgeMsg.Nonce      = msg.Nonce;
            forgeMsg.StartMsgId = PoolCache.CurrentTask.Id;

            //MQApi.SendForgeBlock(msg.WalletAddress, msg.Nonce, PoolCache.CurrentTask.Id);
            RabbitMQApi.SendForgeBlock(msg.WalletAddress, msg.Nonce, PoolCache.CurrentTask.Id);
        }
示例#11
0
        /**
         * Method: FeedbackEvent
         * Access: public
         * Description: Receive hardware feedback from S+, store in variable, and push value to subscribed Interfaces via event
         */
        public void FeedbackEvent(ushort _action, ushort _state, string _text)
        {
            PoolCommand act = (PoolCommand)_action;

            switch (act)
            {
            case PoolCommand.ModeSelect_Pool_Fb:
                if (_state == 1)
                {
                    currentMode = PoolMode.Pool;
                }
                break;

            case PoolCommand.ModeSelect_Spa_Fb:
                if (_state == 1)
                {
                    currentMode = PoolMode.Spa;
                }
                break;

            case PoolCommand.Pool_Heater_Fb:
                poolHeaterOn = _state == 1 ? true : false;
                break;

            case PoolCommand.Spa_Heater_Fb:
                spaHeaterOn = _state == 1 ? true : false;
                break;

            case PoolCommand.FilterPump_Fb:
                filterPumpOn = _state == 1 ? true : false;
                break;

            case PoolCommand.Aux_Fb:
                currentAuxStatus[int.Parse(_text)] = _state == 1 ? true : false;
                break;

            case PoolCommand.Pool_Setpoint_Fb:
                currentPoolSetpoint = float.Parse(_text);
                break;

            case PoolCommand.Pool_Temp_Fb:
                currentPoolTemp = float.Parse(_text);;
                break;

            case PoolCommand.Spa_Setpoint_Fb:
                currentSpaSetpoint = float.Parse(_text);;
                break;

            case PoolCommand.Spa_Temp_Fb:
                currentSpaTemp = float.Parse(_text);;
                break;

            case PoolCommand.Ambient_Temp_Fb:
                currentAmbientTemp = float.Parse(_text);;
                break;

            case PoolCommand.System_Type:
                systemType = _state;
                break;
            }

            // Broadcast to UpdateEvent subscribers
            if (this.UpdateEvent != null)
            {
                UpdateEvent(act, _state, _text);
            }
        }
示例#12
0
        private void processReceive(IAsyncResult ar)
        {
            TcpReceiveState state = (TcpReceiveState)ar.AsyncState;

            try
            {
                //if (state.Stream == null || !state.Stream.CanRead)
                //{
                //    state.Buffer = new byte[m_receiveBufferSize];
                //    state.Stream.BeginRead(state.Buffer, 0, state.Buffer.Length, new AsyncCallback(processReceive), state);
                //}

                int numberOfBytesRead = state.Stream.EndRead(ar);

                if (numberOfBytesRead > 0)
                {
                    //LogHelper.Debug($"Readed {numberOfBytesRead} byte data from {state.Address}");
                    var buffer = new byte[numberOfBytesRead];
                    Array.Copy(state.Buffer, 0, buffer, 0, buffer.Length);
                    //this.receivedDataQueue.Enqueue(new KeyValuePair<TcpReceiveState, byte[]>(state, buffer));
                    var         commandDataList = new List <byte[]>();
                    var         index           = 0;
                    List <byte> bytes           = null;

                    while (index < buffer.Length)
                    {
                        if (bytes == null)
                        {
                            if ((index + 3) < buffer.Length &&
                                buffer[index] == PoolCommand.DefaultPrefixBytes[0] &&
                                buffer[index + 1] == PoolCommand.DefaultPrefixBytes[1] &&
                                buffer[index + 2] == PoolCommand.DefaultPrefixBytes[2] &&
                                buffer[index + 3] == PoolCommand.DefaultPrefixBytes[3])
                            {
                                bytes = new List <byte>();
                                bytes.AddRange(PoolCommand.DefaultPrefixBytes);
                                index += 4;
                            }
                            else
                            {
                                index++;
                            }
                        }
                        else
                        {
                            if ((index + 3) < buffer.Length &&
                                buffer[index] == PoolCommand.DefaultSuffixBytes[0] &&
                                buffer[index + 1] == PoolCommand.DefaultSuffixBytes[1] &&
                                buffer[index + 2] == PoolCommand.DefaultSuffixBytes[2] &&
                                buffer[index + 3] == PoolCommand.DefaultSuffixBytes[3])
                            {
                                bytes.AddRange(PoolCommand.DefaultSuffixBytes);
                                commandDataList.Add(bytes.ToArray());
                                bytes = null;

                                index += 4;
                            }
                            else
                            {
                                bytes.Add(buffer[index]);
                                index++;
                            }
                        }
                    }

                    if (this.ReceivedCommandAction != null)
                    {
                        foreach (var data in commandDataList)
                        {
                            try
                            {
                                var cmd = PoolCommand.ConvertBytesToMessage(data);
                                if (cmd != null)
                                {
                                    HeartbeatCommand.UpdateHeartTime(state);
                                    this.ReceivedCommandAction(state, cmd);
                                }
                            }
                            catch (Exception ex)
                            {
                                LogHelper.Error("Error occured on deserialize messgae: " + ex.Message, ex);
                            }
                        }
                    }
                }

                state.Buffer = new byte[m_receiveBufferSize];
                state.Stream.BeginRead(state.Buffer, 0, state.Buffer.Length,
                                       new AsyncCallback(processReceive), state);
            }
            catch (Exception ex)
            {
                LogHelper.Error("Error occured on receive messgae: " + ex.Message, ex);
                this.CloseSocket(state);
            }
        }
示例#13
0
        /// <summary>
        /// 接收消息
        /// </summary>
        /// <param name="e"></param>
        /// <param name="cmd"></param>
        internal static void Receive(TcpReceiveState e, PoolCommand cmd)
        {
            //TaskWork.Current.Add(new Task(() =>
            //{
            var loginMsg = new LoginMsg();
            int index    = 0;

            loginMsg.Deserialize(cmd.Payload, ref index);
            //验证矿工身份
            if (!MinerApi.ValidateMiner(loginMsg.WalletAddress, loginMsg.SerialNo))
            {
                RejectCommand.Send(e);
                return;
            }

            //TODO: address and SerialNo and account only for one Minner 第一个与条件匹配的矿工
            var miner = PoolCache.WorkingMiners.FirstOrDefault(m => m.WalletAddress == loginMsg.WalletAddress || m.ClientAddress == e.Address || m.SerialNo == loginMsg.SerialNo);

            //矿工不为空,发送stop命令
            if (miner != null)
            {
                StopMsg stopMsg = new StopMsg();
                stopMsg.Result = false;
                if (PoolCache.CurrentTask == null)
                {
                    return;
                }
                stopMsg.BlockHeight = PoolCache.CurrentTask.CurrentBlockHeight;
                stopMsg.StartTime   = PoolCache.CurrentTask.StartTime;
                stopMsg.StopTime    = Time.EpochTime;

                TcpSendState tcpSendState = new TcpSendState()
                {
                    Client = miner.Client, Stream = miner.Stream, Address = miner.ClientAddress
                };
                StopCommand.Send(tcpSendState, stopMsg);

                PoolCache.WorkingMiners.Remove(miner);
            }

            miner               = new Miner();
            miner.SerialNo      = loginMsg.SerialNo;
            miner.WalletAddress = loginMsg.WalletAddress;
            miner.ClientAddress = e.Address;
            miner.Client        = e.Client;
            miner.Stream        = e.Stream;

            Random random = new Random();

            miner.CheckScoopNumber = random.Next(0, POC.MAX_SCOOP_NUMBER + 1);
            PoolCache.WorkingMiners.Add(miner);

            miner.IsConnected         = true;
            miner.ConnectedTime       = Time.EpochTime;
            miner.LatestHeartbeatTime = Time.EpochTime;
            SendLoginResult(e, true);
            LogHelper.Info(miner.ClientAddress + " login success");

            MinerLoginMsg loginMinerMsg = new MinerLoginMsg();

            loginMinerMsg.Account  = loginMsg.WalletAddress;
            loginMinerMsg.SN       = loginMsg.SerialNo;
            loginMinerMsg.ServerId = Setting.PoolId;

            //MQApi.Current.SendLoginMsg(loginMinerMsg);
            RabbitMQApi.Current.SendLoginMsg(loginMinerMsg);
            if (PoolCache.CurrentTask != null)
            {
                StartCommand.Send(e, PoolCache.CurrentTask.CurrentStartMsg);
            }
            //}));
        }
示例#14
0
        internal void Start()
        {
            isStart = true;
            Task.Run(() =>
            {
                while (isStart)
                {
                    if (RunningTasks.Count < MaxTaskCount)
                    {
                        DataInfo analysisDataInfo;
                        if (analysisDataIds.TryDequeue(out analysisDataInfo))
                        {
                            Task task = new Task(() =>
                            {
                                var analysisData    = DbHelper.Current.Get <byte[]>(DataType.ReceiveType, analysisDataInfo.ID);
                                var state           = analysisDataInfo.State;
                                var buffer          = analysisData;
                                var commandDataList = new List <byte[]>();
                                var index           = 0;
                                List <byte> bytes   = null;

                                while (index < buffer.Length)
                                {
                                    if (bytes == null)
                                    {
                                        if ((index + 3) < buffer.Length &&
                                            buffer[index] == PoolCommand.DefaultPrefixBytes[0] &&
                                            buffer[index + 1] == PoolCommand.DefaultPrefixBytes[1] &&
                                            buffer[index + 2] == PoolCommand.DefaultPrefixBytes[2] &&
                                            buffer[index + 3] == PoolCommand.DefaultPrefixBytes[3])
                                        {
                                            bytes = new List <byte>();
                                            bytes.AddRange(PoolCommand.DefaultPrefixBytes);
                                            index += 4;
                                        }
                                        else
                                        {
                                            index++;
                                        }
                                    }
                                    else
                                    {
                                        if ((index + 3) < buffer.Length &&
                                            buffer[index] == PoolCommand.DefaultSuffixBytes[0] &&
                                            buffer[index + 1] == PoolCommand.DefaultSuffixBytes[1] &&
                                            buffer[index + 2] == PoolCommand.DefaultSuffixBytes[2] &&
                                            buffer[index + 3] == PoolCommand.DefaultSuffixBytes[3])
                                        {
                                            bytes.AddRange(PoolCommand.DefaultSuffixBytes);
                                            commandDataList.Add(bytes.ToArray());
                                            bytes = null;

                                            index += 4;
                                        }
                                        else
                                        {
                                            bytes.Add(buffer[index]);
                                            index++;
                                        }
                                    }
                                }

                                foreach (var data in commandDataList)
                                {
                                    try
                                    {
                                        var cmd = PoolCommand.ConvertBytesToMessage(data);
                                        if (cmd != null)
                                        {
                                            MsgPool.Current.AddCommand(new CommandState {
                                                State = state, Command = cmd
                                            });
                                        }
                                    }
                                    catch (Exception ex)
                                    {
                                        LogHelper.Error("Error occured on deserialize messgae: " + ex.Message, ex);
                                    }
                                }
                            });
                            task.ContinueWith(t =>
                            {
                                RunningTasks.Remove(task);
                            });
                            RunningTasks.Add(task);
                            task.Start();
                        }
                    }
                }
            });
        }
示例#15
0
        private void processReceivedDataQueue()
        {
            while (isStarted)
            {
                if (this.receivedDataQueue.Count > 0)
                {
                    var item = receivedDataQueue.Dequeue();

                    Task.Run(() => {
                        var state           = item.Key;
                        var buffer          = item.Value;
                        var commandDataList = new List <byte[]>();
                        var index           = 0;
                        List <byte> bytes   = null;

                        while (index < buffer.Length)
                        {
                            if (bytes == null)
                            {
                                if ((index + 3) < buffer.Length &&
                                    buffer[index] == PoolCommand.DefaultPrefixBytes[0] &&
                                    buffer[index + 1] == PoolCommand.DefaultPrefixBytes[1] &&
                                    buffer[index + 2] == PoolCommand.DefaultPrefixBytes[2] &&
                                    buffer[index + 3] == PoolCommand.DefaultPrefixBytes[3])
                                {
                                    bytes = new List <byte>();
                                    bytes.AddRange(PoolCommand.DefaultPrefixBytes);
                                    index += 4;
                                }
                                else
                                {
                                    index++;
                                }
                            }
                            else
                            {
                                if ((index + 3) < buffer.Length &&
                                    buffer[index] == PoolCommand.DefaultSuffixBytes[0] &&
                                    buffer[index + 1] == PoolCommand.DefaultSuffixBytes[1] &&
                                    buffer[index + 2] == PoolCommand.DefaultSuffixBytes[2] &&
                                    buffer[index + 3] == PoolCommand.DefaultSuffixBytes[3])
                                {
                                    bytes.AddRange(PoolCommand.DefaultSuffixBytes);
                                    commandDataList.Add(bytes.ToArray());
                                    bytes = null;

                                    index += 4;
                                }
                                else
                                {
                                    bytes.Add(buffer[index]);
                                    index++;
                                }
                            }
                        }

                        if (this.ReceivedCommandAction != null)
                        {
                            foreach (var data in commandDataList)
                            {
                                try
                                {
                                    var cmd = PoolCommand.ConvertBytesToMessage(data);
                                    if (cmd != null)
                                    {
                                        HeartbeatCommand.UpdateHeartTime(state);
                                        this.ReceivedCommandAction(state, cmd);
                                    }
                                }
                                catch (Exception ex)
                                {
                                    LogHelper.Error("Error occured on deserialize messgae: " + ex.Message, ex);
                                }
                            }
                        }
                    });
                }
            }
        }
示例#16
0
        /// <summary>
        /// 接收事件响应函数,接收的逻辑
        /// </summary>
        /// <param name="receiveEventArgs"></param>
        private void ProcessReceive(SocketAsyncEventArgs receiveEventArgs)
        {
            AsyncSocketUserToken userToken = receiveEventArgs.UserToken as AsyncSocketUserToken;

            if (userToken.ConnectSocket == null)
            {
                return;
            }
            userToken.ActiveDateTime = DateTime.Now;
            if (userToken.ReceiveEventArgs.BytesTransferred > 0 && userToken.ReceiveEventArgs.SocketError == SocketError.Success)
            {
                HeartbeatCommand.UpdateHeartTime(userToken);

                int offset = userToken.ReceiveEventArgs.Offset;
                int count  = userToken.ReceiveEventArgs.BytesTransferred;

                if (count > 0) //处理接收数据
                {
                    var         buffer          = userToken.ReceiveEventArgs.Buffer;
                    var         commandDataList = new List <byte[]>();
                    var         index           = 0;
                    List <byte> bytes           = null;

                    while (index < buffer.Length)
                    {
                        if (bytes == null)
                        {
                            if ((index + 3) < buffer.Length &&
                                buffer[index] == PoolCommand.DefaultPrefixBytes[0] &&
                                buffer[index + 1] == PoolCommand.DefaultPrefixBytes[1] &&
                                buffer[index + 2] == PoolCommand.DefaultPrefixBytes[2] &&
                                buffer[index + 3] == PoolCommand.DefaultPrefixBytes[3])
                            {
                                bytes = new List <byte>();
                                bytes.AddRange(PoolCommand.DefaultPrefixBytes);
                                index += 4;
                            }
                            else
                            {
                                index++;
                            }
                        }
                        else
                        {
                            if ((index + 3) < buffer.Length &&
                                buffer[index] == PoolCommand.DefaultSuffixBytes[0] &&
                                buffer[index + 1] == PoolCommand.DefaultSuffixBytes[1] &&
                                buffer[index + 2] == PoolCommand.DefaultSuffixBytes[2] &&
                                buffer[index + 3] == PoolCommand.DefaultSuffixBytes[3])
                            {
                                bytes.AddRange(PoolCommand.DefaultSuffixBytes);
                                commandDataList.Add(bytes.ToArray());
                                bytes = null;

                                index += 4;
                            }
                            else
                            {
                                bytes.Add(buffer[index]);
                                index++;
                            }
                        }
                    }

                    if (this.ReceivedCommandAction != null)
                    {
                        foreach (var data in commandDataList)
                        {
                            try
                            {
                                var cmd = PoolCommand.ConvertBytesToMessage(data);
                                if (cmd != null)
                                {
                                    this.ReceivedCommandAction(userToken, cmd);
                                }
                            }
                            catch (Exception ex)
                            {
                                LogHelper.Warn($"Error Data from {userToken.Address}:{Base16.Encode(data)}");
                                LogHelper.Error("Error occured on deserialize messgae: " + ex.Message, ex);
                            }
                        }
                    }

                    if (userToken.ConnectSocket == null || userToken.ReceiveEventArgs == null)
                    {
                        return;
                    }

                    bool willRaiseEvent = userToken.ConnectSocket.ReceiveAsync(userToken.ReceiveEventArgs); //投递接收请求
                    if (!willRaiseEvent)
                    {
                        ProcessReceive(userToken.ReceiveEventArgs);
                    }
                }
                else
                {
                    CloseSocket(userToken);
                }
            }
        }
示例#17
0
 internal static void Receive(TcpReceiveState e, PoolCommand cmd)
 {
     UpdateHeartTime(e);
 }