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()); }
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); }
/// <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); }