Exemplo n.º 1
0
        /// <summary>
        /// <para>Events:</para>
        /// <para>@emits transportclose</para>
        /// <para>@emits dataproducerclose</para>
        /// <para>@emits message - (message: Buffer, ppid: number)</para>
        /// <para>@emits sctpsendbufferfull</para>
        /// <para>@emits bufferedamountlow - (bufferedAmount: number)</para>
        /// <para>@emits @close</para>
        /// <para>@emits @dataproducerclose</para>
        /// <para>Observer events:</para>
        /// <para>@emits close</para>
        /// </summary>
        /// <param name="loggerFactory"></param>
        /// <param name="dataConsumerInternalData"></param>
        /// <param name="sctpStreamParameters"></param>
        /// <param name="label"></param>
        /// <param name="protocol"></param>
        /// <param name="channel"></param>
        /// <param name="payloadChannel"></param>
        /// <param name="appData"></param>
        public DataConsumer(ILoggerFactory loggerFactory,
                            DataConsumerInternalData dataConsumerInternalData,
                            SctpStreamParameters sctpStreamParameters,
                            string label,
                            string protocol,
                            Channel channel,
                            PayloadChannel payloadChannel,
                            Dictionary <string, object>?appData
                            )
        {
            _logger = loggerFactory.CreateLogger <DataConsumer>();

            // Internal
            _internal = dataConsumerInternalData;

            // Data
            SctpStreamParameters = sctpStreamParameters;
            Label    = label;
            Protocol = protocol;

            _channel        = channel;
            _payloadChannel = payloadChannel;
            AppData         = appData;

            HandleWorkerNotifications();
        }
Exemplo n.º 2
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.GetEnumMemberValue(),
                SctpStreamParameters = sctpStreamParameters,
                dataProducer.Label,
                dataProducer.Protocol
            };

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

            var responseData = JsonSerializer.Deserialize <TransportDataConsumeResponseData>(resData !, ObjectExtensions.DefaultJsonSerializerOptions) !;

            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;
                        }
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "@close");
                }
                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;
                        }
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "@dataproducerclose");
                }
                finally
                {
                    DataConsumersLock.Set();
                }
            });

            await DataConsumersLock.WaitAsync();

            try
            {
                DataConsumers[dataConsumer.DataConsumerId] = dataConsumer;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "ConsumeDataAsync()");
            }
            finally
            {
                DataConsumersLock.Set();
            }

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

            return(dataConsumer);
        }