Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- namespace Shoplogix.Server.ScreenManagement
- {
- using System;
- using System.Linq;
- using System.Text;
- using Shoplogix.Streaming;
- using Newtonsoft.Json;
- using Common.Logging;
- using Services;
- using Shoplogix.Server.Configuration;
- using System.Diagnostics;
- using System.Collections.Concurrent;
- class ScreenSocketModule : ISocketModule
- {
- private const string portal_protocol = "portal";
- private const string client_protocol = "client";
- private const string identify_protocol = "identify";
- private const string delete_protocol = "delete";
- private const string closing_protocol = "closing";
- private const string error_protocol = "error";
- private const string url_protocol = "url";
- private const string ping_protocol = "ping";
- private const string heartbeat_protocol = "stayinalive";
- private const string quick_description_protocol = "quickdescription";
- private IUserProvider user;
- private ILog logger;
- private IRoleProvider roleProvider;
- private IConfigManager configManager;
- private IAccessRuleManager ruleManager;
- ConcurrentDictionary<SocketClient, string> unclassified = new ConcurrentDictionary<SocketClient, string>();
- ScreenPortals portals = null;
- ScreenClients clients = null;
- public ScreenSocketModule(IUserProvider user, ILog logger, IRoleProvider roleProvider, IConfigManager configManager, IAccessRuleManager ruleManager)
- {
- this.user = user;
- this.logger = logger;
- this.roleProvider = roleProvider;
- this.configManager = configManager;
- this.ruleManager = ruleManager;
- portals = new ScreenPortals();
- clients = new ScreenClients(ruleManager, roleProvider, configManager, logger);
- JsonConvert.DefaultSettings = () => ApiConstants.JsonSettings;
- }
- public bool Accept(SocketClient client)
- {
- try
- {
- if (!client.Context.Path.Contains("screenmanagement.axd"))
- {
- return false;
- }
- if (clients.Update == null)
- {
- clients.Update += clients_CollectionChanged;
- }
- unclassified[client] = user.CurrentUser;
- client.Received += Client_Received;
- return true;
- }
- catch (Exception e)
- {
- this.logger.Error(e.Message);
- return false;
- }
- }
- private void Client_Received(object sender, SocketReceiveEventArgs e)
- {
- string message = Encoding.Default.GetString(e.Message).Replace("\0", string.Empty);
- var client = e.Client;
- if (unclassified.ContainsKey(client))
- {
- if (message.StartsWith(portal_protocol))
- {
- message = message.RemovePrefix(portal_protocol);
- //if new portal
- if (message.StartsWith(ping_protocol))
- {
- NewPortal(client, unclassified[client]);
- }
- else
- {
- logger.Info("Invalid string from websocket");
- client.Dispose(); //should also close the connection
- }
- }
- else if (message.StartsWith(client_protocol))
- {
- message = message.RemovePrefix(client_protocol);
- if (message.StartsWith(ping_protocol))
- {
- message = message.RemovePrefix(ping_protocol);
- if (message.Length < 1)
- {
- NewClient(client, unclassified[client]);
- }
- else if (message.StartsWith(quick_description_protocol))
- {
- message = message.RemovePrefix(quick_description_protocol);
- NewClient(client, unclassified[client], message);
- }
- else
- {
- LoadClient(client, unclassified[client] ,message);
- }
- }
- else
- {
- logger.Info("Invalid string from websocket");
- client.Dispose(); //should also close the connection
- }
- }
- var removedMessage = (string)null;
- if (!unclassified.TryRemove(client, out removedMessage)) this.logger.Warn("Failed to remove client.");
- }
- if (message.StartsWith(portal_protocol))
- {
- message = message.RemovePrefix(portal_protocol);
- var nPortal = portals.FindByContext(client.Context, user.CurrentUser);
- HandlePortal(nPortal, message);
- }
- if (message.StartsWith(client_protocol))
- {
- message = message.RemovePrefix(client_protocol);
- var nClient = clients.FindByContext(client.Context, user.CurrentUser);
- HandleClient(nClient, message);
- }
- }
- private void HandlePortal(ScreenPortal portal, string message)
- {
- if (portal != null)
- {
- //identify
- if (message.StartsWith(identify_protocol))
- {
- message = message.RemovePrefix(identify_protocol);
- var clientSocket = clients.FindByID(message);
- if (clientSocket != null)
- {
- clientSocket.Send(identify_protocol);
- logger.Debug("Sending: " + identify_protocol);
- }
- else
- {
- logger.Error("Client ID not found while trying to identify");
- string errorMessage = error_protocol + "Client ID not found while trying to identify";
- portal.Socket.Send(errorMessage);
- logger.Debug("Sending: " + errorMessage);
- }
- }
- //delete
- else if (message.StartsWith(delete_protocol))
- {
- message = message.RemovePrefix(delete_protocol);
- var clientSocket = clients.FindByID(message);
- if (clientSocket != null)
- {
- var screen = clients.FindByKey(clientSocket.Context.SecWebSocketKey);
- clientSocket.Dispose();
- clients.Delete(screen);
- clientSocket.Send(delete_protocol);
- logger.Debug("Deleting: " + screen.Id);
- }
- else
- {
- try
- {
- var configToDelete = FindMatchingClient(message);
- //Clients should always contain the key.
- if (clients.ContainsKey(configToDelete))
- {
- logger.Debug("Deleting: " + message);
- clients.Delete(configToDelete);
- clients.RemoveFromConfig(new Guid(message), portal.Account);
- portal.Socket.Send(delete_protocol + message);
- }
- else
- {
- //ID requested is not found in list of clients. Try to aesthetically delete it from the list anyways
- logger.Error("Requested ID not found in list of client IDs");
- portal.Socket.Send(delete_protocol + message);
- }
- }
- catch (Exception)
- {
- logger.Error("Client ID not found while trying to delete");
- string errorMessage = error_protocol + "Client ID not found while trying to delete";
- portal.Socket.Send(errorMessage);
- logger.Debug("Sending: " + errorMessage);
- }
- }
- }
- //update
- else
- {
- var screen = JsonConvert.DeserializeObject<ScreenConfig>(message);
- var existingScreen = clients.Keys.FirstOrDefault(k => k.Id == screen.Id);
- if (existingScreen != null)
- {
- var client = clients.UpdateScreenSettings(existingScreen, screen);
- logger.Info("Updated client");
- var rowMessage = SerializeScreen(screen);
- client.Send(rowMessage);
- logger.Debug("Sending: " + rowMessage);
- portal.Socket.Send(rowMessage);
- logger.Debug("Sending: " + rowMessage);
- }
- else
- {
- logger.Error("Client ID not found while trying to update");
- string errorMessage = error_protocol + "Client ID not found while trying to update";
- portal.Socket.Send(errorMessage);
- logger.Debug("Sending: " + errorMessage);
- }
- }
- }
- else
- {
- logger.Error("Portal was null, either the list was empty or the connection doesn't exist");
- }
- }
- private void NewPortal(SocketClient client, string account)
- {
- var areas = this.configManager.CurrentConfig.RootArea.Areas
- .Where(a => ruleManager.CurrentRules.CanRead(roleProvider, account, a) && a.Screens.Any());
- var portal = new ScreenPortal(Guid.NewGuid(), client, account);
- portals.Add(portal);
- if (clients.Any())
- {
- foreach (var screen in areas.SelectMany(a => a.Screens))
- {
- if (!clients.ContainsKey(screen)) continue;
- var rowMessage = SerializeScreen(screen);
- portal.Socket.Send(rowMessage);
- logger.Debug("Sending: " + rowMessage);
- }
- }
- foreach (var screen in clients)
- {
- if (screen.Value != null && !screen.Value.Closed)
- {
- screen.Key.Online = true;
- }
- else
- {
- screen.Key.Online = false;
- }
- var rowMessage = SerializeScreen(screen.Key);
- portal.Socket.Send(rowMessage);
- logger.Debug("Sending: " + rowMessage);
- }
- }
- private string SerializeScreen(ScreenConfig screen)
- {
- return "row" + JsonConvert.SerializeObject(screen);
- }
- private void HandleClient(ScreenConfig screen, string message)
- {
- if (screen != null)
- {
- if (message.StartsWith(url_protocol))
- {
- var next = screen.Next();
- string json = JsonConvert.SerializeObject(next);
- clients[screen].Send(url_protocol + json);
- logger.Debug("Sending: " + url_protocol + json);
- }
- else if (message.StartsWith(heartbeat_protocol))
- {
- clients[screen].Send(heartbeat_protocol);
- logger.Debug("Heartbeat");
- }
- }
- else
- {
- logger.Error("Client was null, either the list was empty or the connection doesn't exist");
- }
- }
- private void LoadClient(SocketClient clientConnection, string account, string id)
- {
- Debug.WriteLine("LoadClient");
- var screen = clients.Keys.FirstOrDefault(k => Text.Equal(k.Id.ToString(), id));
- if (screen != null)
- {
- screen.Online = true;
- clients.UpdateConnection(screen, clientConnection);
- string json = SerializeScreen(screen);
- string jsonForClient = json.Replace("id:", "newid:");
- clientConnection.Send(jsonForClient);
- portals.Broadcast(json, screen.Account);
- }
- else
- {
- logger.Warn($"Client ID: {id} not found.");
- //clientConnection.Send(error_protocol + $"Client ID: {id} not found.");
- //clientConnection.Dispose();
- logger.Info("Attempting to create new client");
- NewClient(clientConnection, account, id);
- }
- }
- private void NewClient(SocketClient client, string account, string description = "")
- {
- var screen = clients.AddNew(account, description, client);
- string json = SerializeScreen(screen);
- string jsonForClient = json.Replace("id:", "newid:");
- client.Send(jsonForClient);
- logger.Debug("Sending: " + jsonForClient);
- logger.Info("New client");
- }
- void clients_CollectionChanged(object send, ScreenListChangedEventArgs e)
- {
- if (e.Action == SocketListAction.Add || e.Action == SocketListAction.Update)
- {
- string json = SerializeScreen(e.Screen);
- portals.Broadcast(json, e.Screen.Account);
- }
- if (e.Action == SocketListAction.Remove)
- {
- portals.Broadcast(delete_protocol + e.Screen.Id.ToString(), e.Screen.Account);
- }
- }
- //Searches for client with id of "msg", and returns that client's ScreenConfig
- private ScreenConfig FindMatchingClient(string msg)
- {
- foreach (var client in clients)
- {
- var idAsString = client.Key.Id.ToString();
- if (msg == idAsString)
- {
- return client.Key;
- }
- }
- return null;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement