예제 #1
0
        /// <summary>
        /// Redirect recived query from current server to other.
        /// </summary>
        /// <param name="tc">Server's transmission controller.</param>
        /// <param name="query">Query received from client.</param>
        public static void QueryHandler_DuplexRelay(BaseServerTransmissionController tc, UniformQueries.Query query)
        {
            bool decryptionComplete = false;
            bool decryptionResult   = false;

            Task decryptionOperation = new Task(async delegate()
            {
                // Try to encrypt receved message.
                decryptionResult = await EnctyptionOperatorsHandler.TryToDecryptAsync(
                    query,
                    EnctyptionOperatorsHandler.AsymmetricEO);

                decryptionComplete = true;
            });

            decryptionOperation.Start();

            // Whait for decription completing.
            while (!decryptionComplete)
            {
                Thread.Sleep(5);
            }

            // Loging error to client.
            if (!decryptionResult)
            {
                // Try to get answer in string format.
                SendAnswerViaPP("DUPLEX RELEAY ERROR: Data corrupted." +
                                " Decryption not possible. Relay terminated.", query);
                return;
            }

            // Detect routing target.
            bool relayTargetFound =
                UniformClient.BaseClient.routingTable.
                TryGetRoutingInstruction(query, out Instruction instruction);

            // If instruction not found.
            if (!relayTargetFound)
            {
                // If reley target not found then server will mean that query requested to itself.
                PipesProvider.Handlers.Queries.ProcessingAsync(tc, query);

                //// Log
                //Console.WriteLine("RELAY TARGET NOT FOUND: {q}", query);

                //// DO BACKWARED ERROR INFORMATION.
                //SendAnswer("error=404", UniformQueries.API.DetectQueryParts(query));

                // Drop continue computing.
                return;
            }

            // Open connection.
            TransmissionLine tl = UniformClient.BaseClient.EnqueueDuplexQueryViaPP(
                instruction.routingIP,
                instruction.pipeName,
                query,
                // Delegate that will invoked when relayed server send answer.
                // Redirects the answer to a client.
                delegate(TransmissionLine answerTL, UniformQueries.Query receivedData)
            {
                // Try to get answer in string format.
                SendAnswerViaPP(receivedData, query);
                return;
            });
        }
        /// <summary>
        /// Validates and fixed a configuration and params of the transmission line.
        /// </summary>
        /// <param name="line">A transmission line for configuration.</param>
        /// <returns>A result of configurating. False if failed.</returns>
        public static async Task <bool> ConfigurateTransmissionLineAsync(TransmissionLine line)
        {
            if (line.RoutingInstruction != null) // Routing instruction applied.
            {
                // Is partial autorized instruction.
                if (line.RoutingInstruction is PartialAuthorizedInstruction pai)
                {
                    #region Token validation
                    // If token not exist, or emoty, or expired.
                    if (line.LastQuery.Data.TryGetParamValue("token", out UniformQueries.QueryPart token))
                    {
                        // If token value is emoty.
                        if (string.IsNullOrEmpty(token.PropertyValueString))
                        {
                            if (await TokenValidation(pai))
                            {
                                // Apply received token.
                                line.LastQuery.Data.SetParam(new UniformQueries.QueryPart("token", pai.GuestToken));
                            }
                            else
                            {
                                return(false);
                            }
                        }
                    }
                    else
                    {
                        // Validate token
                        if (await TokenValidation(pai))
                        {
                            // Add tokent to query,
                            line.LastQuery.Data.ListedContent?.Add(new UniformQueries.QueryPart("token", pai.GuestToken));
                        }
                        else
                        {
                            return(false);
                        }
                    }

                    #region Methods
                    // Trying to porovide valid guest token.
                    // Returns result of validation. False - token invalid.
                    async Task <bool> TokenValidation(PartialAuthorizedInstruction instruction)
                    {
                        // If guest token is not found or expired.
                        if (pai.GuestToken == null ||
                            UniformQueries.Tokens.IsExpired(instruction.GuestToken, instruction.GuestTokenHandler.ExpiryTime))
                        {
                            // Wait for token.
                            if (!await pai.TryToGetGuestTokenAsync(ClientAppConfigurator.TerminationTokenSource.Token))
                            {
                                return(false);
                            }
                        }

                        return(true);
                    }

                    #endregion
                    #endregion

                    #region Encriprion operators validation
                    if (line.LastQuery.Data.IsEncrypted && // Is query require encryption? (Query can't be encrypted if that query must request key for encryption.)
                        line.RoutingInstruction != null && // Is routing instruction is valid and allow encryption?
                        line.RoutingInstruction.encryption)
                    {
                        // Check asymmetric operator.
                        if (pai.AsymmetricEncryptionOperator == null)
                        {
                            Console.WriteLine("Encryption operator not configurated. Operation declined.");
                            return(false);
                        }

                        #region Receiving public key from intruction's target server
                        // Check if operator is valid.
                        if (!pai.AsymmetricEncryptionOperator.IsValid)
                        {
                            try
                            {
                                // Start async key exchanging.
                                var keysExchangingOperator = RequestPublicEncryptionKeyAsync(pai);

                                try
                                {
                                    if (!keysExchangingOperator.IsCompleted)
                                    {
                                        keysExchangingOperator.Start();
                                    }
                                }
                                catch { };

                                // Drop current query as invalid cause encryption operator still in processing.
                                line.Processing = false;
                                return(false);
                            }
                            catch (Exception ex)
                            {
                                // Unlock loop.
                                line.Processing = false;
                                Console.WriteLine("SECRET KEY ERROR (bcpph1): " + ex.Message);
                                return(false);
                            }
                        }
                        #endregion

                        #region Adding public key for backward encryption if not added yet
                        if (!line.LastQuery.Data.QueryParamExist("pk"))
                        {
                            line.LastQuery.Data.SetParam(new UniformQueries.QueryPart(
                                                             "pk",
                                                             EnctyptionOperatorsHandler.AsymmetricEO.EncryptionKey));
                        }
                        #endregion

                        // Encrypt query by public key of target server.
                        return(await EnctyptionOperatorsHandler.TryToEncryptAsync(
                                   line.LastQuery.Data,
                                   line.RoutingInstruction.sEncCode,
                                   line.RoutingInstruction.AsymmetricEncryptionOperator,
                                   ClientAppConfigurator.TerminationTokenSource.Token));
                    }
                    #endregion
                }
            }

            return(true);
        }
        /// <summary>
        /// A handler that will recives a message from a server.
        /// </summary>
        /// <param name="sharedObject">
        /// Normaly is a <see cref="TransmissionLine"/> that contains information about current transmission.
        /// </param>
        public static async void HandlerInputTransmissionAsync(object sharedObject)
        {
            // Drop as invalid in case of incorrect transmitted data.
            if (!(sharedObject is TransmissionLine lineProcessor))
            {
                Console.WriteLine("TRANSMISSION ERROR (UQPP0): INCORRECT TRANSFERD DATA TYPE. PERMITED ONLY \"LineProcessor\"");
                return;
            }

            // Mark line as busy to avoid calling of next query, cause this handler is async.
            lineProcessor.Processing = true;

            #region Reciving message
            // Open stream reader.
            byte[] receivedData = null;
            try
            {
                Console.WriteLine("{0}/{1}: WAITING FOR MESSAGE",
                                  lineProcessor.ServerName, lineProcessor.ServerPipeName);

                // Avoid an error caused to disconection of client.
                try
                {
                    receivedData = await UniformDataOperator.Binary.IO.StreamHandler.StreamReaderAsync(lineProcessor.pipeClient);
                }
                // Catch the Exception that is raised if the pipe is broken or disconnected.
                catch (Exception e)
                {
                    // Log error.
                    Console.WriteLine("DNS HANDLER ERROR (USAH0): {0}", e.Message);

                    // Stop processing merker to pass async block.
                    lineProcessor.Processing = false;

                    // Close processor case this line already deprecated on the server side as single time task.
                    lineProcessor.Close();
                    return;
                }
            }
            // Catch the Exception that is raised if the pipe is broken or disconnected.
            catch (Exception e)
            {
                // Log
                if (receivedData == null || receivedData.Length == 0)
                {
                    Console.WriteLine("DNS HANDLER ERROR ({1}): {0}", e.Message, lineProcessor.pipeClient.GetHashCode());
                }
            }
            #endregion

            // Log
            if (receivedData == null || receivedData.Length == 0)
            {
                Console.WriteLine("{0}/{1}: RECEIVED MESSAGE IS EMPTY.",
                                  lineProcessor.ServerName, lineProcessor.ServerPipeName);
            }
            else
            {
                // Log state.
                Console.WriteLine("{0}/{1}: MESSAGE RECIVED",
                                  lineProcessor.ServerName, lineProcessor.ServerPipeName);

                // Decode to Query.
                UniformQueries.Query receviedQuery;
                try
                {
                    receviedQuery = UniformDataOperator.Binary.BinaryHandler.FromByteArray <UniformQueries.Query>(receivedData);
                }
                catch (Exception ex)
                {
                    Console.WriteLine("DNS HANDLER ERROR 401({1}): QUERY DAMAGED : {0}", ex.Message, lineProcessor.pipeClient.GetHashCode());

                    // Stop processing merker to pass async block.
                    lineProcessor.Processing = false;

                    // Close processor case this line already deprecated on the server side as single time task.
                    lineProcessor.Close();
                    return;
                }

                // Decrypt if required.
                await EnctyptionOperatorsHandler.TryToDecryptAsync(
                    receviedQuery,
                    EnctyptionOperatorsHandler.AsymmetricEO,
                    ClientAppConfigurator.TerminationTokenSource.Token);

                #region Processing message
                // Try to call answer handler.
                string tableGUID = lineProcessor.ServerName + "\\" + lineProcessor.ServerPipeName;

                // Look for delegate in table.
                if (DuplexBackwardCallbacks[tableGUID] is
                    Action <TransmissionLine, UniformQueries.Query> registredCallback)
                {
                    if (registredCallback != null)
                    {
                        // Invoke delegate if found and has dubscribers.
                        registredCallback.Invoke(lineProcessor, receviedQuery);

                        // Drop reference.
                        DuplexBackwardCallbacks.Remove(tableGUID);

                        // Inform subscribers about answer receiving.
                        eDuplexBackwardCallbacksReceived?.Invoke(tableGUID);
                    }
                    else
                    {
                        Console.WriteLine("{0}/{1}: ANSWER CALLBACK HAS NO SUBSCRIBERS",
                                          lineProcessor.ServerName, lineProcessor.ServerPipeName);
                    }
                }
                else
                {
                    Console.WriteLine("{0}/{1}: ANSWER HANDLER NOT FOUND BY {2}",
                                      lineProcessor.ServerName, lineProcessor.ServerPipeName, tableGUID);
                }

                //Console.WriteLine("{0}/{1}: ANSWER READING FINISH.\nMESSAGE: {2}",
                //    lineProcessor.ServerName, lineProcessor.ServerPipeName, message);
                #endregion
            }

            // Stop processing merker to pass async block.
            lineProcessor.Processing = false;

            // Close processor case this line already deprecated on the server side as single time task.
            lineProcessor.Close();
        }
