/// <summary> /// Queries <see cref="AppProtocolVersion"/> of given <see cref="BoundPeer"/>. /// </summary> /// <param name="peer">The <see cref="BoundPeer"/> to query /// <see cref="AppProtocolVersion"/>.</param> /// <param name="timeout">Timeout value for request.</param> /// <returns><see cref="AppProtocolVersion"/> of given peer. </returns> public static AppProtocolVersion QueryAppProtocolVersion( this BoundPeer peer, TimeSpan?timeout = null ) { using var dealerSocket = new DealerSocket(ToNetMQAddress(peer)); var key = new PrivateKey(); var ping = new Ping(); var netMQMessageCodec = new NetMQMessageCodec(); NetMQMessage request = netMQMessageCodec.Encode( ping, key, new Peer(key.PublicKey), DateTimeOffset.UtcNow, default ); TimeSpan timeoutNotNull = timeout ?? TimeSpan.FromSeconds(5); if (dealerSocket.TrySendMultipartMessage(timeoutNotNull, request)) { var response = new NetMQMessage(); if (dealerSocket.TryReceiveMultipartMessage(timeoutNotNull, ref response)) { return(AppProtocolVersion.FromToken(response.First.ConvertToString())); } } throw new TimeoutException( $"Peer[{peer}] didn't respond within the specified time[{timeout}]." ); }
private async Task Handler() { while (this.IsRunning) { try { using (var socket = new DealerSocket()) using (this.BackendBuffer = new NetMQQueue <TransportMessage>()) using (var poller = new NetMQPoller() { socket, this.BackendBuffer }) using (var monitor = new NetMQ.Monitoring.NetMQMonitor(socket, $"inproc://monitor.forwarderdevice.backend.{Guid.NewGuid().ToString()}", SocketEvents.Connected | SocketEvents.Disconnected)) { socket.Options.Identity = System.Text.Encoding.ASCII.GetBytes(Guid.NewGuid().ToString().Replace("-", "").ToLowerInvariant()); socket.ReceiveReady += (sender, e) => { try { var netmqMessage = new NetMQMessage(); if (e.Socket.TryReceiveMultipartMessage(ref netmqMessage)) { var message = netmqMessage.ToMessage(); this.ForwarderDevice.OnBackendReceived(message); this.ForwarderDevice.frontendBuffer.Enqueue(message); } } catch (Exception ex) { this.ForwarderDevice.OnDiagnosticMessage(ex.Message + ": " + ex.StackTrace); } }; this.BackendBuffer.ReceiveReady += (sender, e) => { try { while (this.BackendBuffer.TryDequeue(out TransportMessage message, TimeSpan.Zero)) { this.ForwarderDevice.OnFrontendForwarded(message); this.ForwarderDevice.OnDiagnosticMessage("Forwarding message to " + this.Endpoint.ToConnectionString()); if (!socket.TrySendMultipartMessage(TimeSpan.FromSeconds(1), message.ToNetMQMessage())) { this.ForwarderDevice.OnDiagnosticMessage("Failed to send message"); } } } catch (Exception ex) { this.ForwarderDevice.OnDiagnosticMessage(ex.Message + ": " + ex.StackTrace); } }; monitor.Connected += (sender, e) => { this.ForwarderDevice.OnDiagnosticMessage($"Dealer socket conntected to {this.Endpoint.ToConnectionString()}"); this.IsConnected = true; }; monitor.Disconnected += (sender, e) => { this.ForwarderDevice.OnDiagnosticMessage($"Dealer socket disconntected from {this.Endpoint.ToConnectionString()}"); this.IsConnected = false; }; this.ForwarderDevice.OnDiagnosticMessage($"Attempting to connect to {this.Endpoint.ToConnectionString()}"); monitor.StartAsync(); monitor.AttachToPoller(poller); var pollerTask = new Task(poller.Run); pollerTask.ContinueWith((Task task) => { var ex = task.Exception; this.ForwarderDevice.OnDiagnosticMessage(ex.Message + ": " + ex.StackTrace); this.IsConnected = false; }, TaskContinuationOptions.OnlyOnFaulted); pollerTask.Start(); socket.Connect(this.Endpoint.ToConnectionString()); var start = DateTime.Now; while (!this.IsConnected) { if ((DateTime.Now - start).TotalMilliseconds > 5000) { throw new Exception($"Connection timeout [{this.ServiceName}]"); } await Task.Delay(1000); } while (this.IsConnected && this.IsRunning) { await Task.Delay(1000); } this.ForwarderDevice.OnDiagnosticMessage("Closing dealer socket..."); poller.StopAsync(); socket.Disconnect(this.Endpoint.ToConnectionString()); monitor.DetachFromPoller(); monitor.Stop(); this.IsConnected = false; } if (this.IsRunning) { await Task.Delay(1000); } } catch (Exception ex) { this.ForwarderDevice.OnDiagnosticMessage(ex.Message + ": " + ex.StackTrace); } } }
public async Task <bool> RunSimulationAsync(Options options, TextWriter logger, CancellationToken token = default) { Logger = logger; try { Id = options.Id; _socket = new DealerSocket(); _socket.Options.Linger = TimeSpan.FromSeconds(30); _socket.Options.Identity = Encoding.ASCII.GetBytes(Id); if (options.Connect) { _socket.Connect(options.URL); } else { _socket.Bind(options.URL); } using (Outgoing = new NetMQQueue <NetMQMessage>()) { using var poller = new NetMQPoller() { _socket, Outgoing }; _socket.ReceiveReady += (sender, e) => { var msg = _socket.ReceiveMultipartMessage(); if (msg.FrameCount < 3) { logger.WriteLine($"Received message with only {msg.FrameCount} frames."); return; } var type = msg[1].ConvertToString(); logger.WriteLine($"Received {type} message."); switch (type) { case "crane": OnCraneMessageReceived(msg[2].Buffer); break; case "sim": OnSimMessageReceived(msg[2].Buffer); break; default: //Console.WriteLine($"Received message with unmapped type {type}"); break; } }; Outgoing.ReceiveReady += (sender, e) => { var msg = Outgoing.Dequeue(); if (_socket.TrySendMultipartMessage(TimeSpan.FromMinutes(1), msg)) // Note that for policyruns (virtual time) a lot of events are generated { logger.WriteLine($"Sent {msg[1].ConvertToString()} message."); } //else logger.WriteLine($"Discarded outgoing {msg[1].ConvertToString()} message."); }; if (!options.RunSync || options.Connect) { poller.RunAsync(); } if (!string.IsNullOrEmpty(options.SettingsPath)) { if (options.SettingsPath.Equals("Default", StringComparison.OrdinalIgnoreCase)) { logger.WriteLine("Using default settings"); _settingsReceived.SetResult(GetDefaultSettings()); } else { logger.WriteLine($"Reading settings from {options.SettingsPath}"); _settingsReceived.SetResult(File.ReadAllBytes(options.SettingsPath)); } } var result = false; try { if (!options.RunSync) { result = await RunSimulationAsync(await _settingsReceived.Task, options.PolicyRun); // wait until the outgoing queue is cleared var remaining = Outgoing.Count; while (remaining > 0) { await Task.Delay(1000, token); if (Outgoing.Count == remaining) { break; // assume nobody is listening for world states } remaining = Outgoing.Count; } } else { result = RunSimulation(await _settingsReceived.Task, options.SyncURL, options.Id); } } finally { poller.Stop(); } return(result); } } finally { DisposeSocket(); } }