コード例 #1
0
        private void onConnectionDropped(Connection conn, Connection.DropReason reason)
        {
            ROS.Debug()($"[{ThisNode.Name}] TransportPublisherLink: onConnectionDropped from remote {conn.RemoteString} with reason {reason.ToString()}");

            if (dropping || conn != connection)
            {
                return;
            }
            if (reason == Connection.DropReason.TransportDisconnect)
            {
                needs_retry = true;
                next_retry  = DateTime.UtcNow.Add(retry_period);
                if (retry_timer == null)
                {
                    retry_timer = ROS.timerManager.StartTimer(onRetryTimer, 100);
                }
                else
                {
                    retry_timer.Restart();
                }
            }
            else
            {
                if (reason == Connection.DropReason.HeaderError)
                {
                    ROS.Error()($"[{ThisNode.Name}] Error in the Header: {( parent != null ? parent.name : "unknown" )}");
                }
                drop();
            }
        }
コード例 #2
0
        private void onRetryTimer(object o)
        {
            ROS.Debug()($"[{ThisNode.Name}] TransportPublisherLink: onRetryTimer");
            if (dropping)
            {
                return;
            }

            if (needs_retry && DateTime.UtcNow.Subtract(next_retry).TotalMilliseconds < 0)
            {
                retry_period =
                    TimeSpan.FromSeconds((retry_period.TotalSeconds > 20) ? 20 : (2 * retry_period.TotalSeconds));
                needs_retry = false;
                TcpTransport old_transport = connection.transport;
                string       host          = old_transport.connectedHost;
                int          port          = old_transport.connectedPort;

                TcpTransport transport = new TcpTransport();
                if (transport.connect(host, port))
                {
                    Connection conn = new Connection();
                    conn.initialize(transport, false, null);
                    initialize(conn);
                    ConnectionManager.Instance.AddConnection(conn);
                }
            }
        }
コード例 #3
0
        public bool pubUpdate(string topic, List <string> pubs)
        {
            ROS.Debug()($"[{ThisNode.Name}] TopicManager is updating publishers for {topic}");

            Subscription sub = null;

            lock ( subcriptionsMutex )
            {
                if (shuttingDown)
                {
                    return(false);
                }

                foreach (Subscription s in subscriptions)
                {
                    if (s.name != topic || s.IsDropped)
                    {
                        continue;
                    }
                    sub = s;
                    break;
                }
            }
            if (sub != null)
            {
                return(sub.pubUpdate(pubs));
            }
            ROS.Info()($"[{ThisNode.Name}] Request for updating publishers of topic {topic}, which has no subscribers.");
            return(false);
        }
コード例 #4
0
        public bool handleHeader(Header header)
        {
            if (!header.Values.ContainsKey("md5sum") || !header.Values.ContainsKey("service") || !header.Values.ContainsKey("callerid"))
            {
                string bbq = $"[{ThisNode.Name}] Error in TcpRos header. Required elements (md5sum, service, callerid) are missing";
                ROS.Error()(bbq);
                connection.sendHeaderError(ref bbq);
                return(false);
            }
            string md5sum          = (string)header.Values["md5sum"];
            string service         = (string)header.Values["service"];
            string client_callerid = (string)header.Values["callerid"];

            if (header.Values.ContainsKey("persistent") && ((string)header.Values["persistent"] == "1" || (string)header.Values["persistent"] == "true"))
            {
                persistent = true;
            }

            ROS.Debug()($"[{ThisNode.Name}] Service client [{client_callerid}] wants service [{service}] with md5sum [{md5sum}]");
            IServicePublication isp = ServiceManager.Instance.LookupServicePublication(service);

            if (isp == null)
            {
                string bbq = $"[{ThisNode.Name}] Received a TcpRos connection for a nonexistent service [{service}]";
                ROS.Warn()(bbq);
                connection.sendHeaderError(ref bbq);
                return(false);
            }

            if (isp.md5sum != md5sum && md5sum != "*" && isp.md5sum != "*")
            {
                string bbq = $"[{ThisNode.Name}] Client wants service {service} to have md5sum {md5sum} but it has {isp.md5sum}. Dropping connection";
                ROS.Error()(bbq);
                connection.sendHeaderError(ref bbq);
                return(false);
            }

            if (isp.isDropped)
            {
                string bbq = $"[{ThisNode.Name}]  Received a TcpRos connection for a nonexistent service [{service}]";
                ROS.Warn()(bbq);
                connection.sendHeaderError(ref bbq);
                return(false);
            }

            parent = isp;
            IDictionary <string, string> m = new Dictionary <string, string>();

            m["request_type"]  = isp.req_datatype;
            m["response_type"] = isp.res_datatype;
            m["type"]          = isp.datatype;
            m["md5sum"]        = isp.md5sum;
            m["callerid"]      = ThisNode.Name;

            connection.writeHeader(m, onHeaderWritten);

            isp.addServiceClientLink(this);
            return(true);
        }
