Пример #1
0
        /// <summary>
        /// Create a DataConsumer.
        /// </summary>
        /// <param name="dataConsumerOptions"></param>
        /// <returns></returns>
        public async Task <DataConsumer> ConsumeDataAsync(DataConsumerOptions dataConsumerOptions)
        {
            _logger.LogDebug($"ConsumeDataAsync() | Transport:{TransportId}");

            if (dataConsumerOptions.DataProducerId.IsNullOrWhiteSpace())
            {
                throw new Exception("Missing dataProducerId");
            }

            var dataProducer = GetDataProducerById(dataConsumerOptions.DataProducerId);

            if (dataProducer == null)
            {
                throw new Exception($"DataProducer with id {dataConsumerOptions.DataProducerId} not found");
            }

            DataProducerType     type;
            SctpStreamParameters?sctpStreamParameters = null;
            int sctpStreamId = -1;

            // If this is not a DirectTransport, use sctpStreamParameters from the
            // DataProducer (if type 'sctp') unless they are given in method parameters.
            // TODO: (alby)反模式
            if (GetType() != typeof(DirectTransport))
            {
                type = DataProducerType.Sctp;

                sctpStreamParameters = dataProducer.SctpStreamParameters.DeepClone <SctpStreamParameters>();
                // This may throw.
                lock (_sctpStreamIdsLock)
                {
                    sctpStreamId = GetNextSctpStreamId();

                    if (_sctpStreamIds == null || sctpStreamId > _sctpStreamIds.Length - 1)
                    {
                        throw new IndexOutOfRangeException(nameof(_sctpStreamIds));
                    }
                    _sctpStreamIds[sctpStreamId]  = 1;
                    sctpStreamParameters.StreamId = sctpStreamId;
                }
            }
            // If this is a DirectTransport, sctpStreamParameters must not be used.
            else
            {
                type = DataProducerType.Direct;

                if (dataConsumerOptions.Ordered.HasValue ||
                    dataConsumerOptions.MaxPacketLifeTime.HasValue ||
                    dataConsumerOptions.MaxRetransmits.HasValue
                    )
                {
                    _logger.LogWarning("ConsumeDataAsync() | Ordered, maxPacketLifeTime and maxRetransmits are ignored when consuming data on a DirectTransport");
                }
            }

            var @internal = new DataConsumerInternalData
                            (
                Internal.RouterId,
                Internal.TransportId,
                dataConsumerOptions.DataProducerId,
                Guid.NewGuid().ToString()
                            );

            var reqData = new
            {
                Type = type.GetEnumStringValue(),
                SctpStreamParameters = sctpStreamParameters,
                dataProducer.Label,
                dataProducer.Protocol
            };

            var status = await Channel.RequestAsync(MethodId.TRANSPORT_CONSUME_DATA, @internal, reqData);

            var responseData = JsonConvert.DeserializeObject <TransportDataConsumeResponseData>(status !);

            var dataConsumer = new DataConsumer(_loggerFactory,
                                                @internal,
                                                responseData.SctpStreamParameters,
                                                responseData.Label,
                                                responseData.Protocol,
                                                Channel,
                                                PayloadChannel,
                                                AppData);

            dataConsumer.On("@close", async _ =>
            {
                await DataConsumersLock.WaitAsync();
                try
                {
                    DataConsumers.Remove(dataConsumer.DataConsumerId);
                    lock (_sctpStreamIdsLock)
                    {
                        if (_sctpStreamIds != null && sctpStreamId >= 0)
                        {
                            _sctpStreamIds[sctpStreamId] = 0;
                        }
                    }
                }
                finally
                {
                    DataConsumersLock.Set();
                }
            });

            dataConsumer.On("@dataproducerclose", async _ =>
            {
                await DataConsumersLock.WaitAsync();
                try
                {
                    DataConsumers.Remove(dataConsumer.DataConsumerId);
                    lock (_sctpStreamIdsLock)
                    {
                        if (_sctpStreamIds != null && sctpStreamId >= 0)
                        {
                            _sctpStreamIds[sctpStreamId] = 0;
                        }
                    }
                }
                finally
                {
                    DataConsumersLock.Set();
                }
            });

            await DataConsumersLock.WaitAsync();

            try
            {
                DataConsumers[dataConsumer.DataConsumerId] = dataConsumer;
            }
            finally
            {
                DataConsumersLock.Set();
            }

            // Emit observer event.
            Observer.Emit("newdataconsumer", dataConsumer);

            return(dataConsumer);
        }