Example #1
0
        private async Task <bool> NegotiateConnection(string xmlRpcUri)
        {
            int         protos = 0;
            XmlRpcValue tcprosArray = new XmlRpcValue(), protosArray = new XmlRpcValue(), Params = new XmlRpcValue();

            tcprosArray.Set(0, "TCPROS");
            protosArray.Set(protos++, tcprosArray);
            Params.Set(0, ThisNode.Name);
            Params.Set(1, Name);
            Params.Set(2, protosArray);

            if (!Network.SplitUri(xmlRpcUri, out string peerHost, out int peerPort))
            {
                logger.LogError($"Bad XML-RPC URI: [{xmlRpcUri}]");
                return(false);
            }

            var client = new XmlRpcClient(peerHost, peerPort);
            var requestTopicTask = client.ExecuteAsync("requestTopic", Params);

            logger.LogDebug($"Began asynchronous XML RPC connection to http://{peerHost}:{peerPort}/ for topic [{Name}]");

            var conn = new PendingConnection(client, requestTopicTask, xmlRpcUri);

            lock (pendingConnections)
            {
                pendingConnections.Add(conn);
            }

            await requestTopicTask.WhenCompleted().ConfigureAwait(false);

            PendingConnectionDone(conn, requestTopicTask);

            return(requestTopicTask.HasCompletedSuccessfully());
        }
Example #2
0
        public bool NegotiateConnection(string xmlRpcUri)
        {
            int         protos = 0;
            XmlRpcValue tcpros_array = new XmlRpcValue(), protos_array = new XmlRpcValue(), Params = new XmlRpcValue();

            tcpros_array.Set(0, "TCPROS");
            protos_array.Set(protos++, tcpros_array);
            Params.Set(0, ThisNode.Name);
            Params.Set(1, name);
            Params.Set(2, protos_array);
            if (!Network.SplitUri(xmlRpcUri, out string peerHost, out int peerPort))
            {
                ROS.Error()($"[{ThisNode.Name}] Bad xml-rpc URI: [{xmlRpcUri}]");
                return(false);
            }

            var client = new XmlRpcClient(peerHost, peerPort);
            var requestTopicTask = client.ExecuteAsync("requestTopic", Params);

            if (requestTopicTask.IsFaulted)
            {
                ROS.Error()($"[{ThisNode.Name}] Failed to contact publisher [{peerHost}:{peerPort}for topic [{name}]");
                return(false);
            }

            ROS.Debug()($"[{ThisNode.Name}] Began asynchronous xmlrpc connection to http://{peerHost}:{peerPort}/ for topic [{name}]");

            var conn = new PendingConnection(client, requestTopicTask, xmlRpcUri);

            lock ( pendingConnections )
            {
                pendingConnections.Add(conn);
                requestTopicTask.ContinueWith(t => PendingConnectionDone(conn, t));
            }

            return(true);
        }
Example #3
0
        /// <summary>
        /// Execute a remote procedure call on the ROS master.
        /// </summary>
        /// <param name="method"></param>
        /// <param name="request">Full request to send to the master </param>
        /// <param name="waitForMaster">If you recieve an unseccessful status code, keep retrying.</param>
        /// <param name="response">Full response including status code and status message. Initially empty.</param>
        /// <param name="payload">Location to store the actual data requested, if any.</param>
        /// <returns></returns>
        public static async Task <bool> ExecuteAsync(string method, XmlRpcValue request, XmlRpcValue response, XmlRpcValue payload, bool waitForMaster)
        {
            bool supprressWarning = false;
            var  startTime        = DateTime.UtcNow;

            try
            {
                var client = new XmlRpcClient(host, port);

                while (true)
                {
                    // check if we are shutting down
                    if (XmlRpcManager.Instance.IsShuttingDown)
                    {
                        return(false);
                    }

                    try
                    {
                        var result = await client.ExecuteAsync(method, request); // execute the RPC call

                        response.Set(result.Value);
                        if (result.Success)
                        {
                            // validateXmlrpcResponse logs error in case of validation error
                            // So we don't need any logging here.
                            if (XmlRpcManager.Instance.ValidateXmlRpcResponse(method, result.Value, payload))
                            {
                                return(true);
                            }
                            else
                            {
                                return(false);
                            }
                        }
                        else
                        {
                            if (response.IsArray && response.Count >= 2)
                            {
                                ROS.Error()($"[{ThisNode.Name}] Execute failed: return={response[0].GetInt()}, desc={response[1].GetString()}");
                            }
                            else
                            {
                                ROS.Error()($"[{ThisNode.Name}] response type: {response.Type.ToString()}");
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        // no connection to ROS Master
                        if (waitForMaster)
                        {
                            if (!supprressWarning)
                            {
                                ROS.Warn()($"[{ThisNode.Name}] [{method}] Could not connect to master at [{host}:{port}]. Retrying for the next {retryTimeout.TotalSeconds} seconds.");
                                supprressWarning = true;
                            }

                            // timeout expired, throw exception
                            if (retryTimeout.TotalSeconds > 0 && DateTime.UtcNow.Subtract(startTime) > retryTimeout)
                            {
                                ROS.Error()($"[{ThisNode.Name}] [{method}] Timed out trying to connect to the master [{host}:{port}] after [{retryTimeout.TotalSeconds}] seconds");

                                throw new RosException($"Cannot connect to ROS Master at {host}:{port}", ex);
                            }
                        }
                        else
                        {
                            throw new RosException($"Cannot connect to ROS Master at {host}:{port}", ex);
                        }
                    }

                    await Task.Delay(250);

                    // recreate the client and reinitiate master connection
                    client = new XmlRpcClient(host, port);
                }
            }
            catch (ArgumentNullException e)
            {
                ROS.Error()($"[{ThisNode.Name}] {e.ToString()}");
            }
            ROS.Error()($"[{ThisNode.Name}] Master API call: {method} failed!\n\tRequest:\n{request}");
            return(false);
        }