コード例 #5
0
 public void AddPollThreadListener(Action poll)
 {
     ROS.Debug()($"[{ThisNode.Name}] Adding pollthreadlistener {poll.Target}:{poll.GetMethodInfo().Name}");
     lock ( signal_mutex )
     {
         signals.Add(new PollSignal(poll));
     }
     CallSignal();
 }
コード例 #6
0
        internal override CallResult Call()
        {
            ROS.Debug()($"[{ThisNode.Name}] Called PeerConnDisconnCallback");
            SingleSubscriberPublisher pub = new SingleSubscriberPublisher(sub_link);

            ROS.Debug()($"[{ThisNode.Name}] Callback: Name: {pub.SubscriberName} Topic: {pub.Topic}");
            callback(pub);
            return(CallResult.Success);
        }
コード例 #7
0
ファイル: Publication.cs プロジェクト: wiwing/ROS.NET
        internal override CallResult Call()
        {
            ROS.Debug()("Called PeerConnDisconnCallback");
            SingleSubscriberPublisher pub = new SingleSubscriberPublisher(subscriberLink);

            logger.LogDebug($"Callback: Name: {pub.SubscriberName} Topic: {pub.Topic}");
            callback(pub);
            return(CallResult.Success);
        }
コード例 #8
0
 public bool Initialize(Connection connection)
 {
     if (parent != null)
     {
         ROS.Debug()($"Init transport subscriber link: {parent.Name}");
     }
     this.connection          = connection;
     connection.DroppedEvent += OnConnectionDropped;
     return(true);
 }
コード例 #9
0
        private bool onResponseOkAndLength(Connection conn, byte[] buf, int size, bool success)
        {
            if (conn != connection)
            {
                throw new ArgumentException("Unknown connection", nameof(conn));
            }

            if (size != 5)
            {
                throw new ArgumentException($"Wrong size {size}", nameof(size));
            }

            if (!success)
            {
                return(false);
            }

            byte ok          = buf[0];
            int  len         = BitConverter.ToInt32(buf, 1);
            int  lengthLimit = 1000000000;

            if (len > lengthLimit)
            {
                ROS.Error()($"[{ThisNode.Name}] Message length exceeds limit of {lengthLimit}. Dropping connection.");
                connection.drop(Connection.DropReason.Destructing);
                return(false);
            }

            lock ( call_queue_mutex )
            {
                if (ok != 0)
                {
                    current_call.success = true;
                }
                else
                {
                    current_call.success = false;
                }
            }

            if (len > 0)
            {
                ROS.Debug()($"[{ThisNode.Name}] Reading message with length of {len}.");
                connection.read(len, onResponse);
            }
            else
            {
                byte[] f = new byte[0];
                onResponse(conn, f, 0, true);
            }
            return(true);
        }
コード例 #10
0
        public bool call(RosMessage req, ref RosMessage resp)
        {
            if (resp == null)
            {
                //instantiate null response IN CASE this call succeeds
                resp = RosMessage.Generate(req.MessageType.Replace("Request", "Response"));
            }

            CallInfo info = new CallInfo {
                req = req, resp = resp, success = false, finished = false
            };

            bool immediate = false;

            lock ( call_queue_mutex )
            {
                if (connection.dropped)
                {
                    return(false);
                }

                if (call_queue.Count == 0 && header_written && header_read)
                {
                    immediate = true;
                }

                call_queue.Enqueue(info);
            }

            if (immediate)
            {
                processNextCall();
            }

            while (!info.finished)
            {
                ROS.Debug()($"[{ThisNode.Name}] info.finished_condition.WaitOne();");
                info.finished_condition.WaitOne();
            }

            if (info.success)
            {
                // response is only sent on success => don't try to deserialize on failure.
                resp.Deserialize(resp.Serialized);
            }

            if (!string.IsNullOrEmpty(info.exception))
            {
                ROS.Error()($"[{ThisNode.Name}] Service call failed: service [{name}] responded with an error: {info.exception}");
            }
            return(info.success);
        }
