diff --git a/server/Program.cs b/server/Program.cs index 5c93acd..0ed5a83 100644 --- a/server/Program.cs +++ b/server/Program.cs @@ -1,16 +1,26 @@ -using System.Net; +using System.Reflection; using Microsoft.OpenApi.Models; var builder = WebApplication.CreateBuilder(args); builder.Services.AddEndpointsApiExplorer(); -builder.Services.AddSwaggerGen(c => +builder.Services.AddSwaggerGen(options => { - c.SwaggerDoc("v1", new OpenApiInfo + options.SwaggerDoc("v1", new OpenApiInfo { Title = "FPGA Web Lab API", Description = "Use FPGA in the cloud", Version = "v1" }); + // Generate Doc and Exam + var executingAssembly = Assembly.GetExecutingAssembly(); + var xmlFilename = $"{executingAssembly.GetName().Name}.xml"; + options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename)); + var referencedProjectsXmlDocPaths = + executingAssembly.GetReferencedAssemblies() + .Where(assembly => assembly.Name != null && assembly.Name.StartsWith("server", StringComparison.InvariantCultureIgnoreCase)) + .Select(assembly => Path.Combine(AppContext.BaseDirectory, $"{assembly.Name}.xml")) + .Where(path => File.Exists(path)); + foreach (var xmlDocPath in referencedProjectsXmlDocPaths) options.IncludeXmlComments(xmlDocPath); }); var app = builder.Build(); diff --git a/server/server.csproj b/server/server.csproj index aa05bf8..c74cb1d 100644 --- a/server/server.csproj +++ b/server/server.csproj @@ -4,13 +4,14 @@ net9.0 enable enable + true - + diff --git a/server/src/JtagController.cs b/server/src/JtagController.cs new file mode 100644 index 0000000..bcbc267 --- /dev/null +++ b/server/src/JtagController.cs @@ -0,0 +1,69 @@ +using System.Net; +using Common; +using DotNext; +using WebProtocol; + +namespace JtagController; + +/// +/// Global Constant Jtag Address +/// +public static class JtagAddr +{ + /// + /// Jtag State Reg + /// + public const UInt32 STATE = 0x10_00_00_00; + /// + /// Jtag Read Reg + /// + public const UInt32 READ_DATA = 0x10_00_00_01; + /// + /// Jtag Write Reg + /// + public const UInt32 WRITE_DATA = 0x10_00_00_02; + /// + /// Jtag Write Command + /// + public const UInt32 WRITE_CMD = 0x10_00_00_03; +} + +class Jtag +{ + + readonly int port; + readonly string address; + private IPEndPoint ep; + + public Jtag(string address, int port) + { + this.address = address; + this.port = port; + this.ep = new IPEndPoint(IPAddress.Parse(address), port); + } + + public async ValueTask> ClearRegisters() + { + var ret = true; + var opts = new SendAddrPackOptions(); + + opts.burstType = BurstType.FixedBurst; + opts.burstLength = 4; + opts.commandID = 0; + opts.address = JtagAddr.STATE; + + // Write Jtag State Register + opts.isWrite = true; + ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts)); + if (!ret) throw new Exception("Send 1st Address Package Failed!"); + ret = await UDPClientPool.SendDataPackAsync(ep, + new SendDataPackage(NumberProcessor.NumberToBytes(0xFF_FF_FF_FF, 4).Value)); + if (!ret) throw new Exception("Send Data Package Failed!"); + + // Read Jtag State Register + ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts)); + if (!ret) throw new Exception("Send 2rd Address Package Failed!"); + + return ret; + } +} diff --git a/server/src/Router.cs b/server/src/Router.cs index b21e362..d8532a9 100644 --- a/server/src/Router.cs +++ b/server/src/Router.cs @@ -1,41 +1,68 @@ using System.Net; using Common; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; namespace Router { + /// + /// Web API + /// class API { - public static void SendString(string address, int port, string text) + /// + /// Send some String + /// + /// IP V4/V6 address + /// Device UDP port + /// Text for send + /// Json: true or false + public static async ValueTask SendString(string address, int port, string text) { var endPoint = new IPEndPoint(IPAddress.Parse(address), port); - UDPClientPool.AsyncSendString(endPoint, [text]); + var ret = await UDPClientPool.SendStringAsync(endPoint, [text]); + if (ret) { return Results.Json(true); } + else { return Results.Json(false); } } - public static void SendAddrPackage( + + [HttpPost] + public static async ValueTask SendAddrPackage( string address, int port, - WebProtocol.BurstType burstType, - byte commandID, - bool isWrite, - byte burstLength, - UInt32 devAddress) + // WebProtocol.BurstType burstType, + // byte commandID, + // bool isWrite, + // byte burstLength, + // UInt32 devAddress) + WebProtocol.SendAddrPackOptions opts) { - WebProtocol.SendAddrPackOptions opts; - opts.burstType = burstType; - opts.commandID = commandID; - opts.isWrite = isWrite; - opts.burstLength = burstLength; - opts.address = devAddress; + // WebProtocol.SendAddrPackOptions opts; + // opts.burstType = burstType; + // opts.commandID = commandID; + // opts.isWrite = isWrite; + // opts.burstLength = burstLength; + // opts.address = devAddress; var endPoint = new IPEndPoint(IPAddress.Parse(address), port); - UDPClientPool.SendAddrPack(endPoint, new WebProtocol.SendAddrPackage(opts)); + var ret = await UDPClientPool.SendAddrPackAsync(endPoint, new WebProtocol.SendAddrPackage(opts)); + if (ret) { return Results.Json(true); } + else { return Results.Json(false); } } - public static void SendDataPackage(string address, int port, string data) + public static async ValueTask SendDataPackage(string address, int port, string data) { var endPoint = new IPEndPoint(IPAddress.Parse(address), port); - UDPClientPool.SendDataPack(endPoint, + var ret = await UDPClientPool.SendDataPackAsync(endPoint, new WebProtocol.SendDataPackage(NumberProcessor.StringToBytes(data).Value)); + if (ret) { return Results.Json(true); } + else { return Results.Json(false); } + } + + public static async ValueTask GetDeviceIDCode(string address, int port) + { + + } } } diff --git a/server/src/UdpClientPool.cs b/server/src/UdpClientPool.cs index d197de9..17d52a4 100644 --- a/server/src/UdpClientPool.cs +++ b/server/src/UdpClientPool.cs @@ -6,61 +6,73 @@ class UDPClientPool { private static IPAddress localhost = IPAddress.Parse("127.0.0.1"); - public static void SendString(IPEndPoint endPoint, string[] stringArray) + public static bool SendString(IPEndPoint endPoint, string[] stringArray) { Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); byte[] sendbuf = Encoding.ASCII.GetBytes(stringArray[0]); - socket.SendTo(sendbuf, endPoint); + var sendLen = socket.SendTo(sendbuf, endPoint); + if (sendLen == stringArray[0].Length) { return true; } + else { return false; } } - public async static void AsyncSendString(IPEndPoint endPoint, string[] stringArray) + public async static ValueTask SendStringAsync(IPEndPoint endPoint, string[] stringArray) { - await Task.Run(() => { SendString(endPoint, stringArray); }); + return await Task.Run(() => { return SendString(endPoint, stringArray); }); } - public static void SendBytes(IPEndPoint endPoint, byte[] buf) + public static bool SendBytes(IPEndPoint endPoint, byte[] buf) { Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - socket.SendTo(buf, endPoint); + var sendLen = socket.SendTo(buf, endPoint); + if (sendLen == buf.Length) { return true; } + else { return false; } } - public async static void AsyncSendBytes(IPEndPoint endPoint, byte[] buf) + public async static ValueTask SendBytesAsync(IPEndPoint endPoint, byte[] buf) { - await Task.Run(() => { SendBytes(endPoint, buf); }); + return await Task.Run(() => { return SendBytes(endPoint, buf); }); } - public static void SendAddrPack(IPEndPoint endPoint, WebProtocol.SendAddrPackage pkg) + public static bool SendAddrPack(IPEndPoint endPoint, WebProtocol.SendAddrPackage pkg) { Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - socket.SendTo(pkg.ToBytes(), endPoint); + var sendBytes = pkg.ToBytes(); + var sendLen = socket.SendTo(sendBytes, endPoint); + if (sendLen == sendBytes.Length) { return true; } + else { return false; } } - public async static void AsyncSendAddrPack(IPEndPoint endPoint, WebProtocol.SendAddrPackage pkg) + public async static ValueTask SendAddrPackAsync(IPEndPoint endPoint, WebProtocol.SendAddrPackage pkg) { - await Task.Run(() => { SendAddrPack(endPoint, pkg); }); + return await Task.Run(() => { return SendAddrPack(endPoint, pkg); }); } - public static void SendDataPack(IPEndPoint endPoint, WebProtocol.SendDataPackage pkg) + public static bool SendDataPack(IPEndPoint endPoint, WebProtocol.SendDataPackage pkg) { Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - socket.SendTo(pkg.ToBytes(), endPoint); + var sendBytes = pkg.ToBytes(); + var sendLen = socket.SendTo(sendBytes, endPoint); + if (sendLen == sendBytes.Length) { return true; } + else { return false; } } - public async static void AsyncSendDataPack(IPEndPoint endPoint, WebProtocol.SendDataPackage pkg) + public async static ValueTask SendDataPackAsync(IPEndPoint endPoint, WebProtocol.SendDataPackage pkg) { - await Task.Run(() => { SendDataPack(endPoint, pkg); }); + return await Task.Run(() => { return SendDataPack(endPoint, pkg); }); } - public static void SendLocalHost(int port, string[] stringArray) + public static bool SendLocalHost(int port, string[] stringArray) { Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - byte[] sendbuf = Encoding.ASCII.GetBytes(stringArray[0]); + byte[] sendBytes = Encoding.ASCII.GetBytes(stringArray[0]); IPEndPoint ep = new IPEndPoint(localhost, port); - socket.SendTo(sendbuf, ep); + var sendLen = socket.SendTo(sendBytes, ep); + if (sendLen == sendBytes.Length) { return true; } + else { return false; } } public static void CycleSendLocalHost(int times, int sleepMilliSeconds, int port, string[] stringArray) diff --git a/server/src/UdpServer.cs b/server/src/UdpServer.cs index 35090bb..740c4ad 100644 --- a/server/src/UdpServer.cs +++ b/server/src/UdpServer.cs @@ -2,12 +2,29 @@ using System.Net; using System.Net.Sockets; using System.Text; +public struct UDPData +{ + public DateTime datetime; + public string addr; + public int port; + public byte[] data; +} + +/// +/// UDP Server +/// public class UDPServer { private int listenPort; private UdpClient listener; private IPEndPoint groupEP; + private Dictionary udpData = new Dictionary(); + /// + /// Construct a udp server with fixed port + /// + /// Device UDP Port + /// UDPServer class public UDPServer(int port) { // Construction @@ -31,9 +48,31 @@ public class UDPServer { var remoteEP = new IPEndPoint(IPAddress.Any, listenPort); byte[] bytes = listener.EndReceive(res, ref remoteEP); + var nowtime = DateTime.Now; + // Handle RemoteEP + string remoteStr; + if (remoteEP is not null) + { + var remoteAddress = remoteEP.Address.ToString(); + var remotePort = remoteEP.Port; + // Record UDP Receive Data + udpData.Add(remoteAddress, new UDPData() + { + addr = remoteAddress, + port = remotePort, + data = bytes, + datetime = nowtime, + }); + remoteStr = $"{remoteAddress}:{remotePort}"; + } + else + { + remoteStr = "Unknown"; + } + + // Handle Package var sign = bytes[0]; - string recvData; if (sign == (byte)WebProtocol.PackSign.SendAddr) { @@ -60,8 +99,7 @@ public class UDPServer recvData = Encoding.ASCII.GetString(bytes, 0, bytes.Length); } - string remoteStr = (remoteEP is null) ? "Unknown" : $"{remoteEP.Address.ToString()}:{remoteEP.Port.ToString()}"; - Console.WriteLine($"Receive Data from {remoteStr} at {DateTime.Now.ToString()}:"); + Console.WriteLine($"Receive Data from {remoteStr} at {nowtime.ToString()}:"); Console.WriteLine($"Original Data: {BitConverter.ToString(bytes).Replace("-", " ")}"); if (recvData.Length != 0) Console.WriteLine(recvData); Console.WriteLine(); @@ -69,6 +107,10 @@ public class UDPServer listener.BeginReceive(new AsyncCallback(ReceiveHandler), null); } + /// + /// Start UDP Server + /// + /// None public void Start() { try @@ -85,6 +127,10 @@ public class UDPServer } } + /// + /// Close UDP Server + /// + /// None public void Stop() { listener.Close(); diff --git a/server/src/WebProtocol.cs b/server/src/WebProtocol.cs index 16ff7f9..8b721aa 100644 --- a/server/src/WebProtocol.cs +++ b/server/src/WebProtocol.cs @@ -3,26 +3,50 @@ using Newtonsoft.Json; namespace WebProtocol { + + /// The Sign of Package public enum PackSign { + /// Package: Send Read or Write Address to Device SendAddr = 0x00, + /// Package: Send Data Which Update the flash of Device SendData = 0xFF, + /// RecvData = 0x0F, + /// RecvResp = 0xF0, } + /// Package Burst Type public enum BurstType { + /// Extended Type ExtendBurst = 0b00, + /// Fixed Type FixedBurst = 0b01, } + + /// Package options which to send address to read or write + /// + /// { + /// "burType":0, + /// "commandID":1, + /// } + /// public struct SendAddrPackOptions { + + /// Package Burst Type + [JsonProperty("burstType")] public BurstType burstType; + /// 1 public byte commandID; + /// true public bool isWrite; + /// 255 public byte burstLength; + /// 0x10_00_00_00 public UInt32 address; public override string ToString()