EBS_POC/EBS POC/Sockets.cs

186 lines
7.0 KiB
C#

using EBS_POC.Controls;
using EBS_POC.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace EBS_POC
{
public class Sockets
{
public static async Task<bool> InitHostConnection(string FilePath)
{
try
{
Main_Model.Current.LockFS = File.Create(FilePath + ".lock");
Main_Model.Current.EBSFilePath = FilePath;
var strMasterFile = await FilePlus.ReadAllText(FilePath);
Main_Model.Current.EBSFile = JsonHelper.Decode<Master_File>(strMasterFile);
Main_Model.Current.EBSFile.HostName = Environment.MachineName;
await FilePlus.WriteAllText(FilePath, JsonHelper.Encode(Main_Model.Current.EBSFile));
Main_Model.Current.Listener = new TcpListener(IPAddress.Any, Main_Model.Current.Port);
Main_Model.Current.Listener.Start();
ListenForConnections();
return true;
}
catch
{
return false;
}
}
public static async Task<bool> InitClientConnection(string FilePath)
{
try
{
var strMasterContents = await FilePlus.ReadAllText(FilePath);
Main_Model.Current.EBSFile = JsonHelper.Decode<Master_File>(strMasterContents);
var client = new TcpClient();
if (Main_Model.Current.EBSFile.HostName == Environment.MachineName)
{
await client.ConnectAsync(IPAddress.Loopback, Main_Model.Current.Port);
}
else
{
await client.ConnectAsync(Main_Model.Current.EBSFile.HostName, Main_Model.Current.Port);
}
Main_Model.Current.ConnectionToServer = client;
client.Client.Send(Encoding.UTF8.GetBytes(Environment.MachineName));
HandleServer(client);
return true;
}
catch
{
return false;
}
}
public static void ConnectAsHost()
{
Main_Model.Current.IsHost = true;
MainWindow.Current.frameMain.Navigate(new EBS_Page());
}
public static void ConnectAsClient()
{
if (Main_Model.Current.EBSFile.HostName == "")
{
// Wait for host or error.
}
Main_Model.Current.IsHost = false;
MainWindow.Current.frameMain.Navigate(new EBS_Page());
}
public static async void ListenForConnections()
{
var listener = Main_Model.Current.Listener;
while (listener != null)
{
var client = await listener.AcceptTcpClientAsync();
while (client.Available == 0)
{
await Task.Delay(50);
}
byte[] buffer = new byte[client.Available];
client.Client.Receive(buffer);
var strReceived = Encoding.UTF8.GetString(buffer);
var clientName = strReceived.Split('{')[0];
if (Main_Model.Current.ClientList.ContainsKey(clientName))
{
// Send error message to client.
client.Close();
return;
}
Main_Model.Current.ClientList.Add(clientName, client.Client);
if (strReceived.Length > clientName.Length)
{
ReceiveMessage(strReceived.Substring(clientName.Length));
}
HandleClient(clientName, client.Client);
}
}
public static async void HandleClient(string ClientName, Socket ClientSocket)
{
while (ClientSocket.Connected)
{
try
{
while (ClientSocket.Available == 0)
{
await Task.Delay(50);
}
var buffer = new byte[ClientSocket.Available];
ClientSocket.Receive(buffer);
var strReceived = Encoding.UTF8.GetString(buffer);
ReceiveMessage(strReceived);
foreach (var client in Main_Model.Current.ClientList.Where(kp => kp.Key != ClientName))
{
client.Value.Send(buffer);
}
await FilePlus.WriteAllText(Main_Model.Current.EBSFilePath, JsonHelper.Encode(Main_Model.Current.EBSFile));
}
catch
{
Main_Model.Current.ClientList.Remove(ClientName);
break;
}
}
}
public static async void HandleServer(TcpClient ServerConnection)
{
while (ServerConnection.Connected)
{
try
{
while (ServerConnection.Available == 0)
{
await Task.Delay(50);
}
var buffer = new byte[ServerConnection.Available];
ServerConnection.Client.Receive(buffer);
var strMessage = Encoding.UTF8.GetString(buffer);
ReceiveMessage(strMessage);
}
catch
{
// Instead, logic should be here for the next client to pick up hosting.
MessageBox.Show("Connection error.");
MainWindow.Current.frameMain.Navigate(new Start_Page());
}
}
}
public static void ReceiveMessage(string Received)
{
for (var i = 5; i < Received.Length; i++)
{
if (!Received.Remove(i).EndsWith("}") && i < Received.Length - 1 )
{
continue;
}
try
{
// This assumes only serialized Worker objects will be sent. If using
// additional DTO types, create a base DTO that can be used to determine the
// derived type, then deserialize again to the derived type.
var worker = JsonHelper.Decode<Worker>(Received.Remove(i));
Main_Model.Current.EBSFile.WorkerList.Find(existing => existing.Name == worker.Name).Notes = worker.Notes;
var workerWindow = EBS_Page.Current.stackWorkers.Children.Cast<Worker_Window>().FirstOrDefault(ww => ww.Name == worker.Name);
MainWindow.Current.frameMain.Focus();
workerWindow.textNotes.Text = worker.Notes;
ReceiveMessage(Received.Substring(i));
}
catch
{
continue;
}
}
}
}
}