/// <summary> /// This method initiates the reverse connection setup. /// It creates a new message and sends it via relay to the unreachable peer /// which then connects to this peer again. After the connect message from the /// unreachable peer, this peer will send the original message and its content /// directly. /// </summary> /// <param name="handler"></param> /// <param name="tcsResponse"></param> /// <param name="message"></param> /// <param name="channelCreator"></param> /// <param name="connectTimeoutMillis"></param> /// <param name="peerConnection"></param> /// <param name="timeoutHandler"></param> private async Task HandleRconAsync(IInboundHandler handler, TaskCompletionSource <Message.Message> tcsResponse, Message.Message message, ChannelCreator channelCreator, int connectTimeoutMillis, PeerConnection peerConnection, TimeoutFactory timeoutHandler) { message.SetKeepAlive(true); Logger.Debug("Initiate reverse connection setup to peer with address {0}.", message.Recipient); var rconMessage = CreateRconMessage(message); // TODO works? // cache the original message until the connection is established _cachedRequests.AddOrUpdate(message.MessageId, tcsResponse, (i, source) => tcsResponse); // wait for response (whether the reverse connection setup was successful) var tcsRconResponse = new TaskCompletionSource <Message.Message>(rconMessage); // .NET-specific: specify and use a RconInboundHandler class var rconInboundHandler = new RconInboundHandler(tcsRconResponse, tcsResponse); // send reverse connection request instead of normal message await SendTcpAsync(rconInboundHandler, tcsRconResponse, rconMessage, channelCreator, connectTimeoutMillis, connectTimeoutMillis, peerConnection); }