private async ValueTask OnOffer(int channelId, Memory <byte> payloadBuffer, CancellationToken cancellationToken) { await ReadToFillAsync(this.stream, payloadBuffer, throwOnEmpty : true, cancellationToken).ConfigureAwait(false); string name = DecodeString(payloadBuffer); var channel = new Channel(this, channelId, name, channelOptions: DefaultChannelOptions); bool acceptingChannelAlreadyPresent = false; ChannelOptions options = null; lock (this.syncObject) { if (name != null && this.acceptingChannels.TryGetValue(name, out var acceptingChannels)) { while (acceptingChannels.Count > 0) { var candidate = acceptingChannels.Dequeue(); if (candidate.TrySetResult(channel)) { if (this.TraceSource.Switch.ShouldTrace(TraceEventType.Information)) { this.TraceSource.TraceEvent(TraceEventType.Information, (int)TraceEventId.ChannelOfferReceived, "Remote party offers channel {1} \"{0}\" which matches up with a pending " + nameof(this.AcceptChannelAsync), name, channelId); } acceptingChannelAlreadyPresent = true; options = (ChannelOptions)candidate.Task.AsyncState; break; } } } if (!acceptingChannelAlreadyPresent) { if (name != null) { if (this.TraceSource.Switch.ShouldTrace(TraceEventType.Information)) { this.TraceSource.TraceEvent(TraceEventType.Information, (int)TraceEventId.ChannelOfferReceived, "Remote party offers channel {1} \"{0}\" which has no pending " + nameof(this.AcceptChannelAsync), name, channelId); } if (!this.channelsOfferedByThemByName.TryGetValue(name, out var offeredChannels)) { this.channelsOfferedByThemByName.Add(name, offeredChannels = new Queue <Channel>()); } offeredChannels.Enqueue(channel); } else { if (this.TraceSource.Switch.ShouldTrace(TraceEventType.Information)) { this.TraceSource.TraceEvent(TraceEventType.Information, (int)TraceEventId.ChannelOfferReceived, "Remote party offers anonymous channel {0}", channelId); } } } this.openChannels.Add(channelId, channel); } if (acceptingChannelAlreadyPresent) { this.AcceptChannelOrThrow(channel, options); } var args = new ChannelOfferEventArgs(channel.Id, channel.Name, acceptingChannelAlreadyPresent); this.OnChannelOffered(args); }
/// <summary> /// Raises the <see cref="ChannelOffered"/> event. /// </summary> /// <param name="args">The arguments to pass to the event handlers.</param> protected virtual void OnChannelOffered(ChannelOfferEventArgs args) => this.ChannelOffered?.Invoke(this, args);