/// <summary> /// Processes incoming socket messages from taskt clients /// </summary> /// <param name="context"></param> /// <param name="webSocket"></param> /// <returns></returns> public async Task ProcessIncomingSocketMessage(HttpContext context, WebSocket webSocket) { //create dbcontext Models.SQL.tasktserverContext dbContext = new tasktserverContext(); //generate GUID for this connection Guid guid; guid = Guid.NewGuid(); string connectionGUID = guid.ToString(); var buffer = new byte[1024 * 4]; WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment <byte>(buffer), CancellationToken.None); while (!result.CloseStatus.HasValue) { //get connection information string connectionID = context.Connection.Id; string ipAddress = context.Connection.RemoteIpAddress.ToString(); //retrieve value var arraySegment = new ArraySegment <byte>(buffer, 0, result.Count); var incomingMessage = System.Text.Encoding.Default.GetString(arraySegment.Array); incomingMessage = incomingMessage.Substring(0, result.Count); //convert client data var clientData = Newtonsoft.Json.JsonConvert.DeserializeObject <SocketPackage>(incomingMessage); var clientInfo = string.Join(", ", "MACHINE: " + clientData.MACHINE_NAME, "USER: "******"MESSAGE: " + clientData.MESSAGE, "IP: " + ipAddress); if (clientData.MESSAGE.StartsWith("CLIENT_STATUS=")) { var clientUpdate = clientData.MESSAGE.Replace("CLIENT_STATUS=", ""); var socketClient = ActiveSocketClients.GetClient(clientData.PUBLIC_KEY); if (socketClient.PingRequest.AwaitingPingReply) { socketClient.PingRequest.AwaitingPingReply = false; socketClient.PingRequest.ClientStatus = clientUpdate; socketClient.PingRequest.ReadyForUIReporting = true; } LogEvent(new ApplicationLogs() { Type = "WORKER UPDATE", Guid = connectionGUID, Message = clientUpdate, LoggedBy = clientData.PUBLIC_KEY }); var worker = dbContext.Workers.Where(f => f.PublicKey == clientData.PUBLIC_KEY).FirstOrDefault(); if (worker != null) { worker.LastCommunicationReceived = DateTime.Now; worker.LastExecutionStatus = clientUpdate; dbContext.SaveChanges(); } await SendMessageAsync(webSocket, "ACK", CancellationToken.None); } LogEvent(new ApplicationLogs() { Guid = connectionGUID, Message = "ROBOT CONNECTED FROM '" + ipAddress + "'", LoggedBy = "SYSTEM", Type = "SOCKET REQUEST" }); LogEvent(new ApplicationLogs() { Guid = connectionGUID, Message = "CLIENT INFO: " + clientInfo + "", LoggedBy = "SYSTEM", Type = "SOCKET REQUEST" }); //if public key is null or empty we automatically assign if ((string.IsNullOrEmpty(clientData.PUBLIC_KEY)) || (dbContext.Workers.Where(f => f.PublicKey == clientData.PUBLIC_KEY).FirstOrDefault() == null)) { LogEvent(new ApplicationLogs() { Guid = connectionGUID, Message = "ROBOT NOT REGISTERED", LoggedBy = "SYSTEM", Type = "SOCKET REQUEST" }); var generatedKeys = tasktServer.Cryptography.CreateKeyPair(); var worker = new Workers() { MachineName = clientData.MACHINE_NAME, UserName = clientData.USER_NAME, AccountStatus = (int)ApprovalStatus.RequiresApproval, LastCommunicationReceived = DateTime.Now, PublicKey = generatedKeys.Item2, PrivateKey = generatedKeys.Item1 }; dbContext.Workers.Add(worker); dbContext.SaveChanges(); ActiveSocketClients.SetClient(clientData.PUBLIC_KEY, webSocket); LogEvent(new ApplicationLogs() { Guid = connectionGUID, Message = "ROBOT GIVEN NEW PUBLIC KEY AND AWAITING AUTHORIZATION", LoggedBy = "SYSTEM", Type = "SOCKET REQUEST" }); await SendMessageAsync(webSocket, "ACCEPT_KEY=" + worker.PublicKey, CancellationToken.None); } else { var knownClient = dbContext.Workers.Where(f => f.PublicKey == clientData.PUBLIC_KEY).FirstOrDefault(); knownClient.LastCommunicationReceived = DateTime.Now; dbContext.SaveChanges(); ActiveSocketClients.SetClient(clientData.PUBLIC_KEY, webSocket); switch (knownClient.AccountStatus) { case (int)ApprovalStatus.RequiresApproval: LogEvent(new ApplicationLogs() { Guid = connectionGUID, Message = "RESPONDED WORKER_AWAITING_APPROVAL", LoggedBy = "SYSTEM", Type = "SOCKET REQUEST" }); await SendMessageAsync(webSocket, "WORKER_AWAITING_APPROVAL", CancellationToken.None); break; case (int)ApprovalStatus.Disabled: LogEvent(new ApplicationLogs() { Guid = connectionGUID, Message = "RESPONDED WORKER_DISABLED", LoggedBy = "SYSTEM", Type = "SOCKET REQUEST" }); await SendMessageAsync(webSocket, "WORKER_DISABLED", CancellationToken.None); break; case (int)ApprovalStatus.Enabled: LogEvent(new ApplicationLogs() { Guid = connectionGUID, Message = "RESPONDED WORKER_ENABLED", LoggedBy = "SYSTEM", Type = "SOCKET REQUEST" }); await SendMessageAsync(webSocket, "WORKER_ENABLED", CancellationToken.None); break; default: break; } } result = await webSocket.ReceiveAsync(new ArraySegment <byte>(buffer), CancellationToken.None); } await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None); }
/// <summary> /// Processes incoming socket messages from taskt clients /// </summary> /// <param name="context"></param> /// <param name="webSocket"></param> /// <returns></returns> public async Task ProcessIncomingSocketMessage(HttpContext context, WebSocket webSocket) { //create dbcontext Models.SQL.tasktserverContext dbContext = new tasktserverContext(); //generate GUID for this connection Guid guid; guid = Guid.NewGuid(); string connectionGUID = guid.ToString(); var buffer = new byte[1024 * 4]; WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment <byte>(buffer), CancellationToken.None); while (!result.CloseStatus.HasValue) { //get connection information string connectionID = context.Connection.Id; string ipAddress = context.Connection.RemoteIpAddress.ToString(); //retrieve value var arraySegment = new ArraySegment <byte>(buffer, 0, result.Count); var incomingMessage = System.Text.Encoding.Default.GetString(arraySegment.Array); incomingMessage = incomingMessage.Substring(0, result.Count); System.Console.WriteLine(incomingMessage); //convert client data var clientData = Newtonsoft.Json.JsonConvert.DeserializeObject <SocketPackage>(incomingMessage); var clientInfo = string.Join(", ", "MACHINE: " + clientData.MACHINE_NAME, "USER: "******"MESSAGE: " + clientData.MESSAGE, "IP: " + ipAddress); //determine if we were pinging this client for availability if (clientData.MESSAGE.StartsWith("CLIENT_STATUS=")) { //get client update var clientUpdate = clientData.MESSAGE.Replace("CLIENT_STATUS=", ""); //find client socket connection var socketClient = ActiveSocketClients.GetClient(clientData.PUBLIC_KEY); //check if we are awaiting a ping reply from this client if (socketClient.PingRequest.AwaitingPingReply) { //update client object accordingly socketClient.PingRequest.AwaitingPingReply = false; socketClient.PingRequest.ClientStatus = clientUpdate; socketClient.PingRequest.ReadyForUIReporting = true; } //log update from worker LogEvent(new ApplicationLogs() { Type = "WORKER UPDATE", Guid = connectionGUID, Message = clientUpdate, LoggedBy = clientData.PUBLIC_KEY }); //get reference to the client var worker = dbContext.Workers.Where(f => f.PublicKey == clientData.PUBLIC_KEY).FirstOrDefault(); //update communication worker.LastCommunicationReceived = DateTime.Now; dbContext.SaveChanges(); //send acknowledge to client await SendMessageAsync(webSocket, "ACK", CancellationToken.None); } //log client connection LogEvent(new ApplicationLogs() { Guid = connectionGUID, Message = "ROBOT CONNECTED FROM '" + ipAddress + "'", LoggedBy = "SYSTEM", Type = "SOCKET REQUEST" }); LogEvent(new ApplicationLogs() { Guid = connectionGUID, Message = "CLIENT INFO: " + clientInfo + "", LoggedBy = "SYSTEM", Type = "SOCKET REQUEST" }); //determine if this client is known if ((string.IsNullOrEmpty(clientData.PUBLIC_KEY)) || (dbContext.Workers.Where(f => f.PublicKey == clientData.PUBLIC_KEY).FirstOrDefault() == null)) { //client is new or not yet configured //create log LogEvent(new ApplicationLogs() { Guid = connectionGUID, Message = "ROBOT NOT REGISTERED", LoggedBy = "SYSTEM", Type = "SOCKET REQUEST" }); //generate key pair - public key sent to client and private key stored locally var generatedKeys = tasktServer.Cryptography.CreateKeyPair(); //add as a new worker to the database var worker = new Workers() { MachineName = clientData.MACHINE_NAME, UserName = clientData.USER_NAME, AccountStatus = (int)ApprovalStatus.RequiresApproval, LastCommunicationReceived = DateTime.Now, PublicKey = generatedKeys.Item2, PrivateKey = generatedKeys.Item1 }; dbContext.Workers.Add(worker); //save changes dbContext.SaveChanges(); //set client as an active socket client which enables the ability to execute scripts ActiveSocketClients.SetClient(clientData.PUBLIC_KEY, webSocket); //create log LogEvent(new ApplicationLogs() { Guid = connectionGUID, Message = "ROBOT GIVEN NEW PUBLIC KEY AND AUTHENTICATED AUTOMATICALLY (DANGEROUS!)", LoggedBy = "SYSTEM", Type = "SOCKET REQUEST" }); //send key back to client await SendMessageAsync(webSocket, "ACCEPT_KEY=" + worker.PublicKey, CancellationToken.None); } else { //find client info var knownClient = dbContext.Workers.Where(f => f.PublicKey == clientData.PUBLIC_KEY).FirstOrDefault(); //update last communication received knownClient.LastCommunicationReceived = DateTime.Now; //save changes dbContext.SaveChanges(); //set client as active and available ActiveSocketClients.SetClient(clientData.PUBLIC_KEY, webSocket); //send message back to client await SendMessageAsync(webSocket, "WORKER_ENABLED", CancellationToken.None); //APPROVAL PROCESS, FUTURE ENHANCEMENT! //switch (worker.ApprovalStatus) //{ // case ApprovalStatus.RequiresApproval: // LogEvent(new ApplicationLogs() { Guid = connectionGUID, Message = "RESPONDED WORKER_AWAITING_APPROVAL", LoggedBy = "SYSTEM", Type = "SOCKET REQUEST" }); // await SendMessageAsync(webSocket, "WORKER_AWAITING_APPROVAL", CancellationToken.None); // break; // case ApprovalStatus.Disabled: // LogEvent(new ApplicationLogs() { Guid = connectionGUID, Message = "RESPONDED WORKER_DISABLED", LoggedBy = "SYSTEM", Type = "SOCKET REQUEST" }); // await SendMessageAsync(webSocket, "WORKER_DISABLED", CancellationToken.None); // break; // case ApprovalStatus.Enabled: // LogEvent(new ApplicationLogs() { Guid = connectionGUID, Message = "RESPONDED WORKER_ENABLED", LoggedBy = "SYSTEM", Type = "SOCKET REQUEST" }); // await SendMessageAsync(webSocket, "WORKER_ENABLED", CancellationToken.None); // break; // default: // break; //} } result = await webSocket.ReceiveAsync(new ArraySegment <byte>(buffer), CancellationToken.None); } await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None); }