public void seek(double position) { IConnection connection = FluorineContext.Current.Connection; if (!(connection is IStreamCapableConnection)) { return; } IStreamCapableConnection streamConnection = connection as IStreamCapableConnection; int streamId = GetCurrentStreamId(); IClientStream stream = streamConnection.GetStreamById(streamId); if (stream == null || !(stream is ISubscriberStream)) { return; } ISubscriberStream subscriberStream = stream as ISubscriberStream; try { subscriberStream.Seek((int)position); } catch (NotSupportedException ex) { StatusASO seekFailed = new StatusASO(StatusASO.NS_SEEK_FAILED); seekFailed.clientid = streamId; seekFailed.description = "The stream doesn't support seeking."; seekFailed.level = "error"; seekFailed.details = ex.Message; // FIXME: there should be a direct way to send the status RtmpChannel channel = (streamConnection as RtmpConnection).GetChannel((byte)(4 + ((streamId - 1) * 5))); channel.SendStatus(seekFailed); } }
public void seek(double position) { IConnection connection = FluorineContext.Current.Connection; if (connection is IStreamCapableConnection) { IStreamCapableConnection connection2 = connection as IStreamCapableConnection; int currentStreamId = this.GetCurrentStreamId(); IClientStream streamById = connection2.GetStreamById(currentStreamId); if ((streamById != null) && (streamById is ISubscriberStream)) { ISubscriberStream stream2 = streamById as ISubscriberStream; try { stream2.Seek((int)position); } catch (NotSupportedException exception) { StatusASO status = new StatusASO("NetStream.Seek.Failed") { clientid = currentStreamId, description = "The stream doesn't support seeking.", level = "error", details = exception.Message }; (connection2 as RtmpConnection).GetChannel((byte)(4 + ((currentStreamId - 1) * 5))).SendStatus(status); } } } }
public void publish(bool dontStop) { if (!dontStop) { IConnection connection = FluorineContext.Current.Connection; if (connection is IStreamCapableConnection) { IStreamCapableConnection connection2 = connection as IStreamCapableConnection; int currentStreamId = this.GetCurrentStreamId(); IClientStream streamById = connection2.GetStreamById(currentStreamId); if (streamById is IBroadcastStream) { IBroadcastStream stream2 = streamById as IBroadcastStream; if (stream2.PublishedName != null) { IBroadcastScope broadcastScope = this.GetBroadcastScope(connection.Scope, stream2.PublishedName); if (broadcastScope != null) { broadcastScope.Unsubscribe(stream2.Provider); if (connection is BaseConnection) { (connection as BaseConnection).UnregisterBasicScope(broadcastScope); } } stream2.Close(); connection2.DeleteStreamById(currentStreamId); } } } } }
public void pause(bool pausePlayback, double position) { IConnection connection = FluorineContext.Current.Connection; if (!(connection is IStreamCapableConnection)) { return; } IStreamCapableConnection streamConnection = connection as IStreamCapableConnection; int streamId = GetCurrentStreamId(); IClientStream stream = streamConnection.GetStreamById(streamId); if (stream == null || !(stream is ISubscriberStream)) { return; } ISubscriberStream subscriberStream = stream as ISubscriberStream; if (pausePlayback) { subscriberStream.Pause((int)position); } else { subscriberStream.Resume((int)position); } }
public void closeStream() { IConnection connection = FluorineContext.Current.Connection; if (!(connection is IStreamCapableConnection)) { return; } IClientStream stream = (connection as IStreamCapableConnection).GetStreamById(GetCurrentStreamId()); if (stream != null) { if (stream is IClientBroadcastStream) { IClientBroadcastStream bs = stream as IClientBroadcastStream; IBroadcastScope bsScope = GetBroadcastScope(connection.Scope, bs.PublishedName); if (bsScope != null && connection is BaseConnection) { (connection as BaseConnection).UnregisterBasicScope(bsScope); } } stream.Close(); } (connection as IStreamCapableConnection).DeleteStreamById(GetCurrentStreamId()); }
protected void RegisterStream(IClientStream stream) { lock (((ICollection)this._streams).SyncRoot) { this._streams[stream.StreamId - 1] = stream; } }
public void publish(bool dontStop) { if (!dontStop) { IConnection connection = FluorineContext.Current.Connection; if (!(connection is IStreamCapableConnection)) { return; } IStreamCapableConnection streamConnection = connection as IStreamCapableConnection; int streamId = GetCurrentStreamId(); IClientStream stream = streamConnection.GetStreamById(streamId); if (!(stream is IBroadcastStream)) { return; } IBroadcastStream bs = stream as IBroadcastStream; if (bs.PublishedName == null) { return; } IBroadcastScope bsScope = GetBroadcastScope(connection.Scope, bs.PublishedName); if (bsScope != null) { bsScope.Unsubscribe(bs.Provider); if (connection is BaseConnection) { (connection as BaseConnection).UnregisterBasicScope(bsScope); } } bs.Close(); streamConnection.DeleteStreamById(streamId); } }
public void OnOOBControlMessage(IMessageComponent source, IPipe pipe, OOBControlMessage oobCtrlMsg) { if ("ConnectionConsumer".Equals(oobCtrlMsg.Target)) { if ("pendingCount".Equals(oobCtrlMsg.ServiceName)) { oobCtrlMsg.Result = this._connection.PendingMessages; } else if ("pendingVideoCount".Equals(oobCtrlMsg.ServiceName)) { IClientStream streamByChannelId = null; if (this._connection is IStreamCapableConnection) { streamByChannelId = (this._connection as IStreamCapableConnection).GetStreamByChannelId(this._video.ChannelId); } if (streamByChannelId != null) { oobCtrlMsg.Result = this._connection.GetPendingVideoMessages(streamByChannelId.StreamId); } else { oobCtrlMsg.Result = 0L; } } else if ("writeDelta".Equals(oobCtrlMsg.ServiceName)) { long num = 0L; IBWControllable parentBWControllable = this._connection as IBWControllable; while ((parentBWControllable != null) && (parentBWControllable.BandwidthConfiguration == null)) { parentBWControllable = parentBWControllable.GetParentBWControllable(); } if ((parentBWControllable != null) && (parentBWControllable.BandwidthConfiguration != null)) { IBandwidthConfigure bandwidthConfiguration = parentBWControllable.BandwidthConfiguration; if (bandwidthConfiguration is IConnectionBWConfig) { num = (bandwidthConfiguration as IConnectionBWConfig).DownstreamBandwidth / 8L; } } if (num <= 0L) { num = 0x1e000L; } oobCtrlMsg.Result = new long[] { this._connection.WrittenBytes - this._connection.ClientBytesRead, num / 2L }; } else if ("chunkSize".Equals(oobCtrlMsg.ServiceName)) { int num2 = (int)oobCtrlMsg.ServiceParameterMap["chunkSize"]; if (num2 != this._chunkSize) { this._chunkSize = num2; ChunkSize message = new ChunkSize(this._chunkSize); this._connection.GetChannel(2).Write(message); } } } }
public IMessageOutput GetConsumerOutput(IClientStream stream) { IStreamCapableConnection streamConnection = stream.Connection; if (streamConnection == null || !(streamConnection is RtmpConnection)) return null; RtmpConnection connection = streamConnection as RtmpConnection; // TODO Better manage channels. // now we use OutputStream as a channel wrapper. OutputStream outputStream = connection.CreateOutputStream(stream.StreamId); IPipe pipe = new InMemoryPushPushPipe(); pipe.Subscribe(new ConnectionConsumer(connection, outputStream.Video.ChannelId, outputStream.Audio.ChannelId, outputStream.Data.ChannelId), null); return pipe; }
public void Write(IRtmpEvent message) { IClientStream streamByChannelId = null; if (this._connection is IStreamCapableConnection) { streamByChannelId = (this._connection as IStreamCapableConnection).GetStreamByChannelId(this._channelId); } if ((this._channelId <= 3) || (streamByChannelId != null)) { int streamId = (streamByChannelId == null) ? 0 : streamByChannelId.StreamId; this.Write(message, streamId); } }
public void receiveVideo(bool receive) { IConnection connection = FluorineContext.Current.Connection; if (connection is IStreamCapableConnection) { IStreamCapableConnection connection2 = connection as IStreamCapableConnection; int currentStreamId = this.GetCurrentStreamId(); IClientStream streamById = connection2.GetStreamById(currentStreamId); if ((streamById != null) && (streamById is ISubscriberStream)) { (streamById as ISubscriberStream).ReceiveVideo(receive); } } }
public IMessageOutput GetConsumerOutput(IClientStream stream) { IStreamCapableConnection connection = stream.Connection; if (!((connection != null) && (connection is RtmpConnection))) { return(null); } RtmpConnection connection2 = connection as RtmpConnection; OutputStream stream2 = connection2.CreateOutputStream(stream.StreamId); IPipe pipe = new InMemoryPushPushPipe(); pipe.Subscribe(new ConnectionConsumer(connection2, stream2.Video.ChannelId, stream2.Audio.ChannelId, stream2.Data.ChannelId), null); return(pipe); }
public override void MessageSent(RtmpConnection connection, object message) { base.MessageSent(connection, message); RtmpPacket packet = message as RtmpPacket; int channelId = packet.Header.ChannelId; IClientStream streamByChannelId = null; if (connection is IStreamCapableConnection) { streamByChannelId = (connection as IStreamCapableConnection).GetStreamByChannelId(channelId); } if ((streamByChannelId != null) && (streamByChannelId is PlaylistSubscriberStream)) { (streamByChannelId as PlaylistSubscriberStream).Written(packet.Message); } }
/// <summary> /// Writes packet from event data to the RTMP connection. /// </summary> /// <param name="message">Event data.</param> public void Write(IRtmpEvent message) { IClientStream stream = null; if (_connection is IStreamCapableConnection) { stream = (_connection as IStreamCapableConnection).GetStreamByChannelId(_channelId); } if (_channelId > 3 && stream == null) { //Stream doesn't exist any longer, discarding message return; } int streamId = (stream == null) ? 0 : stream.StreamId; Write(message, streamId); }
public void play(bool dontStop) { if (!dontStop) { IConnection connection = FluorineContext.Current.Connection; if (connection is IStreamCapableConnection) { IStreamCapableConnection connection2 = connection as IStreamCapableConnection; int currentStreamId = this.GetCurrentStreamId(); IClientStream streamById = connection2.GetStreamById(currentStreamId); if (streamById != null) { streamById.Stop(); } } } }
public override void MessageSent(RtmpConnection connection, object message) { base.MessageSent(connection, message); RtmpPacket sent = message as RtmpPacket; int channelId = sent.Header.ChannelId; IClientStream stream = null; if (connection is IStreamCapableConnection) { stream = (connection as IStreamCapableConnection).GetStreamByChannelId(channelId); } // XXX we'd better use new event model for notification if (stream != null && (stream is PlaylistSubscriberStream)) { (stream as PlaylistSubscriberStream).Written(sent.Message); } }
protected override void OnPing(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, Ping ping) { switch (ping.Value1) { case 3: { if (ping.Value2 == 0) { log.Warn("Unhandled ping: " + ping); break; } IClientStream streamById = null; if (connection is IStreamCapableConnection) { streamById = (connection as IStreamCapableConnection).GetStreamById(ping.Value2); } int bufferDuration = ping.Value3; if (streamById == null) { if (connection is RtmpServerConnection) { (connection as RtmpServerConnection).RememberStreamBufferDuration(ping.Value2, bufferDuration); } if (log.get_IsInfoEnabled()) { log.Info("Remembering client buffer on stream: " + bufferDuration); } break; } streamById.SetClientBufferDuration(bufferDuration); if (log.get_IsInfoEnabled()) { log.Info("Setting client buffer on stream: " + bufferDuration); } break; } case 7: connection.PingReceived(ping); break; default: log.Warn("Unhandled ping: " + ping); break; } }
public IMessageOutput GetConsumerOutput(IClientStream stream) { IStreamCapableConnection streamConnection = stream.Connection; if (streamConnection == null || !(streamConnection is RtmpConnection)) { return(null); } RtmpConnection connection = streamConnection as RtmpConnection; // TODO Better manage channels. // now we use OutputStream as a channel wrapper. OutputStream outputStream = connection.CreateOutputStream(stream.StreamId); IPipe pipe = new InMemoryPushPushPipe(); pipe.Subscribe(new ConnectionConsumer(connection, outputStream.Video.ChannelId, outputStream.Audio.ChannelId, outputStream.Data.ChannelId), null); return(pipe); }
public void DeferredClose() { lock (base.SyncRoot) { if (this._keepAliveJobName != null) { (base.Scope.GetService(typeof(ISchedulingService)) as ISchedulingService).RemoveScheduledJob(this._keepAliveJobName); this._keepAliveJobName = null; } if (!base.IsDisposed && !this.IsDisconnected) { this._state = 0; IStreamService scopeService = ScopeUtils.GetScopeService(base.Scope, typeof(IStreamService)) as IStreamService; if (scopeService != null) { lock (((ICollection)this._streams).SyncRoot) { IClientStream[] array = new IClientStream[this._streams.Count]; this._streams.Values.CopyTo(array, 0); foreach (IClientStream stream in array) { if (stream != null) { if (log.get_IsDebugEnabled()) { log.Debug("Closing stream: " + stream.StreamId); } scopeService.deleteStream(this, stream.StreamId); this._streamCount--; } } this._streams.Clear(); } } if (((this._bwContext != null) && (base.Scope != null)) && (base.Scope.Context != null)) { (base.Scope.GetService(typeof(IBWControlService)) as IBWControlService).UnregisterBWControllable(this._bwContext); this._bwContext = null; } base.Close(); this._rtmpServer.OnConnectionClose(this); this._rtmpNetworkStream.Close(); } } }
protected override void OnPing(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, Ping ping) { switch (ping.PingType) { case Ping.ClientBuffer: IClientStream stream = null; // Get the stream id int streamId = ping.Value2; // Get requested buffer size in milliseconds int buffer = ping.Value3; if (streamId != 0) { // The client wants to set the buffer time stream = connection.GetStreamById(streamId); if (stream != null) { stream.SetClientBufferDuration(buffer); if (log.IsDebugEnabled) { log.Debug(string.Format("Client sent a buffer size: {0} ms for stream id: {1}", buffer, streamId)); } } } // Catch-all to make sure buffer size is set if (stream == null) { // Remember buffer time until stream is created connection.RememberStreamBufferDuration(streamId, buffer); if (log.IsDebugEnabled) { log.Debug(string.Format("Remembering client buffer size: {0} on stream id: {1} ", buffer, streamId)); } } break; case Ping.PongServer: // This is the response to an IConnection.Ping request connection.PingReceived(ping); break; default: log.Warn("Unhandled ping: " + ping); break; } }
public void play(bool dontStop) { if (!dontStop) { IConnection connection = FluorineContext.Current.Connection; if (!(connection is IStreamCapableConnection)) { return; } IStreamCapableConnection streamConnection = connection as IStreamCapableConnection; int streamId = GetCurrentStreamId(); IClientStream stream = streamConnection.GetStreamById(streamId); if (stream != null) { stream.Stop(); } } }
public void deleteStream(IStreamCapableConnection connection, int streamId) { IClientStream stream = connection.GetStreamById(streamId); if (stream != null) { if (stream is IClientBroadcastStream) { IClientBroadcastStream bs = stream as IClientBroadcastStream; IBroadcastScope bsScope = GetBroadcastScope(connection.Scope, bs.PublishedName); if (bsScope != null && connection is BaseConnection) { (connection as BaseConnection).UnregisterBasicScope(bsScope); } } stream.Close(); } connection.UnreserveStreamId(streamId); }
public void deleteStream(IStreamCapableConnection connection, int streamId) { IClientStream streamById = connection.GetStreamById(streamId); if (streamById != null) { if (streamById is IClientBroadcastStream) { IClientBroadcastStream stream2 = streamById as IClientBroadcastStream; IBroadcastScope broadcastScope = this.GetBroadcastScope(connection.Scope, stream2.PublishedName); if ((broadcastScope != null) && (connection is BaseConnection)) { (connection as BaseConnection).UnregisterBasicScope(broadcastScope); } } streamById.Close(); } connection.UnreserveStreamId(streamId); }
public void receiveAudio(bool receive) { IConnection connection = FluorineContext.Current.Connection; if (!(connection is IStreamCapableConnection)) { return; } IStreamCapableConnection streamConnection = connection as IStreamCapableConnection; int streamId = GetCurrentStreamId(); IClientStream stream = streamConnection.GetStreamById(streamId); if (stream == null || !(stream is ISubscriberStream)) { return; } ISubscriberStream subscriberStream = stream as ISubscriberStream; subscriberStream.ReceiveAudio(receive); }
public void closeStream() { IConnection connection = FluorineContext.Current.Connection; if (connection is IStreamCapableConnection) { IClientStream streamById = (connection as IStreamCapableConnection).GetStreamById(this.GetCurrentStreamId()); if (streamById != null) { if (streamById is IClientBroadcastStream) { IClientBroadcastStream stream2 = streamById as IClientBroadcastStream; IBroadcastScope broadcastScope = this.GetBroadcastScope(connection.Scope, stream2.PublishedName); if ((broadcastScope != null) && (connection is BaseConnection)) { (connection as BaseConnection).UnregisterBasicScope(broadcastScope); } } streamById.Close(); } (connection as IStreamCapableConnection).DeleteStreamById(this.GetCurrentStreamId()); } }
public void pause(bool pausePlayback, double position) { IConnection connection = FluorineContext.Current.Connection; if (connection is IStreamCapableConnection) { IStreamCapableConnection connection2 = connection as IStreamCapableConnection; int currentStreamId = this.GetCurrentStreamId(); IClientStream streamById = connection2.GetStreamById(currentStreamId); if ((streamById != null) && (streamById is ISubscriberStream)) { ISubscriberStream stream2 = streamById as ISubscriberStream; if (pausePlayback) { stream2.Pause((int)position); } else { stream2.Resume((int)position); } } } }
/// <summary> /// Message recieved. /// </summary> /// <param name="connection">Connection object.</param> /// <param name="obj">Message object.</param> public void MessageReceived(RtmpConnection connection, object obj) { IRtmpEvent message = null; RtmpPacket packet = null; RtmpHeader header = null; RtmpChannel channel = null; IClientStream stream = null; try { packet = obj as RtmpPacket; message = packet.Message; header = packet.Header; channel = connection.GetChannel(header.ChannelId); if (connection is IStreamCapableConnection) { stream = (connection as IStreamCapableConnection).GetStreamById(header.StreamId); } // Support stream ids #if !SILVERLIGHT FluorineContext.ValidateContext(); FluorineContext.Current.Connection.SetAttribute(FluorineContext.FluorineStreamIdKey, header.StreamId); #endif // Increase number of received messages connection.MessageReceived(); #if !SILVERLIGHT if (log != null && log.IsDebugEnabled) { log.Debug("RtmpConnection message received, type = " + header.DataType); } #endif if (message != null) { message.Source = connection; } switch (header.DataType) { case Constants.TypeInvoke: OnInvoke(connection, channel, header, message as Invoke); if (message.Header.StreamId != 0 && (message as Invoke).ServiceCall.ServiceName == null && (message as Invoke).ServiceCall.ServiceMethodName == BaseRtmpHandler.ACTION_PUBLISH) { if (stream != null) //Dispatch if stream was created { (stream as IEventDispatcher).DispatchEvent(message); } } break; case Constants.TypeFlexInvoke: OnFlexInvoke(connection, channel, header, message as FlexInvoke); if (message.Header.StreamId != 0 && (message as Invoke).ServiceCall.ServiceName == null && (message as Invoke).ServiceCall.ServiceMethodName == BaseRtmpHandler.ACTION_PUBLISH) { if (stream != null) //Dispatch if stream was created { (stream as IEventDispatcher).DispatchEvent(message); } } break; case Constants.TypeNotify: // just like invoke, but does not return if ((message as Notify).Data != null && stream != null) { // Stream metadata (stream as IEventDispatcher).DispatchEvent(message); } else { OnInvoke(connection, channel, header, message as Notify); } break; case Constants.TypePing: OnPing(connection, channel, header, message as Ping); break; case Constants.TypeBytesRead: OnStreamBytesRead(connection, channel, header, message as BytesRead); break; case Constants.TypeSharedObject: case Constants.TypeFlexSharedObject: OnSharedObject(connection, channel, header, message as SharedObjectMessage); break; case Constants.TypeFlexStreamEnd: if (stream != null) { (stream as IEventDispatcher).DispatchEvent(message); } break; case Constants.TypeChunkSize: OnChunkSize(connection, channel, header, message as ChunkSize); break; case Constants.TypeAudioData: case Constants.TypeVideoData: // NOTE: If we respond to "publish" with "NetStream.Publish.BadName", // the client sends a few stream packets before stopping. We need to // ignore them. if (stream != null) { ((IEventDispatcher)stream).DispatchEvent(message); } break; case Constants.TypeServerBandwidth: OnServerBW(connection, channel, header, message as ServerBW); break; case Constants.TypeClientBandwidth: OnClientBW(connection, channel, header, message as ClientBW); break; default: #if !SILVERLIGHT if (log != null && log.IsDebugEnabled) { log.Debug("RtmpService event not handled: " + header.DataType); } #endif break; } } catch (Exception ex) { #if !SILVERLIGHT if (log.IsErrorEnabled) { log.Error(__Res.GetString(__Res.Rtmp_HandlerError), ex); log.Error(__Res.GetString(__Res.Error_ContextDump)); //log.Error(Environment.NewLine); log.Error(packet); } #endif } }
/// <summary> /// Adds the client stream. /// This method supports the infrastructure and is not intended to be used directly from your code. /// </summary> /// <param name="stream">The stream.</param> public void AddClientStream(IClientStream stream) { int streamId = stream.StreamId; try { ReaderWriterLock.AcquireWriterLock(); if (_reservedStreams.Length > streamId - 1 && _reservedStreams[streamId - 1]) return;//Already reserved if (_reservedStreams.Length <= streamId - 1) _reservedStreams.Length = streamId; _reservedStreams[streamId - 1] = true; } finally { ReaderWriterLock.ReleaseWriterLock(); } _streams[streamId - 1] = stream; _streamCount.Increment(); }
/// <summary> /// Remove a stream from the connection. /// </summary> /// <param name="stream"></param> private void UnregisterStream(IClientStream stream) { _streams.Remove(stream.StreamId); }
/// <summary> /// Store a stream in the connection. /// </summary> /// <param name="stream"></param> protected void RegisterStream(IClientStream stream) { _streams[stream.StreamId - 1] = stream; }
public void play(string name, double start, double length, bool flushPlaylist) { IConnection connection = FluorineContext.Current.Connection; if (!(connection is IStreamCapableConnection)) { return; } IStreamCapableConnection streamConnection = connection as IStreamCapableConnection; IScope scope = connection.Scope; int streamId = GetCurrentStreamId(); if (name == null || string.Empty.Equals(name)) { SendNSFailed(streamConnection as RtmpConnection, "The stream name may not be empty.", name, streamId); return; } IStreamSecurityService security = ScopeUtils.GetScopeService(scope, typeof(IStreamSecurityService)) as IStreamSecurityService; if (security != null) { IEnumerator handlers = security.GetStreamPlaybackSecurity(); while (handlers.MoveNext()) { IStreamPlaybackSecurity handler = handlers.Current as IStreamPlaybackSecurity; if (!handler.IsPlaybackAllowed(scope, name, (long)start, (long)length, flushPlaylist)) { SendNSFailed(streamConnection as RtmpConnection, "You are not allowed to play the stream.", name, streamId); return; } } } IClientStream stream = streamConnection.GetStreamById(streamId); bool created = false; if (stream == null) { stream = streamConnection.NewPlaylistSubscriberStream(streamId); stream.Start(); created = true; } if (!(stream is ISubscriberStream)) { return; } ISubscriberStream subscriberStream = stream as ISubscriberStream; SimplePlayItem item = new SimplePlayItem(); item.Name = name; item.Start = (long)start; item.Length = (long)length; if (subscriberStream is IPlaylistSubscriberStream) { IPlaylistSubscriberStream playlistStream = subscriberStream as IPlaylistSubscriberStream; if (flushPlaylist) { playlistStream.RemoveAllItems(); } playlistStream.AddItem(item); } else if (subscriberStream is ISingleItemSubscriberStream) { ISingleItemSubscriberStream singleStream = subscriberStream as ISingleItemSubscriberStream; singleStream.PlayItem = item; } else { // not supported by this stream service return; } try { subscriberStream.Play(); } catch (System.IO.IOException ex) { if (created) { stream.Close(); streamConnection.DeleteStreamById(streamId); } SendNSFailed(streamConnection as RtmpConnection, ex.Message, name, streamId); } }
public void publish(string name, string mode) { IConnection connection = FluorineContext.Current.Connection; if (!(connection is IStreamCapableConnection)) { return; } IStreamCapableConnection streamConnection = connection as IStreamCapableConnection; IScope scope = connection.Scope; int streamId = GetCurrentStreamId(); if (name == null || string.Empty.Equals(name)) { SendNSFailed(streamConnection as RtmpConnection, "The stream name may not be empty.", name, streamId); return; } IStreamSecurityService security = ScopeUtils.GetScopeService(scope, typeof(IStreamSecurityService)) as IStreamSecurityService; if (security != null) { IEnumerator handlers = security.GetStreamPublishSecurity(); while (handlers.MoveNext()) { IStreamPublishSecurity handler = handlers.Current as IStreamPublishSecurity; if (!handler.IsPublishAllowed(scope, name, mode)) { SendNSFailed(streamConnection as RtmpConnection, "You are not allowed to publish the stream.", name, streamId); return; } } } IBroadcastScope bsScope = GetBroadcastScope(scope, name); if (bsScope != null && bsScope.GetProviders().Count > 0) { // Another stream with that name is already published. StatusASO badName = new StatusASO(StatusASO.NS_PUBLISH_BADNAME); badName.clientid = streamId; badName.details = name; badName.level = "error"; // FIXME: there should be a direct way to send the status RtmpChannel channel = (streamConnection as RtmpConnection).GetChannel((byte)(4 + ((streamId - 1) * 5))); channel.SendStatus(badName); return; } IClientStream stream = streamConnection.GetStreamById(streamId); if (stream != null && !(stream is IClientBroadcastStream)) { return; } bool created = false; if (stream == null) { stream = streamConnection.NewBroadcastStream(streamId); created = true; } IClientBroadcastStream bs = stream as IClientBroadcastStream; try { bs.PublishedName = name; IScopeContext context = connection.Scope.Context; //IProviderService providerService = (IProviderService)context.getBean(IProviderService.BEAN_NAME); IProviderService providerService = ScopeUtils.GetScopeService(connection.Scope, typeof(IProviderService)) as IProviderService; // TODO handle registration failure if (providerService.RegisterBroadcastStream(connection.Scope, name, bs)) { bsScope = GetBroadcastScope(connection.Scope, name); bsScope.SetAttribute(Constants.BroadcastScopeStreamAttribute, bs); if (connection is BaseConnection) { (connection as BaseConnection).RegisterBasicScope(bsScope); } } if (Constants.ClientStreamModeRecord.Equals(mode)) { bs.Start(); bs.SaveAs(name, false); } else if (Constants.ClientStreamModeAppend.Equals(mode)) { bs.Start(); bs.SaveAs(name, true); } else if (Constants.ClientStreamModeLive.Equals(mode)) { bs.Start(); } bs.StartPublishing(); } catch (System.IO.IOException ex) { StatusASO accessDenied = new StatusASO(StatusASO.NS_RECORD_NOACCESS); accessDenied.clientid = streamId; accessDenied.description = "The file could not be created/written to." + ex.Message; accessDenied.details = name; accessDenied.level = "error"; // FIXME: there should be a direct way to send the status RtmpChannel channel = (streamConnection as RtmpConnection).GetChannel((byte)(4 + ((streamId - 1) * 5))); channel.SendStatus(accessDenied); bs.Close(); if (created) { streamConnection.DeleteStreamById(streamId); } } catch (Exception ex) { log.Warn("Publish caught exception", ex); } }
protected override void OnPing(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, Ping ping) { switch (ping.PingType) { case Ping.PingClient: case Ping.StreamBegin: case Ping.RecordedStream: case Ping.StreamPlayBufferClear: // The server wants to measure the RTT Ping pong = new Ping(); pong.PingType = Ping.PongServer; // The event data is a 4-byte timestamp, which was received with the in the Ping request pong.Value2 = ping.Value2; connection.Ping(pong); break; case Ping.StreamDry: #if !SILVERLIGHT if (Log.IsDebugEnabled) { Log.Debug("Stream indicates there is no data available"); } #endif break; case Ping.ClientBuffer: //Set the client buffer IClientStream stream = null; //Get the stream id int streamId = ping.Value2; //Get requested buffer size in milliseconds int buffer = ping.Value3; #if !SILVERLIGHT if (Log.IsDebugEnabled) { Log.Debug(string.Format("Client sent a buffer size: {0} ms for stream id: {1}", buffer, streamId)); } #endif if (streamId != 0) { // The client wants to set the buffer time stream = connection.GetStreamById(streamId); if (stream != null) { stream.SetClientBufferDuration(buffer); #if !SILVERLIGHT if (Log.IsDebugEnabled) { Log.Debug(string.Format("Setting client buffer on stream: {0}", streamId)); } #endif } } //Catch-all to make sure buffer size is set if (stream == null) { // Remember buffer time until stream is created connection.RememberStreamBufferDuration(streamId, buffer); #if !SILVERLIGHT if (Log.IsDebugEnabled) { Log.Debug(string.Format("Remembering client buffer on stream: {0}", streamId)); } #endif } break; default: #if !SILVERLIGHT if (Log.IsDebugEnabled) { Log.Debug(string.Format("Unhandled ping: {0}", ping)); } #endif break; } }
public void OnOOBControlMessage(IMessageComponent source, IPipe pipe, OOBControlMessage oobCtrlMsg) { if (!"ConnectionConsumer".Equals(oobCtrlMsg.Target)) { return; } if ("pendingCount".Equals(oobCtrlMsg.ServiceName)) { oobCtrlMsg.Result = _connection.PendingMessages; } else if ("pendingVideoCount".Equals(oobCtrlMsg.ServiceName)) { IClientStream stream = null; if (_connection is IStreamCapableConnection) { stream = (_connection as IStreamCapableConnection).GetStreamByChannelId(_video.ChannelId); } if (stream != null) { oobCtrlMsg.Result = _connection.GetPendingVideoMessages(stream.StreamId); } else { oobCtrlMsg.Result = (long)0; } } else if ("writeDelta".Equals(oobCtrlMsg.ServiceName)) { long maxStream = 0; IBWControllable bwControllable = _connection as IBWControllable; // Search FC containing valid BWC while (bwControllable != null && bwControllable.BandwidthConfiguration == null) { bwControllable = bwControllable.GetParentBWControllable(); } if (bwControllable != null && bwControllable.BandwidthConfiguration != null) { IBandwidthConfigure bwc = bwControllable.BandwidthConfiguration; if (bwc is IConnectionBWConfig) { maxStream = (bwc as IConnectionBWConfig).DownstreamBandwidth / 8; } } if (maxStream <= 0) { // Use default value // TODO: this should be configured somewhere and sent to the client when connecting maxStream = 120 * 1024; } // Return the current delta between sent bytes and bytes the client // reported to have received, and the interval the client should use // for generating BytesRead messages (half of the allowed bandwidth). oobCtrlMsg.Result = new long[] { _connection.WrittenBytes - _connection.ClientBytesRead, maxStream / 2 }; } else if ("chunkSize".Equals(oobCtrlMsg.ServiceName)) { int newSize = (int)oobCtrlMsg.ServiceParameterMap["chunkSize"]; if (newSize != _chunkSize) { _chunkSize = newSize; SendChunkSize(); } } }