コード例 #11
0
 private void ThreadFunc()
 {
     while (!shutting_down)
     {
         CallSignal();
         Thread.Sleep(ROS.WallDuration);
         if (shutting_down)
         {
             return;
         }
     }
     ROS.Debug()($"[{ThisNode.Name}] PollManager thread finished");
 }
コード例 #12
0
 public override void drop()
 {
     dropping = true;
     connection.drop(Connection.DropReason.Destructing);
     if (parent != null)
     {
         parent.removePublisherLink(this);
     }
     else
     {
         ROS.Debug()($"[{ThisNode.Name}] Last publisher link removed");
     }
 }
コード例 #13
0
        private void OnConnectionDropped(Connection conn, Connection.DropReason reason)
        {
            if (conn != connection || parent == null)
            {
                return;
            }

            ROS.Debug()($"[{ThisNode.Name}] TransportSubscriberLink: OnConnectionDropped from remote {conn.RemoteString} with reason {reason.ToString()}");
            lock ( parent )
            {
                parent.removeSubscriberLink(this);
            }
        }
コード例 #14
0
        public bool HandleHeader(Header header)
        {
            if (!header.Values.ContainsKey("topic"))
            {
                string msg = $"[{ThisNode.Name}] Header from subscriber did not have the required element: topic";
                ROS.Warn()(msg);
                connection.sendHeaderError(ref msg);
                return(false);
            }
            string      name            = (string)header.Values["topic"];
            string      client_callerid = (string)header.Values["callerid"];
            Publication pt = TopicManager.Instance.lookupPublication(name);

            if (pt == null)
            {
                string msg = $"[{ThisNode.Name}] received a connection for a nonexistent topic [{name}] from [{connection.transport}] [{client_callerid}]";
                ROS.Warn()(msg);
                connection.sendHeaderError(ref msg);
                return(false);
            }
            string error_message = "";

            if (!pt.validateHeader(header, ref error_message))
            {
                connection.sendHeaderError(ref error_message);
                ROS.Error()($"[{ThisNode.Name}] {error_message}");
                return(false);
            }
            destination_caller_id = client_callerid;
            connection_id         = ConnectionManager.Instance.GetNewConnectionId();
            name   = pt.Name;
            topic  = name;
            parent = pt;
            lock ( parent )
            {
                maxQueue = parent.MaxQueue;
            }

            var m = new Dictionary <string, string>();

            m["type"]               = pt.DataType;
            m["md5sum"]             = pt.Md5sum;
            m["message_definition"] = pt.MessageDefinition;
            m["callerid"]           = ThisNode.Name;
            m["latching"]           = Convert.ToString(pt.Latch);
            connection.writeHeader(m, OnHeaderWritten);
            pt.addSubscriberLink(this);
            ROS.Debug()($"[{ThisNode.Name}] Finalize transport subscriber link for {name}");
            return(true);
        }
コード例 #15
0
        private void onConnectionDropped(Connection connection, Connection.DropReason reason)
        {
            if (connection != this.connection)
            {
                throw new ArgumentException("Unknown connection", nameof(connection));
            }

            ROS.Debug()($"[{ThisNode.Name}] Service client from [{connection.RemoteString}] for [{name}] dropped");

            clearCalls();

            ServiceManager.Instance.RemoveServiceServerLink(this);

            IsValid = false;
        }
コード例 #16
0
        private void ThreadFunc()
        {
            TimeSpan wallDuration = new TimeSpan(0, 0, 0, 0, ROS.WallDuration);

            while (ROS.ok)
            {
                DateTime begin = DateTime.UtcNow;
                CallAvailable(ROS.WallDuration);
                DateTime end = DateTime.UtcNow;

                var remainingTime = wallDuration - (end - begin);
                if (remainingTime > TimeSpan.Zero)
                {
                    Thread.Sleep(remainingTime);
                }
            }
            ROS.Debug()($"[{ThisNode.Name}] CallbackQueue thread broke out!");
        }