예제 #4
0
        /// <summary>
        /// Code that will work on server loop when connection will be established.
        /// Recoomended to using as default DNS Handler for queries reciving.
        /// </summary>
        public static async void ClientToServerAsync(BaseServerTransmissionController controller)
        {
            DateTime sessionTime = DateTime.Now.AddSeconds(5000);

            // Read until trasmition exits not finished.
            while (controller.PipeServer.IsConnected)
            {
                // Open stream reader.
                byte[] binaryQuery;
                #region Reciving message
                // Read data from stream.
                // Avoid an error caused to disconection of client.
                try
                {
                    binaryQuery = await StreamHandler.StreamReaderAsync(controller.PipeServer);
                }
                // Catch the Exception that is raised if the pipe is broken or disconnected.
                catch (Exception e)
                {
                    Console.WriteLine("DNS HANDLER ERROR: {0}", e.Message);
                    return;
                }

                if (DateTime.Compare(sessionTime, DateTime.Now) < 0)
                {
                    Console.WriteLine("Connection terminated cause allowed time has expired.");
                    // Avoid disconnectin error.
                    try
                    {
                        controller.PipeServer.Disconnect();
                    }
                    catch
                    {
                        // Exception caused by disconecction on client side.
                    }

                    return;
                }
                #endregion

                #region Finalizing connection
                // Disconnect user if query recived.
                if (controller.PipeServer.IsConnected)
                {
                    try
                    {
                        controller.PipeServer.Disconnect();
                    }
                    catch
                    {
                        // Exception caused by disconecction on client side.
                    }
                }

                // Remove temporal data.
                controller.PipeServer.Dispose();
                #endregion

                #region Query processing
                // Drop if stream is over.
                if (binaryQuery == null || binaryQuery.Length == 0)
                {
                    //Console.WriteLine("NULL REQUEST AVOIDED. CONNECTION TERMINATED.");
                    break;
                }

                // Decode query from binary data.
                Query query;
                try
                {
                    query = UniformDataOperator.Binary.BinaryHandler.FromByteArray <Query>(binaryQuery);
                }
                catch (Exception ex)
                {
                    Console.WriteLine("DNS HANDLER ERROR (DNS50): DAMAGED DATA : {0}", ex.Message);
                    return;
                }

                // Try to decrypt. In case of fail decryptor returns an entry message.
                await EnctyptionOperatorsHandler.TryToDecryptAsync(
                    query, EnctyptionOperatorsHandler.AsymmetricEO);

                // Log query.
                Console.WriteLine(@"RECIVED QUERY (DNS0): {0}", query);

                // Try to get correct transmisssion controller.
                if (controller is ClientToServerTransmissionController CToSTS)
                {
                    // Redirect handler.
                    CToSTS.queryHandlerCallback?.Invoke(controller, query);
                }
                else
                {
                    // Log error.
                    Console.WriteLine(@"DNS HANDLER ERROR (DNS40):\nQuery processing not posssible.\nTransmission controller not {0}",
                                      typeof(ClientToServerTransmissionController).FullName);
                }
                #endregion
            }

            // Log about transmission finish.
            Console.WriteLine("{0} : TRANSMISSION FINISHED AT {1}",
                              controller.PipeName, DateTime.Now.ToString("HH:mm:ss.fff"));
        }