/// <summary> /// <para>Events:</para> /// <para>@emits transportclose</para> /// <para>@emits @close</para> /// <para>Observer events:</para> /// <para>@emits close</para> /// </summary> /// <param name="loggerFactory"></param> /// <param name="dataProducerInternalData"></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 DataProducer(ILoggerFactory loggerFactory, DataProducerInternalData dataProducerInternalData, SctpStreamParameters sctpStreamParameters, string label, string protocol, Channel channel, PayloadChannel payloadChannel, Dictionary <string, object>?appData ) { _logger = loggerFactory.CreateLogger <DataProducer>(); // Internal _internal = dataProducerInternalData; // Data SctpStreamParameters = sctpStreamParameters; Label = label; Protocol = protocol; _channel = channel; _payloadChannel = payloadChannel; AppData = appData; HandleWorkerNotifications(); }
/// <summary> /// Create a DataProducer. /// </summary> /// <returns></returns> public async Task <DataProducer> ProduceDataAsync(DataProducerOptions dataProducerOptions) { _logger.LogDebug($"ProduceDataAsync() | Transport:{TransportId}"); if (!dataProducerOptions.Id.IsNullOrWhiteSpace() && DataProducers.ContainsKey(dataProducerOptions.Id !)) { throw new Exception($"A DataProducer with same id {dataProducerOptions.Id} already exists"); } if (dataProducerOptions.Label.IsNullOrWhiteSpace()) { dataProducerOptions.Label = string.Empty; } if (dataProducerOptions.Protocol.IsNullOrWhiteSpace()) { dataProducerOptions.Protocol = string.Empty; } DataProducerType type; // If this is not a DirectTransport, sctpStreamParameters are required. // TODO: (alby) 反模式 if (GetType() != typeof(DirectTransport)) { type = DataProducerType.Sctp; // This may throw. ORTC.ValidateSctpStreamParameters(dataProducerOptions.SctpStreamParameters !); } // If this is a DirectTransport, sctpStreamParameters must not be given. else { type = DataProducerType.Direct; if (dataProducerOptions.SctpStreamParameters != null) { _logger.LogWarning($"ProduceDataAsync() | Transport:{TransportId} sctpStreamParameters are ignored when producing data on a DirectTransport"); } } var @internal = new DataProducerInternalData ( Internal.RouterId, Internal.TransportId, dataProducerOptions.Id.NullOrWhiteSpaceReplace(Guid.NewGuid().ToString()) ); var reqData = new { Type = type.GetEnumMemberValue(), dataProducerOptions.SctpStreamParameters, Label = dataProducerOptions.Label !, Protocol = dataProducerOptions.Protocol ! }; var resData = await Channel.RequestAsync(MethodId.TRANSPORT_PRODUCE_DATA, @internal, reqData); var responseData = JsonSerializer.Deserialize <TransportDataProduceResponseData>(resData !, ObjectExtensions.DefaultJsonSerializerOptions) !; var dataProducer = new DataProducer(_loggerFactory, @internal, responseData.SctpStreamParameters, responseData.Label !, responseData.Protocol !, Channel, PayloadChannel, AppData); dataProducer.On("@close", async(_, _) => { await DataProducersLock.WaitAsync(); try { DataProducers.Remove(dataProducer.DataProducerId); } catch (Exception ex) { _logger.LogError(ex, "@close"); } finally { DataProducersLock.Set(); } Emit("@dataproducerclose", dataProducer); }); await DataProducersLock.WaitAsync(); try { DataProducers[dataProducer.DataProducerId] = dataProducer; } catch (Exception ex) { _logger.LogError(ex, "ProduceDataAsync()"); } finally { DataProducersLock.Set(); } Emit("@newdataproducer", dataProducer); // Emit observer event. Observer.Emit("newdataproducer", dataProducer); return(dataProducer); }