コード例 #17
0
        private void RemoveDroppedConnections()
        {
            Connection[] localDroppedConnections = null;
            lock ( dropped_connections_mutex )
            {
                localDroppedConnections = dropped_connections.ToArray();
                dropped_connections.Clear();
            }

            lock ( connections_mutex )
            {
                foreach (Connection c in localDroppedConnections)
                {
                    ROS.Debug()($"[{ThisNode.Name}] Removing dropped connection: {c.CallerID}");
                    connections.Remove(c);
                }
            }
        }
コード例 #18
0
        async Task HandleConnection()
        {
            try
            {
                await Handshake().ConfigureAwait(false);

                while (await callQueue.MoveNext(cancel).ConfigureAwait(false))
                {
                    var call = callQueue.Current;
                    await ProcessCall(call).ConfigureAwait(false);
                }

                connection.Socket.Shutdown(SocketShutdown.Send);
                connection.Close(50);
            }
            catch (System.IO.EndOfStreamException ex)
            {
                ROS.Debug()("EndOfStreamException during connection handling. Message: {0}, Stacktrace : {1}",
                            ex.ToString(), ex.StackTrace);
            }
            catch (System.IO.IOException ex)
            {
                ROS.Debug()("IOException during connection handling. Message: {0}, Stacktrace : {1}",
                            ex.ToString(), ex.StackTrace);
            }
            catch (Exception e)
            {
                if (!(e is OperationCanceledException))
                {
                    logger.LogDebug($"Service client for [{name}] dropped: {e.Message}");
                }

                FlushCallQueue(e);
                callQueue = new AsyncQueue <CallInfo>(MAX_CALL_QUEUE_LENGTH, true);

                throw;
            }
            finally
            {
                logger.LogDebug($"Removing service client for [{name}] from ServiceManager.");
                ServiceManager.Instance.RemoveServiceServerLinkAsync(this);
            }
        }
コード例 #19
0
        public void RemoveById(long ownerId)
        {
            SetupTls();
            IDInfo idinfo;

            lock ( idInfoMutex )
            {
                if (!idInfo.ContainsKey(ownerId))
                {
                    return;
                }
                idinfo = idInfo[ownerId];
            }
            if (idinfo.id == tls.calling_in_this_thread)
            {
                RemoveAll(ownerId);
            }
            else
            {
                ROS.Debug()($"[{ThisNode.Name}] removeByID w/ WRONG THREAD ID");
                RemoveAll(ownerId);
            }
        }
コード例 #20
0
        public bool initialize(Connection connection)
        {
            ROS.Debug()($"[{ThisNode.Name}] Init transport publisher link: {parent.name }");
            this.connection          = connection;
            connection.DroppedEvent += onConnectionDropped;
            if (connection.transport.getRequiresHeader())
            {
                connection.setHeaderReceivedCallback(onHeaderReceived);
                IDictionary <string, string> header = new Dictionary <string, string>();

                header["topic"]       = parent.name;
                header["md5sum"]      = parent.md5sum;
                header["callerid"]    = ThisNode.Name;
                header["type"]        = parent.datatype;
                header["tcp_nodelay"] = "1";
                connection.writeHeader(header, onHeaderWritten);
            }
            else
            {
                connection.read(4, onMessageLength);
            }
            return(true);
        }
コード例 #21
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);
        }
