/// <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);
        }
Example #2
0
        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();
                }
            }
        }