/// <summary> /// Processes incoming requests of request_type 'read' or 'write' /// </summary> /// <param name="request"></param> /// <returns>Same as incoming request but with fields for 'values' (in case of read request) and / or 'message' (in case of error) filled.</returns> public TCRequest ProcessTCRequest(TCRequest request) { var hash = request.GetHashCode(); string currentVar = ""; try { if (request.names?.Length != request.types?.Length || request.names?.Length == 0 || request.request_type == null || (request.request_type != "read" && request.request_type != "write") || (request.request_type == "write" && request.values?.Length != request.names?.Length)) { request.message = "Invalid request! Length of names and types must be equal and larger than zero. Request type must be either 'read' or 'write'. If request_type is 'write' values must be supplied."; Send_TcClient_EventHandling(DateTime.Now, LogTextCategory.Error, request.message, Verbosity.Important); return(request); } Send_TcClient_EventHandling(DateTime.Now, LogTextCategory.Incoming, string.Format("Received ADS {0} request for {1} items (hash: {2})", request.request_type, request.names.Length, hash)); //read request if (request.request_type == "read") { request.values = new object[request.names.Length]; for (int i = 0; i < request.names.Length; i++) { currentVar = request.names[i]; if (!request.types[i].EndsWith("]") || request.types[i].StartsWith("string")) { request.values[i] = ReadItem(request.names[i], request.types[i]); } else { var length = int.Parse(request.types[i].Split('[')[1].Split(']')[0]); request.values[i] = ReadArray(request.names[i], request.types[i], length); } } } //write request else { for (int i = 0; i < request.names.Length; i++) { currentVar = request.names[i]; if (!request.types[i].EndsWith("]") || request.types[i].StartsWith("string")) { WriteItem(request.names[i], request.types[i], request.values[i]); } else { var length = int.Parse(request.types[i].Split('[')[1].Split(']')[0]); var arr = (request.values[i] as Newtonsoft.Json.Linq.JArray).ToObject <object[]>(); if (arr.Length != length) { throw new Exception( string.Format( "Write request for {0}: Array length in 'values' ({1}) doesn't match the indicated array length in 'types' property ({2}). " + "Make sure they are the same\nFor example if your item is an integer array of length three ('values' = [[2, 4, 1]]) " + "make sure to indicate the correct length in 'types' = ['int[3]']", request.names[i], arr.Length, length)); } WriteArray(request.names[i], request.types[i], arr); } } } Send_TcClient_EventHandling(DateTime.Now, LogTextCategory.Outgoing, string.Format("Responded to ADS {0} request for {1} items (hash: {2})", request.request_type, request.names.Length, hash)); } catch (Exception e) { request.message = string.Format("Error at variable: '{0}'. --- Error Message: {1}. --- Please refer to TwinCATAdsServer log for more info.", currentVar, e.Message); Send_TcClient_EventHandling(DateTime.Now, LogTextCategory.Error, string.Format("Exception occured during processing of request:{0}Variable: {1}{0}Request hash: {2}{0}Exception: {3}", Logging.NewLineTab, currentVar, hash, e.ToString())); } return(request); }
public async Task HandleIncomingRequests() { // While a user hasn't visited the `shutdown` url, keep on handling requests while (Running) { // Will wait here until we hear from a connection HttpListenerContext ctx = await listener.GetContextAsync(); LogArgs.When = DateTime.Now; HttpListenerRequest req = ctx.Request; HttpListenerResponse resp = ctx.Response; resp.ContentType = "application/json"; resp.ContentEncoding = Encoding.UTF8; try { //check if this is a shutdown request if (req.Url.AbsolutePath == "/btn_shutdown") { Running = false; byte[] resBytes = Encoding.UTF8.GetBytes("bye"); resp.OutputStream.Write(resBytes, 0, resBytes.Length); break; } //turn http request into tcsrequest object var tcRequest = JsonConvert.DeserializeObject <TCRequest>(req.Url.LocalPath.Remove(0, 1)); var hash = tcRequest.GetHashCode(); //notify user LogArgs.Message = string.Format("Received {0} request from {1}. (hash: {2})", req.HttpMethod, req.RemoteEndPoint, hash); LogArgs.Verbosity = Verbosity.Important; LogArgs.Category = LogTextCategory.Incoming; Logging.SendMessage(LogArgs); //actually process the request using TcIOClient var res = TcIOClient.ProcessTCRequest(tcRequest); LogArgs.When = DateTime.Now; var js = JsonConvert.SerializeObject(res); byte[] data = Encoding.UTF8.GetBytes(js); //formulate response resp.ContentLength64 = data.LongLength; await resp.OutputStream.WriteAsync(data, 0, data.Length); LogArgs.Message = string.Format("Responded with data of size {0} to {1} request. (hash: {2})", resp.ContentLength64, req.HttpMethod, hash); LogArgs.Category = LogTextCategory.Outgoing; LogArgs.Verbosity = Verbosity.Important; Logging.SendMessage(LogArgs); resp.Close(); } catch (Exception e) { var tcNull = new TCRequest(); tcNull.message = string.Format("Error in Http Server: {0} - Please refer to TwinCATHttpServer log for more information.", e.Message); LogArgs.Message = string.Format("Error in Http Server:{0}{1}{0}{2}", Logging.NewLineTab, e.Message, e.ToString()); LogArgs.Category = LogTextCategory.Error; LogArgs.Verbosity = Verbosity.Important; Logging.SendMessage(LogArgs); var js = JsonConvert.SerializeObject(tcNull); byte[] data = Encoding.UTF8.GetBytes(js); resp.ContentLength64 = data.LongLength; await resp.OutputStream.WriteAsync(data, 0, data.Length); resp.Close(); } } }