public void Handle(ClientRequestHandler handler) { try { AL2POS_Domain request = null; bool doMac = true; AL2POS_Domain response = null; byte[] responseArr = null; log.Debug(m => m("[State_AutoLoadQuery] {0} Request(ASCII):{1}", handler.ClientSocket.RemoteEndPoint.ToString(), ClientRequestHandler.asciiOctets2String(handler.Request))); //1.驗證Mac if (this.CheckMac(CheckMacContainer.ALQReqMsgUtility,handler.Request)) { //2.parse request request = this.ParseRequest(CheckMacContainer.ALQReqMsgUtility,handler.Request); //3.send to Back-End request and get response response = this.GetResponse(request); if (response == null) { //back-End Error response = new AL2POS_Domain() { AL2POS_SN = "99999999", AL2POS_RC = "990001" }; } } else { //MAC驗證失敗 doMac = false; response = new AL2POS_Domain() { AL2POS_SN = "99999999", AL2POS_RC = "990007" }; } //4. parse response byte array(create mac) responseArr = this.ParseResponse(CheckMacContainer.ALQRespMsgUtility,response, handler.Request, doMac); log.Info(m => m("Response(length:{0}):{1}", responseArr.Length, BitConverter.ToString(responseArr).Replace("-", ""))); int sendLength = handler.ClientSocket.Send(responseArr); if (sendLength != responseArr.Length) { log.Error(m => m("Response[length:{0}] not equal Actual Send Response[Length:{1}]", responseArr.Length, sendLength)); } } catch (SocketException sckEx) { log.Error(m => m("[State_AutoLoadQuery][Handle] Socket Error: {0} \r\n{1}", sckEx.Message, sckEx.StackTrace)); } catch (Exception ex) { log.Error(m => m("[State_AutoLoadQuery][Handle] Error: {0} \r\n{1}", ex.Message, ex.StackTrace)); } finally { handler.ServiceState = new State_Exit(); } }
/// <summary> /// Sends a command request to the service. /// </summary> /// <param name="clientID">Client ID of sender.</param> /// <param name="userInput">Request string.</param> public void SendRequest(Guid clientID, string userInput) { ClientRequest request = ClientRequest.Parse(userInput); if ((object)request != null) { ClientRequestHandler requestHandler = ServiceHelper.FindClientRequestHandler(request.Command); if (SecurityProviderUtility.IsResourceSecurable(request.Command) && !SecurityProviderUtility.IsResourceAccessible(request.Command, Thread.CurrentPrincipal)) { ServiceHelper.UpdateStatus(clientID, UpdateType.Alarm, $"Access to \"{request.Command}\" is denied.\r\n\r\n"); return; } if ((object)requestHandler != null) { requestHandler.HandlerMethod(new ClientRequestInfo(new ClientInfo { ClientID = clientID }, request)); } else { ServiceHelper.UpdateStatus(clientID, UpdateType.Alarm, $"Command \"{request.Command}\" is not supported.\r\n\r\n"); } } }
public void Handle(ClientRequestHandler handler) { try { AL2POS_Domain request = null; bool doMac = true; AL2POS_Domain response = null; byte[] responseArr = null; log.Debug(m => m("[State_AutoLoadQuery] {0} Request(ASCII):{1}", handler.ClientSocket.RemoteEndPoint.ToString(), ClientRequestHandler.asciiOctets2String(handler.Request))); //1.驗證Mac if (this.CheckMac(CheckMacContainer.ALQReqMsgUtility, handler.Request)) { //2.parse request request = this.ParseRequest(CheckMacContainer.ALQReqMsgUtility, handler.Request); //3.send to Back-End request and get response response = this.GetResponse(request); if (response == null) { //back-End Error response = new AL2POS_Domain() { AL2POS_SN = "99999999", AL2POS_RC = "990001" }; } } else { //MAC驗證失敗 doMac = false; response = new AL2POS_Domain() { AL2POS_SN = "99999999", AL2POS_RC = "990007" }; } //4. parse response byte array(create mac) responseArr = this.ParseResponse(CheckMacContainer.ALQRespMsgUtility, response, handler.Request, doMac); log.Info(m => m("Response(length:{0}):{1}", responseArr.Length, BitConverter.ToString(responseArr).Replace("-", ""))); int sendLength = handler.ClientSocket.Send(responseArr); if (sendLength != responseArr.Length) { log.Error(m => m("Response[length:{0}] not equal Actual Send Response[Length:{1}]", responseArr.Length, sendLength)); } } catch (SocketException sckEx) { log.Error(m => m("[State_AutoLoadQuery][Handle] Socket Error: {0} \r\n{1}", sckEx.Message, sckEx.StackTrace)); } catch (Exception ex) { log.Error(m => m("[State_AutoLoadQuery][Handle] Error: {0} \r\n{1}", ex.Message, ex.StackTrace)); } finally { handler.ServiceState = new State_Exit(); } }
private void ThreadProc(object obj) { //TeamlabDocService service = (TeamlabDocService) obj; // load configuration // start task manager mTaskManager = new TaskManager(); mRequestHandler = new ClientRequestHandler(mTaskManager); // start monitors int nPort = Int32.Parse(ConfigurationSettings.AppSettings["port"]); // tcp port number - loaded from configuration // start ipc server ServiceProvider commService = new ServiceProvider(); commService.Requested += new ControlTcpRequestEventHandler(OnRequest); TcpLib.TcpServer server = new TcpLib.TcpServer(commService, ConfigurationSettings.AppSettings["ip"], nPort); //Debugger.Launch(); server.Start(); // todo: use event/mutex/monitor while (!mThreadShouldStop) { // do work Thread.Sleep(1); } server.Stop(); mTaskManager.RemoveAllTasks(); }
/// <summary> /// 產生一個背景執行緒來執行main Socket(某個Service)的連線服務 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void bgWorker_DoWork(object sender, DoWorkEventArgs e) { try { //若 Socket 正在工作,則停止 if (this.mainSocket != null) { this.mainSocket.Close(); } // 1.建立Socket物件,接受雙向的Tcp/Ip協議 this.mainSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // 2.建立允許連入的IP資訊關聯 this.mainSocket.Bind(new IPEndPoint(this.listenIP, this.port)); // 3.開始進入監聽狀態並監聽嘗試連入的連線 //之前測試,當等待的連線有作資料傳送時,可能會在暫存等待區裡面建立一個新的Socket並將收到的資料存放於此Socket的buffer中,當輪到此連線連入時就可以讀取buffer中的Client傳入資料 this.mainSocket.Listen(3000);//等待連接的最高上限會因OS不同(或ISP限制)而有不同限制 log.Debug(">> Server Start ..."); //持續監聽此服務 while (this.KeepSocketServerAlive) { // 4.開始等待連入(Blocking) Socket socket4Client = this.mainSocket.Accept(); lock (cLock) { if (this.clientNo == Int32.MaxValue) { this.clientNo = 0; } else { this.clientNo += 1; } // //log.Info //( // " >> " // + "Client[" // + ((IPEndPoint)socket4Client.RemoteEndPoint).ToString() // + "] Request No:" // + Convert.ToString(this.clientNo) // + " started!" //); // 5.產生一個Client物件並利用State來處理該作的事(並代入父層物件) ClientRequestHandler client = new ClientRequestHandler(this.clientNo, socket4Client, this, ServiceFactory.GetService(this.stateName)); //this.dicHandler.Add(this.clientNo, this.clientRequestHandler);//* // 6.加入Client管理列表的字典檔 this.dicHandler.Add(this.clientNo, client); // 7.產生一個背景執行緒執行此Client要處理的State this.dicHandler[this.clientNo].DoCommunicate(); } } log.Debug(">> Server Stop..."); } catch (Exception ex) { log.Error(">> Main Socket Error : " + ex.StackTrace); this.Stop(); } this.RemoveAllClients(); }
/// <summary> /// Sends a command request to the service. /// </summary> /// <param name="clientID">Client ID of sender.</param> /// <param name="principal">The principal used for role-based security.</param> /// <param name="userInput">Request string.</param> public void SendRequest(Guid clientID, IPrincipal principal, string userInput) { ClientRequest request = ClientRequest.Parse(userInput); if (request is null) { return; } if (SecurityProviderUtility.IsResourceSecurable(request.Command) && !SecurityProviderUtility.IsResourceAccessible(request.Command, principal)) { ServiceHelper.UpdateStatus(clientID, UpdateType.Alarm, $"Access to \"{request.Command}\" is denied.\r\n\r\n"); return; } ClientRequestHandler requestHandler = ServiceHelper.FindClientRequestHandler(request.Command); if (requestHandler is null) { ServiceHelper.UpdateStatus(clientID, UpdateType.Alarm, $"Command \"{request.Command}\" is not supported.\r\n\r\n"); return; } ClientInfo clientInfo = new ClientInfo { ClientID = clientID }; clientInfo.SetClientUser(principal); ClientRequestInfo requestInfo = new ClientRequestInfo(clientInfo, request); requestHandler.HandlerMethod(requestInfo); }
public async Task GetForecastAsync(DateTime startDate) { var forecast = await ClientRequestHandler .GetForecastAsync(startDate) .ConfigureAwait(false); await Clients.Caller.ReceiveWeatherForecast(forecast); }
/// <summary> /// Asynchronization Callback /// </summary> /// <param name="ar"></param> private void AcceptCallback(IAsyncResult ar) { ClientRequestHandler client = null; bool setFlag = false; try { //連線等待1秒 if (ar.AsyncWaitHandle.WaitOne(1000)) { if (ar.IsCompleted) { client = ((ClientRequestHandler)ar.AsyncState); client.ClientSocket = client.MainSocket.EndAccept(ar); setFlag = this.AcceptConnectEvent.Set(); //開始執行工作流程 client.DoCommunicate(); } } else { //目前測試不出這種狀況,或許需要拉到mainSocket.BeginAccept下跑才有用 //Console.WriteLine("[掛了沒連上]"); log.Error(m => m("[AcceptCallback]建立連線逾時")); client = ((ClientRequestHandler)ar.AsyncState); client.ClientSocket = client.MainSocket.EndAccept(ar); client.CancelAsync(); } } catch (SocketException sckEx) { //Console.WriteLine("[AcceptCallback]Socket Error:" + sckEx.Message + Environment.NewLine + sckEx.StackTrace); log.Error(m => m("[AcceptCallback]Socket Error:" + sckEx.Message + Environment.NewLine + sckEx.StackTrace)); } catch (Exception ex) { //Console.WriteLine("[AcceptCallback]Callback Error:" + ex.Message + Environment.NewLine + ex.StackTrace); log.Error(m => m("[AcceptCallback]Callback Error:" + ex.Message + Environment.NewLine + ex.StackTrace)); } finally { //this.AcceptConnectEvent.Set(); if (!setFlag) { try { this.AcceptConnectEvent.Set(); } catch (ObjectDisposedException objDisposeEx) { //Console.WriteLine(" AcceptConnectEvent Error: {0}", objDisposeEx.Message); log.Error(m => m(" AcceptConnectEvent Error: {0}", objDisposeEx.Message)); } } } }
public void Handle(ClientRequestHandler handler) { try { ALTxlog_Domain request = null; ALTxlog_Domain response = null; byte[] responseArr = null; log.Debug(m => m("[State_AutoLoadTxLog] {0} Request(ASCII):{1}", handler.ClientSocket.RemoteEndPoint.ToString(), ClientRequestHandler.asciiOctets2String(handler.Request))); try { //1.parse Txlog request = this.ParseRequest(CheckMacContainer.TOLReqMsgUtility,handler.Request); //2.send to Back-End request and get response response = this.GetResponse(request); if (response == null || String.IsNullOrEmpty(response.TXLOG_RC)) { //後台 error response = new ALTxlog_Domain() { TXLOG_RC = "990001" }; } } catch(Exception ex) { log.Error(m => m("[State_AutoLoadTxLog][Handle] Business Error: {0} \r\n{1}", ex.Message, ex.StackTrace)); //格式 error response = new ALTxlog_Domain() { TXLOG_RC = "770001" }; } //3.開始轉換Response responseArr = this.ParseResponse(CheckMacContainer.TOLRespMsgUtility,response, handler.Request); log.Info(m => m("Response(length:{0}):{1}", responseArr.Length, BitConverter.ToString(responseArr).Replace("-", ""))); int sendLength = handler.ClientSocket.Send(responseArr); if (sendLength != responseArr.Length) { log.Error(m => m("Response[length:{0}] not equal Actual Send Response[Length:{1}]", responseArr.Length, sendLength)); } } catch (SocketException sckEx) { log.Error(m => m("[State_AutoLoadTxLog][Handle] Socket Error: {0} \r\n{1}", sckEx.Message, sckEx.StackTrace)); } catch (Exception ex) { log.Error(m => m("[State_AutoLoadTxLog][Handle] Error: {0} \r\n{1}", ex.Message, ex.StackTrace)); } finally { handler.ServiceState = new State_Exit(); } }
public void Handle(ClientRequestHandler handler) { try { ALTxlog_Domain request = null; ALTxlog_Domain response = null; byte[] responseArr = null; log.Debug(m => m("[State_AutoLoadTxLog] {0} Request(ASCII):{1}", handler.ClientSocket.RemoteEndPoint.ToString(), ClientRequestHandler.asciiOctets2String(handler.Request))); try { //1.parse Txlog request = this.ParseRequest(CheckMacContainer.TOLReqMsgUtility, handler.Request); //2.send to Back-End request and get response response = this.GetResponse(request); if (response == null || String.IsNullOrEmpty(response.TXLOG_RC)) { //後台 error response = new ALTxlog_Domain() { TXLOG_RC = "990001" }; } } catch (Exception ex) { log.Error(m => m("[State_AutoLoadTxLog][Handle] Business Error: {0} \r\n{1}", ex.Message, ex.StackTrace)); //格式 error response = new ALTxlog_Domain() { TXLOG_RC = "770001" }; } //3.開始轉換Response responseArr = this.ParseResponse(CheckMacContainer.TOLRespMsgUtility, response, handler.Request); log.Info(m => m("Response(length:{0}):{1}", responseArr.Length, BitConverter.ToString(responseArr).Replace("-", ""))); int sendLength = handler.ClientSocket.Send(responseArr); if (sendLength != responseArr.Length) { log.Error(m => m("Response[length:{0}] not equal Actual Send Response[Length:{1}]", responseArr.Length, sendLength)); } } catch (SocketException sckEx) { log.Error(m => m("[State_AutoLoadTxLog][Handle] Socket Error: {0} \r\n{1}", sckEx.Message, sckEx.StackTrace)); } catch (Exception ex) { log.Error(m => m("[State_AutoLoadTxLog][Handle] Error: {0} \r\n{1}", ex.Message, ex.StackTrace)); } finally { handler.ServiceState = new State_Exit(); } }
/// <summary> /// 狀態選擇 /// </summary> /// <param name="handler"></param> /// <returns></returns> public IState StateSelect(ClientRequestHandler handler) { string conType = string.Empty; handler.Request = this.receiveData;// Encoding.ASCII.GetString(this.receiveData); //Console.WriteLine("State Factory Select Request"); if (handler.Request.Length > 10) { //依據接收字串內的某個Command字串 conType = Encoding.ASCII.GetString(handler.Request).Substring(6, 4);//0332,0333,0334,0531,0331,0341,0631,0641 //選擇處理狀態 switch (conType) { //自動加値類 case "0332": return(new State_AutoLoad()); case "0333": return(new State_AutoLoadTxLog()); case "0334": return(new State_AutoLoadReversalTxLog()); case "0531": return(new State_AutoLoadQuery()); //一般加値類 case "0331": return(new State_Loading()); case "0341": return(new State_LoadingTxLog()); //一般退貨類 case "0631": return(new State_PurchaseReturn()); case "0641": return(new State_PurchaseReturnTxLog()); //PAM取額度 case "0322": return(new State_PAMQuota()); default: return(new State_Exit()); } } else { return(new State_Exit()); } }
public BrokerProcessor( IReadableChannel <ITransportConnection> incomingConnections, IRegistryProvider registryProvider, IProtocolSerializerFactory serializerFactory, IAppLifecycleManager connectionTracker) { _incomingConnections = incomingConnections; var registryService = new RegistryService(registryProvider); var protocol = new ProtocolImplementation(DefaultProtocolMessageFactory, serializerFactory); _authenticationHandler = new AuthenticationHandler(connectionTracker, protocol, registryService); _clientRequestHandler = new ClientRequestHandler(connectionTracker, protocol, registryService); }
public void Handle(ClientRequestHandler handler) { byte[] buffer = new byte[0x1000];//buffer 4k size int receiveLength = 0; SocketError errorCode; string receiveString = String.Empty; //TODO...若被ping是否步要顯示log? //Console.WriteLine("State ReceiveData: ClientNo {0} | Count{1}", handler.ClientNo, handler.UseCount); log.Debug(m => m("State ReceiveData: ClientNo {0} | Count:{1}", handler.ClientNo, handler.UseCount)); try { receiveLength = handler.ClientSocket.Receive(buffer, 0, buffer.Length, SocketFlags.None, out errorCode); if (errorCode == SocketError.Success) { if (receiveLength > 0) { Array.Resize(ref buffer, receiveLength); receiveString = BitConverter.ToString(buffer).Replace("-", ""); //Console.WriteLine("[{0}]Request:{1}", this.GetType().Name, receiveString); log.Info(m => m("[State_ReceiveData][Handle]Request[hex]:{0}", receiveString)); handler.ServiceState = new State_Factory(buffer); } else { //收到長度0的資料 handler.ServiceState = new State_Exit(); } } else { //預期情況內的Socket異常 //Console.WriteLine("[{0}][Handle]Socket Error: {1}", this.GetType().Name, errorCode.ToString()); log.Error(m => m("[State_ReceiveData][Handle]Client Socket Error:{0}", errorCode.ToString())); handler.ServiceState = new State_Exit(); } } catch (Exception ex) { //Console.WriteLine("超過預期的異常:{0}", ex.Message); log.Error(m => m("[State_ReceiveData][Handle]超過預期的異常:{0}", ex.Message)); handler.ServiceState = new State_Exit(); } }
/// <summary> /// Sends a command request to the service. /// </summary> /// <param name="clientID">Client ID of sender.</param> /// <param name="userInput">Request string.</param> public void SendRequest(Guid clientID, string userInput) { ClientRequest request = ClientRequest.Parse(userInput); if ((object)request != null) { ClientRequestHandler requestHandler = ServiceHelper.FindClientRequestHandler(request.Command); if ((object)requestHandler != null) { requestHandler.HandlerMethod(new ClientRequestInfo(new ClientInfo() { ClientID = clientID }, request)); } else { DisplayStatusMessage($"Command \"{request.Command}\" is not supported\r\n\r\n", UpdateType.Alarm); } } }
/// <summary> /// 啟動Async Socket Server服務 /// </summary> private void StartService() { this.KeepSocketServerAlive = true; //若 Socket 正在工作,則停止 if (this.mainSocket != null) { this.mainSocket.Close(); } try { this.mainSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); this.mainSocket.Bind(new IPEndPoint(this.listenIP, this.port)); this.mainSocket.Listen(5000); //Console.WriteLine("StartService Thread Id:{0} background:{1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsBackground.ToString()); //Console.WriteLine(">> Server Start ...{0}", this.stateName); log.Info(m => m(">> Server Start ...{0}", this.serviceName)); //Async do { this.AcceptConnectEvent.Reset(); ClientRequestHandler client = (ClientRequestHandler)this.clientManager.GetInstance();//new ClientRequestHandler(this.clientNo);// (ClientRequestHandler)ClientRequestHandleManager.GetInstance(this.mainSocket); if (client.MainSocket == null) { client.MainSocket = this.mainSocket; } IAsyncResult ar = this.mainSocket.BeginAccept(AcceptCallback, client); //callback 要帶的狀態或數據要一起帶到callback,去就回不來了 this.AcceptConnectEvent.WaitOne(); //TODO...看之後要不要加入釋放Thread wait用的時間間隔 log.Debug(m => m("[StartService]Next Waiting for ... ")); //Console.WriteLine("Next Loop ... "); }while (this.KeepSocketServerAlive); //Console.WriteLine("End Start..."); log.Debug("End Start..."); } catch (Exception ex) { //Console.WriteLine("Start Failed...{0}", ex.Message); log.Error(m => m("Start Failed...{0}", ex.Message)); } }
private void ServiceHeartbeatHandler(string s, object[] args) { foreach (IServiceMonitor serviceMonitor in m_serviceMonitors.Adapters) { try { if (serviceMonitor.Enabled) { serviceMonitor.HandleServiceHeartbeat(); } } catch (Exception ex) { HandleException(ex); } } const string RequestCommand = "Health"; ClientRequestHandler requestHandler = m_serviceHelper.FindClientRequestHandler(RequestCommand); requestHandler?.HandlerMethod(ClientHelper.PretendRequest(RequestCommand)); }
public void Handle(ClientRequestHandler handler) { handler.ServiceState = this.StateSelect(handler); }
public void WhenIProcessTheRequestFromTheClientRequestHandler() { ClientRequestHandler.ProcessNextRequestFrom(ClientConnection); }
public void GivenAClientRequestHandler() { ClientRequestHandler = new ClientRequestHandler(ClientRequestProcessor); }
public void Handle(ClientRequestHandler handler) { //Console.WriteLine("Exit State ..."); log.Debug(m => m("Exit State ...")); handler.CancelAsync(); }
/// <summary> /// 狀態選擇 /// </summary> /// <param name="handler"></param> /// <returns></returns> public IState StateSelect(ClientRequestHandler handler) { string conType = string.Empty; handler.Request = this.receiveData;// Encoding.ASCII.GetString(this.receiveData); //Console.WriteLine("State Factory Select Request"); if (handler.Request.Length > 10) { //依據接收字串內的某個Command字串 conType = Encoding.ASCII.GetString(handler.Request).Substring(6, 4);//0332,0333,0334,0531,0331,0341,0631,0641 //選擇處理狀態 switch (conType) { //自動加値類 case "0332": return new State_AutoLoad(); case "0333": return new State_AutoLoadTxLog(); case "0334": return new State_AutoLoadReversalTxLog(); case "0531": return new State_AutoLoadQuery(); //一般加値類 case "0331": return new State_Loading(); case "0341": return new State_LoadingTxLog(); //一般退貨類 case "0631": return new State_PurchaseReturn(); case "0641": return new State_PurchaseReturnTxLog(); //PAM取額度 case "0322": return new State_PAMQuota(); default: return new State_Exit(); } } else { return new State_Exit(); } }
/// <summary> /// 處理邏輯 /// </summary> /// <param name="handler"></param> public void Handle(ClientRequestHandler handler) { try { CTGB_Soc_Request request = null; bool doMac = true; CTGB_Soc_Request response = null; byte[] responseArr = null; log.Debug(m => m("[State_PAMQuota] {0} Request(ASCII):{1}", handler.ClientSocket.RemoteEndPoint.ToString(), ClientRequestHandler.asciiOctets2String(handler.Request))); //1.驗證Mac if (this.CheckMac(CheckMacContainer.PAMReqMsgUtility, handler.Request)) { //2.parse request request = this.ParseRequest(CheckMacContainer.PAMReqMsgUtility, handler.Request); //3.send to Back-End request and get response response = this.GetResponse(request); if (response == null || string.IsNullOrEmpty(response.RETURN_CODE)) { //back-End Error response = new CTGB_Soc_Request() { SN = "00000000", RETURN_CODE = "190001", MERCHANT_ID = request.MERCHANT_ID, STORE_NO = request.STORE_NO, REG_ID = request.REG_ID, POS_SEQNO = request.POS_SEQNO, CASHIER_NO = request.CASHIER_NO, READER_ID = request.READER_ID, LOADING_BAL = request.LOADING_BAL, LOADING_SEQ = request.LOADING_SEQ, DATETIME = request.DATETIME }; } } else { //MAC驗證失敗 doMac = false; response = new CTGB_Soc_Request() { SN = "0000000", RETURN_CODE = "190003" }; } //4. parse response byte array(create mac) responseArr = this.ParseResponse(CheckMacContainer.PAMRespMsgUtility, response, handler.Request, doMac); log.Info(m => m("Response(length:{0}):{1}", responseArr.Length, BitConverter.ToString(responseArr).Replace("-", ""))); int sendLength = handler.ClientSocket.Send(responseArr); if (sendLength != responseArr.Length) { log.Error(m => m("Response[length:{0}] not equal Actual Send Response[Length:{1}]", responseArr.Length, sendLength)); } } catch (Exception ex) { log.Error(m => m("[State_PAMQuota][Handle] Error: {0} \r\n{1}", ex.Message, ex.StackTrace)); } finally { handler.ServiceState = new State_Exit(); } }