public void PushMessage(IPipe pipe, IMessage message) { if (message is ResetMessage) { _timeStamper.Reset(); } else if (message is StatusMessage) { StatusMessage statusMsg = message as StatusMessage; _data.SendStatus(statusMsg.body as StatusASO); } else if (message is RtmpMessage) { // Make sure chunk size has been sent if (!_chunkSizeSent) SendChunkSize(); RtmpMessage rtmpMsg = message as RtmpMessage; IRtmpEvent msg = rtmpMsg.body; int eventTime = msg.Timestamp; #if !SILVERLIGHT if(log.IsDebugEnabled) log.Debug(string.Format("Message timestamp: {0}", eventTime)); #endif if (eventTime < 0) { #if !SILVERLIGHT if (log.IsDebugEnabled) log.Debug(string.Format("Message has negative timestamp: {0}", eventTime)); #endif return; } byte dataType = msg.DataType; // Create a new header for the consumer RtmpHeader header = _timeStamper.GetTimeStamp(dataType, eventTime); switch (msg.DataType) { case Constants.TypeStreamMetadata: Notify notify = new Notify((msg as Notify).Data); notify.Header = header; notify.Timestamp = header.Timer; _data.Write(notify); break; case Constants.TypeFlexStreamEnd: // TODO: okay to send this also to AMF0 clients? FlexStreamSend send = new FlexStreamSend((msg as Notify).Data); send.Header = header; send.Timestamp = header.Timer; _data.Write(send); break; case Constants.TypeVideoData: VideoData videoData = new VideoData((msg as VideoData).Data); videoData.Header = header; videoData.Timestamp = header.Timer; _video.Write(videoData); break; case Constants.TypeAudioData: AudioData audioData = new AudioData((msg as AudioData).Data); audioData.Header = header; audioData.Timestamp = header.Timer; _audio.Write(audioData); break; case Constants.TypePing: Ping ping = new Ping((msg as Ping).PingType, (msg as Ping).Value2, (msg as Ping).Value3, (msg as Ping).Value4); ping.Header = header; _connection.Ping(ping); break; case Constants.TypeBytesRead: BytesRead bytesRead = new BytesRead((msg as BytesRead).Bytes); bytesRead.Header = header; bytesRead.Timestamp = header.Timer; _connection.GetChannel((byte)2).Write(bytesRead); break; default: _data.Write(msg); break; } } }
/// <summary> /// Send reset message /// </summary> private void SendReset() { if (_isPullMode) { Ping ping1 = new Ping(); ping1.PingType = (short)Ping.RecordedStream; ping1.Value2 = this.StreamId; RtmpMessage ping1Msg = new RtmpMessage(); ping1Msg.body = ping1; DoPushMessage(ping1Msg); } Ping ping2 = new Ping(); ping2.PingType = (short)Ping.StreamBegin; ping2.Value2 = this.StreamId; RtmpMessage ping2Msg = new RtmpMessage(); ping2Msg.body = ping2; DoPushMessage(ping2Msg); ResetMessage reset = new ResetMessage(); DoPushMessage(reset); }
static ByteBuffer EncodePing(RtmpContext context, Ping ping) { int len = 6; if (ping.Value3 != Ping.Undefined) { len += 4; } if (ping.Value4 != Ping.Undefined) { len += 4; } ByteBuffer output = ByteBuffer.Allocate(len); output.PutShort(ping.PingType); output.PutInt(ping.Value2); if (ping.Value3 != Ping.Undefined) { output.PutInt(ping.Value3); } if (ping.Value4 != Ping.Undefined) { output.PutInt(ping.Value4); } return output; }
static Ping DecodePing(ByteBuffer stream) { Ping ping = new Ping(); ping.PingType = stream.GetShort(); ping.Value2 = stream.GetInt(); if(stream.HasRemaining) ping.Value3 = stream.GetInt(); if(stream.HasRemaining) ping.Value4 = stream.GetInt(); return ping; }
/// <summary> /// Send clear ping, that is, just to check if connection is alive /// </summary> private void SendClearPing() { Ping ping1 = new Ping(); ping1.PingType = (short)Ping.StreamPlayBufferClear; ping1.Value2 = this.StreamId; RtmpMessage ping1Msg = new RtmpMessage(); ping1Msg.body = ping1; DoPushMessage(ping1Msg); }
/// <summary> /// Marks that pingback was received. /// </summary> /// <param name="pong"></param> internal void PingReceived(Ping pong) { int now = Environment.TickCount; int previousReceived = _lastPongReceived.Value; #if !SILVERLIGHT if( log.IsDebugEnabled ) log.Debug(string.Format("{0} Ping received at {1} with value {2}, previous received at {3}", _connectionId, now, pong.Value2, previousReceived )); #endif if (_lastPongReceived.CompareAndSet(previousReceived, now)) { _lastPingTime.Value = ((int)(previousReceived & 0xffffffff)) - pong.Value2; } }
/// <summary> /// Start measuring the roundtrip time for a packet on the connection. /// </summary> /// <param name="ping"></param> public void Ping(Ping ping) { GetChannel(2).Write(ping); }
/// <summary> /// Start measuring the roundtrip time for a packet on the connection. /// </summary> public override void Ping() { int newPingTime = Environment.TickCount; #if !SILVERLIGHT if( log.IsDebugEnabled ) log.Debug(string.Format("{0} Pinging connection at {1}, last ping sent at {2}", _connectionId, newPingTime, _lastPingSent.Value)); #endif if(_lastPingSent.Value == 0) _lastPongReceived.Value = newPingTime; Ping pingRequest = new Ping(); pingRequest.PingType = Event.Ping.PingClient; _lastPingSent.Value = newPingTime; int now = (int)(newPingTime & 0xffffffff); pingRequest.Value2 = now; pingRequest.Value3 = Event.Ping.Undefined; Ping(pingRequest); }
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; } }
/// <summary> /// This method supports the Fluorine infrastructure and is not intended to be used directly from your code. /// </summary> /// <param name="connection"></param> /// <param name="channel"></param> /// <param name="source"></param> /// <param name="ping"></param> protected abstract void OnPing(RtmpConnection connection, RtmpChannel channel, RtmpHeader source, Ping ping);