Ejemplo n.º 1
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);
        }
Ejemplo n.º 2
0
        private void PendingConnectionDone(PendingConnection conn, Task <XmlRpcCallResult> callTask)
        {
            lock (pendingConnections)
            {
                pendingConnections.Remove(conn);
            }

            using (logger.BeginScope(nameof(PendingConnectionDone)))
            {
                if (callTask.IsFaulted)
                {
                    logger.LogWarning($"Negotiating for {Name} has failed (Error: {callTask.Exception.Message}).");
                    return;
                }

                if (!callTask.Result.Success)
                {
                    logger.LogWarning($"Negotiating for {Name} has failed. XML-RCP call failed.");
                    return;
                }

                var resultValue = callTask.Result.Value;

                lock (gate)
                {
                    if (IsDisposed)
                    {
                        return;
                    }
                }

                var proto = new XmlRpcValue();
                if (!XmlRpcManager.Instance.ValidateXmlRpcResponse("requestTopic", resultValue, proto))
                {
                    logger.LogWarning($"Negotiating for {Name} has failed.");
                    return;
                }

                string peerHost  = conn.Client.Host;
                int    peerPort  = conn.Client.Port;
                string xmlrpcUri = "http://" + peerHost + ":" + peerPort + "/";
                if (proto.Count == 0)
                {
                    logger.LogDebug(
                        $"Could not agree on any common protocols with [{xmlrpcUri}] for topic [{Name}]"
                        );
                    return;
                }
                if (proto.Type != XmlRpcType.Array)
                {
                    logger.LogWarning($"Available protocol info returned from {xmlrpcUri} is not a list.");
                    return;
                }

                string protoName = proto[0].GetString();
                if (protoName == "UDPROS")
                {
                    logger.LogError("UDP is currently not supported. Use TCPROS instead.");
                }
                else if (protoName == "TCPROS")
                {
                    if (proto.Count != 3 || proto[1].Type != XmlRpcType.String || proto[2].Type != XmlRpcType.Int)
                    {
                        logger.LogWarning("TcpRos Publisher should implement string, int as parameter");
                        return;
                    }

                    string pubHost = proto[1].GetString();
                    int    pubPort = proto[2].GetInt();
                    logger.LogDebug($"Connecting via tcpros to topic [{Name}] at host [{pubHost}:{pubPort}]");

                    try
                    {
                        var pubLink = new TransportPublisherLink(this, xmlrpcUri);
                        lock (gate)
                        {
                            pubLink.Initialize(pubHost, pubPort);
                            AddPublisherLink(pubLink);
                        }

                        logger.LogDebug($"Connected to publisher of topic [{Name}] at  [{pubHost}:{pubPort}]");
                    }
                    catch
                    {
                        logger.LogError($"Failed to connect to publisher of topic [{Name}] at [{pubHost}:{pubPort}]");
                    }
                }
                else
                {
                    logger.LogError("The XmlRpc Server does not provide a supported protocol.");
                }
            }
        }
Ejemplo n.º 3
0
        private void PendingConnectionDone(PendingConnection conn, Task <XmlRpcCallResult> callTask)
        {
            lock ( pendingConnections )
            {
                pendingConnections.Remove(conn);
            }

            if (callTask.IsFaulted)
            {
                List <string> errorMessages = new List <string>();

                foreach (Exception exception in callTask.Exception.InnerExceptions)
                {
                    errorMessages.Add(BuildExceptionMessages(exception));
                }

                ROS.Warn()($"[{ThisNode.Name}] Negotiating for {name} has failed (Error: {string.Join( ", ", errorMessages.ToArray() )}).");
                return;
            }

            if (!callTask.Result.Success)
            {
                ROS.Warn()($"[{ThisNode.Name}] Negotiating for {name} has failed. XML-RPC call failed.");
                return;
            }

            var resultValue = callTask.Result.Value;

            lock ( shutdown_mutex )
            {
                if (shutting_down || _dropped)
                {
                    return;
                }
            }

            var proto = new XmlRpcValue();

            if (!XmlRpcManager.Instance.ValidateXmlRpcResponse("requestTopic", resultValue, proto))
            {
                ROS.Warn()($"[{ThisNode.Name}] Negotiating for {name} has failed.");
                return;
            }

            string peerHost  = conn.Client.Host;
            int    peerPort  = conn.Client.Port;
            string xmlrpcUri = $"http://{peerHost}:{peerPort}/";

            if (proto.Count == 0)
            {
                ROS.Debug()($"[{ThisNode.Name}] Could not agree on any common protocols with [{xmlrpcUri}] for topic [{name}]");
                return;
            }
            if (proto.Type != XmlRpcType.Array)
            {
                ROS.Warn()($"[{ThisNode.Name}] Available protocol info returned from {xmlrpcUri} is not a list.");
                return;
            }

            string protoName = proto[0].GetString();

            if (protoName == "UDPROS")
            {
                ROS.Error()($"[{ThisNode.Name}] UDP is currently not supported. Use TCPROS instead.");
            }
            else if (protoName == "TCPROS")
            {
                if (proto.Count != 3 || proto[1].Type != XmlRpcType.String || proto[2].Type != XmlRpcType.Int)
                {
                    ROS.Warn()($"[{ThisNode.Name}] TcpRos Publisher should implement string, int as parameter");
                    return;
                }

                string pubHost = proto[1].GetString();
                int    pubPort = proto[2].GetInt();
                ROS.Debug()($"[{ThisNode.Name}] Connecting via tcpros to topic [{name}] at host [{pubHost}:{pubPort}]");

                var transport = new TcpTransport(PollManager.Instance.poll_set)
                {
                    _topic = name
                };
                if (transport.connect(pubHost, pubPort))
                {
                    var connection = new Connection();
                    var pubLink    = new TransportPublisherLink(this, xmlrpcUri);

                    connection.initialize(transport, false, null);
                    pubLink.initialize(connection);

                    ConnectionManager.Instance.AddConnection(connection);

                    lock ( publisher_links_mutex )
                    {
                        addPublisherLink(pubLink);
                    }

                    ROS.Debug()($"[{ThisNode.Name}] Connected to publisher of topic [{name}] at  [{pubHost}:{pubPort}]");
                }
                else
                {
                    ROS.Error()($"[{ThisNode.Name}] Failed to connect to publisher of topic [{name}] at [{pubHost}:{pubPort}]");
                }
            }
            else
            {
                ROS.Error()($"[{ThisNode.Name}] The XmlRpc Server does not provide a supported protocol.");
            }
        }