예제 #1
0
        /// <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);
        }