250 lines
7.8 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading;
using System.Windows.Threading;
using System.Collections.ObjectModel;
using System.Collections;
using System.Data;
using System.Net.Sockets;
using System.Net;
using System.Windows.Media.Media3D;
using System.Text.Json;
using System.Security.Claims;
namespace WpfBlockChanApp
{
public partial class MainWindow : Window
{
DispatcherTimer timer1s;
DispatcherTimer timer1m;
ObservableCollection<Block> observableBlockChain = new ObservableCollection<Block>();
ObservableCollection<int> observableString = new ObservableCollection<int>();
//static List<string> strings = new List<string>();
static List<int> clients = new List<int>();
const string STD_IP = "127.0.0.1";
static string data;
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
ChainView.ItemsSource = observableBlockChain;
LogView.ItemsSource = observableString;
timer1s = new DispatcherTimer();
timer1s.Interval = TimeSpan.FromSeconds(1);
timer1s.Tick += UpdateData;
timer1s.Start();
timer1m = new DispatcherTimer();
timer1m.Interval = TimeSpan.FromSeconds(30);
timer1m.Tick += Timer1m_Tick;
timer1m.Start();
tcpListener = new TcpListener(IPAddress.Parse(STD_IP), 0);
tcpListener.Start();
data = ((IPEndPoint)tcpListener.LocalEndpoint).Port.ToString();
MyPort.Content = data;
Blockchain.Chain = new List<Block>();
Blockchain.Compute = true;
Block tmpBlock = new Block(0, "", "", 0, 0);
tmpBlock.Hash = "";
Blockchain.Chain.Add(tmpBlock);
stopNetwork = false;
listenThread = new Thread(() => listenerThredFunction());
listenThread.Start();
}
private void Timer1m_Tick(object? sender, EventArgs e)
{
UpdateClients();
}
void UpdateData(object? sender, EventArgs e)
{
for (int i = observableBlockChain.Count; i < Blockchain.Chain.Count; i++)
observableBlockChain.Add(Blockchain.Chain[i]);
for (int i = observableString.Count; i < clients.Count; i++)
observableString.Add(clients[i]);
}
Thread calcualteBlockThread;
static bool stopNetwork = false;
static bool stopMiner = false;
static void ComputeBlockThreadFunction()
{
while (true)
{
if (stopMiner) break;
Blockchain.Compute = true;
ReturnOption option = Blockchain.ComputeBlock(data);
if (!option.isValid) { continue; }
if (Blockchain.AddBlock(option.value))
{
UpdateClients(option.value);
//UpdateClients();
}
}
}
static TcpListener tcpListener;
Thread listenThread;
static void listenerThredFunction()
{
while (true)
{
if (stopNetwork) break;
listen();
}
}
static void listen()
{
try
{
using TcpClient tcpClient = tcpListener.AcceptTcpClient();
using NetworkStream networkStream = tcpClient.GetStream();
byte[] buffer = new byte[4];
int readByts = networkStream.Read(buffer, 0, buffer.Length);
if (readByts <= 0) return;
int sizeOfStruct = BitConverter.ToInt32(buffer);
byte[] isListBuffer = new byte[1];
readByts = networkStream.Read(isListBuffer, 0, isListBuffer.Length);
if(readByts <= 0) return;
bool isList = BitConverter.ToBoolean(isListBuffer);
byte[] data = new byte[sizeOfStruct];
int messageSize = networkStream.Read(data, 0, data.Length);
if (messageSize <= 0) return;
string messageString = Encoding.UTF8.GetString(data, 0, messageSize);
if (isList)
{
List<Block> chain = JsonSerializer.Deserialize<List<Block>>(messageString);
if (!Blockchain.IsValid(chain)) return;
bool update = Blockchain.Evaluete(chain, Blockchain.Chain);
if (update)
{
Blockchain.Chain = chain;
Blockchain.Compute = false;
UpdateClients();
}
}
else
{
Block block = JsonSerializer.Deserialize<Block>(messageString);
if (Blockchain.AddBlock(block))
{
Blockchain.Compute = false;
UpdateClients(block);
}
}
}
catch (Exception e)
{
}
}
static void UpdateClients()
{
string chainString = JsonSerializer.Serialize(Blockchain.Chain);
foreach (var clien in clients)
{
UpdateClient(clien, chainString, true);
}
}
static void UpdateClients(Block block)
{
string blockString = JsonSerializer.Serialize(block);
foreach (var clien in clients)
{
UpdateClient(clien, blockString, false);
}
}
static void UpdateClient(int port, string data, bool isListBool)
{
try
{
using TcpClient tcpClient = new TcpClient();
tcpClient.Connect(IPAddress.Parse(STD_IP), port);
using NetworkStream networkStream = tcpClient.GetStream();
byte[] dataBytes = Encoding.UTF8.GetBytes(data);
byte[] isList = BitConverter.GetBytes(isListBool);
byte[] size = BitConverter.GetBytes(dataBytes.Length);
networkStream.Write(size, 0, size.Length);
networkStream.Write(isList, 0, isList.Length);
networkStream.Write(dataBytes, 0, dataBytes.Length);
}catch(Exception e)
{
}
}
private void Start_Click(object sender, RoutedEventArgs e)
{
Blockchain.Compute = true;
stopMiner = false;
calcualteBlockThread = new Thread(() => ComputeBlockThreadFunction());
calcualteBlockThread.Start();
}
private void Stop_Click(object sender, RoutedEventArgs e)
{
Blockchain.Compute = false;
stopMiner = true;
}
private void Connect_Click(object sender, RoutedEventArgs e)
{
int i = 0;
if(int.TryParse(ConnectBox.Text, out i))
{
clients.Add(i);
ConnectBox.Text = "";
}
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
stopNetwork = true;
stopMiner = true;
tcpListener.Stop();
Blockchain.Compute = false;
}
}
}