コード例 #22
0
        private async Task RunServiceLoopAsync(Header header)
        {
            await Task.Yield();

            try
            {
                try
                {
                    await HandleHeader(header).ConfigureAwait(false);
                }
                catch (Exception e)
                {
                    if (ROS.shuttingDown)
                    {
                        await connection.SendHeaderError("ROS node shutting down", cancel).ConfigureAwait(false);
                    }
                    else
                    {
                        ROS.Error()(e.Message);
                        await connection.SendHeaderError(e.Message, cancel).ConfigureAwait(false);
                    }

                    connection.Close(50);

                    throw;
                }

                while (true)
                {
                    cancel.ThrowIfCancellationRequested();

                    // read request
                    int requestLength = await connection.ReadInt32(cancel).ConfigureAwait(false);

                    if (requestLength < 0 || requestLength > Connection.MESSAGE_SIZE_LIMIT)
                    {
                        var errorMessage =
                            $"Message length exceeds limit of {Connection.MESSAGE_SIZE_LIMIT}. Dropping connection.";
                        ROS.Error()(errorMessage);
                        throw new ConnectionError(errorMessage);
                    }

                    byte[] requestBuffer = await connection.ReadBlock(requestLength, cancel).ConfigureAwait(false);

                    try
                    {
                        // process
                        var(result, success) = await parent.ProcessRequest(requestBuffer, this).ConfigureAwait(false);
                        await ProcessResponse(result, success).ConfigureAwait(false);
                    }
                    catch (Exception e)
                    {
                        string errorMessage = "Exception thrown while processing service call: " + e.Message;
                        ROS.Error()(errorMessage);
                        await ProcessResponse(errorMessage, false).ConfigureAwait(false);
                    }

                    if (!persistent)
                    {
                        break;
                    }
                }
            }
            catch (System.IO.EndOfStreamException ex)
            {
                ROS.Debug()("EndOfStreamException during connection handling. Message: {0}, Stacktrace : {1}",
                            ex.ToString(), ex.StackTrace);
            }
            catch (System.IO.IOException ex)
            {
                ROS.Debug()("IOException during connection handling. Message: {0}, Stacktrace : {1}",
                            ex.ToString(), ex.StackTrace);
            }
            catch (Exception ex)
            {
                ROS.Error()("Error during service loop. Error: {0}, Stacktrace: {1}", ex.ToString(), ex.StackTrace);
            }
            finally
            {
                UnregisterServiceLink();
            }
        }
コード例 #23
0
        public bool connect(string host, int port)
        {
            socket        = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            connectedHost = host;
            connectedPort = port;
            if (!setNonBlocking())
            {
                throw new Exception($"[{ThisNode.Name}] Failed to make socket nonblocking");
            }
            setNoDelay(true);

            IPAddress ip;

            if (!IPAddress.TryParse(host, out ip))
            {
                ip = Dns.GetHostAddressesAsync(host).Result.Where(x => !x.ToString().Contains(":")).FirstOrDefault();
                if (ip == null)
                {
                    close();
                    ROS.Error()($"[{ThisNode.Name}] Couldn't resolve host name [{host}]");
                    return(false);
                }
            }

            if (ip == null)
            {
                return(false);
            }

            IPEndPoint ipep = new IPEndPoint(ip, port);

            LocalEndPoint = ipep;
            DateTime connectionAttempted = DateTime.UtcNow;

            IAsyncResult asyncres = socket.BeginConnect(ipep, iar =>
            {
                lock (this)
                {
                    if (socket != null)
                    {
                        try
                        {
                            socket.EndConnect(iar);
                        }
                        catch (Exception e)
                        {
                            ROS.Error()($"[{ThisNode.Name}] {e.ToString()}");
                        }
                    }
                }
            }, null);

            bool completed = false;

            while (ROS.ok && !ROS.shutting_down)
            {
                completed = asyncres.AsyncWaitHandle.WaitOne(10);
                if (completed)
                {
                    break;
                }
                if (DateTime.UtcNow.Subtract(connectionAttempted).TotalSeconds >= 3)
                {
                    ROS.Info()($"[{ThisNode.Name}] Trying to connect for {DateTime.UtcNow.Subtract( connectionAttempted ).TotalSeconds}s\t: {this}");
                    if (!asyncres.AsyncWaitHandle.WaitOne(100))
                    {
                        socket.Close();
                        socket = null;
                    }
                }
            }

            if (!completed || socket == null || !socket.Connected)
            {
                return(false);
            }
            else
            {
                ROS.Debug()($"[{ThisNode.Name}] TcpTransport connection established.");
            }

            return(ROS.ok && initializeSocket());
        }
コード例 #24
0
        private async Task HandleConnection()
        {
            // establish connection
            using (var client = new TcpClient())
            {
                await client.ConnectAsync(host, port).ConfigureAwait(false);

                client.NoDelay = true;

                try
                {
                    this.connection = new Connection(client);

                    // write/read header handshake
                    await WriteHeader().ConfigureAwait(false);

                    var headerFields = await connection.ReadHeader(cancel).ConfigureAwait(false);

                    SetHeader(new Header(headerFields));

                    // connection established
                    this.connected = true;

                    while (!cancel.IsCancellationRequested)
                    {
                        // read message length
                        int length = await connection.ReadInt32(cancel).ConfigureAwait(false);

                        if (length > Connection.MESSAGE_SIZE_LIMIT)
                        {
                            var message =
                                $"Message received in TransportPublisherLink exceeds length limit of {Connection.MESSAGE_SIZE_LIMIT}. Dropping connection";
                            throw new RosException(message);
                        }

                        // read message
                        var messageBuffer = await connection.ReadBlock(length, cancel).ConfigureAwait(false);

                        // deserialize message
                        RosMessage msg = RosMessage.Generate(Parent.DataType);
                        msg.Serialized        = messageBuffer;
                        msg.connection_header = this.Header.Values;
                        HandleMessage(msg);

                        // reset retry delay after first successfully processed message
                        retryDelay = BASE_RETRY_DELAY;
                    }

                    client.Close();
                }
                catch (System.IO.EndOfStreamException ex)
                {
                    ROS.Debug()("EndOfStreamException during connection handling to a publisher. Message: {0}, Stacktrace : {1}",
                                ex.ToString(), ex.StackTrace);
                }
                catch (System.IO.IOException ex)
                {
                    ROS.Debug()("IOException during connection handling to a publisher. Message: {0}, Stacktrace : {1}",
                                ex.ToString(), ex.StackTrace);
                }
                catch (Exception ex)
                {
                    ROS.Error()("Error during connection handling to a publisher. Error: {0}, Stacktrace: {1}",
                                ex.ToString(),
                                ex.StackTrace);
                }
                finally
                {
                    this.connected  = false;
                    this.connection = null;
                }
            }
        }
コード例 #25
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.");
            }
        }
コード例 #26
0
        public bool pubUpdate(IEnumerable <string> publisherUris)
        {
            lock ( shutdown_mutex )
            {
                if (shutting_down || _dropped)
                {
                    return(false);
                }
            }

            bool retval = true;

            ROS.Debug()($"[{ThisNode.Name}] Publisher update for [{name}]");

            var additions = new List <string>();
            List <PublisherLink> subtractions;

            lock ( publisher_links_mutex )
            {
                subtractions = publisher_links.Where(x => !publisherUris.Any(u => urisEqual(x.XmlRpcUri, u))).ToList();
                foreach (string uri in publisherUris)
                {
                    bool found = publisher_links.Any(spc => urisEqual(uri, spc.XmlRpcUri));
                    if (found)
                    {
                        continue;
                    }

                    lock ( pendingConnections )
                    {
                        if (pendingConnections.Any(pc => urisEqual(uri, pc.RemoteUri)))
                        {
                            found = true;
                        }

                        if (!found)
                        {
                            additions.Add(uri);
                        }
                    }
                }
            }
            foreach (PublisherLink link in subtractions)
            {
                if (link.XmlRpcUri != XmlRpcManager.Instance.Uri)
                {
                    ROS.Debug()($"[{ThisNode.Name}] Disconnecting from publisher [{link.CallerID}] of topic [{name}] at [{link.XmlRpcUri}]");
                    link.drop();
                }
                else
                {
                    ROS.Warn()($"[{ThisNode.Name}] Cannot disconnect from self for topic: {name}");
                }
            }

            foreach (string i in additions)
            {
                ROS.Debug()($"[{ThisNode.Name}] Start connecting to {i} for [{name}]");
                if (XmlRpcManager.Instance.Uri != i)
                {
                    retval &= NegotiateConnection(i);
                    //ROS.Debug()("NEGOTIATINGING");
                }
                else
                {
                    ROS.Info()($"[{ThisNode.Name}] Skipping myself ({name}, {XmlRpcManager.Instance.Uri})");
                }
            }
            return(retval);
        }
コード例 #27
0
 private bool ValidateFailed(string method, string errorFormat, params object[] args)
 {
     ROS.Debug()($"[{ThisNode.Name}] XML-RPC Call [{method}] {string.Format(errorFormat, args)} failed validation");
     return(false);
 }