protected override void WritingMessage(RtmpPacket packet) { base.WritingMessage(packet); if (packet.Message is VideoData) { int streamId = packet.Header.StreamId; AtomicInteger integer = new AtomicInteger(); AtomicInteger integer2 = null; lock (((ICollection)this._pendingVideos).SyncRoot) { if (!this._pendingVideos.ContainsKey(streamId)) { this._pendingVideos.Add(streamId, integer); integer2 = integer; } else { integer2 = this._pendingVideos[streamId]; } } if (integer2 == null) { integer2 = integer; } integer2.Increment(); } }
public static ByteBuffer EncodePacket(RtmpContext context, RtmpPacket packet) { RtmpHeader header = packet.Header; int channelId = header.ChannelId; IRtmpEvent message = packet.Message; if (message is ChunkSize) { ChunkSize size = (ChunkSize)message; context.SetWriteChunkSize(size.Size); } ByteBuffer input = EncodeMessage(context, header, message); if (input.Position != 0L) { input.Flip(); } else { input.Rewind(); } header.Size = input.Limit; RtmpHeader lastWriteHeader = context.GetLastWriteHeader(channelId); int num2 = CalculateHeaderSize(header, lastWriteHeader); context.SetLastWriteHeader(channelId, header); context.SetLastWritePacket(channelId, packet); int writeChunkSize = context.GetWriteChunkSize(); int num4 = 1; if (header.ChannelId > 320) { num4 = 3; } else if (header.ChannelId > 0x3f) { num4 = 2; } int num5 = (int)Math.Ceiling((double)(((float)header.Size) / ((float)writeChunkSize))); int capacity = (header.Size + num2) + ((num5 > 0) ? ((num5 - 1) * num4) : 0); ByteBuffer buffer = ByteBuffer.Allocate(capacity); EncodeHeader(header, lastWriteHeader, buffer); if (num5 == 1) { ByteBuffer.Put(buffer, input, buffer.Remaining); } else { for (int i = 0; i < (num5 - 1); i++) { ByteBuffer.Put(buffer, input, writeChunkSize); EncodeHeaderByte(buffer, 3, header.ChannelId); } ByteBuffer.Put(buffer, input, buffer.Remaining); } buffer.Flip(); return(buffer); }
public void SetLastWritePacket(int channelId, RtmpPacket packet) { RtmpPacket packet2 = null; if (this._writePackets.ContainsKey(channelId)) { packet2 = this._writePackets[channelId]; } if ((packet2 != null) && (packet2.Data != null)) { packet2.Data = null; } this._writePackets[channelId] = packet; }
/// <summary> /// Writes packet from event data to the RTMP connection using the specified stream id. /// </summary> /// <param name="message">Event data.</param> /// <param name="streamId">Stream id.</param> private void Write(IRtmpEvent message, int streamId) { RtmpHeader header = new RtmpHeader(); RtmpPacket packet = new RtmpPacket(header, message); header.ChannelId = _channelId; header.Timer = message.Timestamp; header.StreamId = streamId; header.DataType = message.DataType; if (message.Header != null) { header.IsTimerRelative = message.Header.IsTimerRelative; } _connection.Write(packet); }
internal override void MessageSent(RtmpPacket packet) { if (packet.Message is VideoData) { int streamId = packet.Header.StreamId; lock (((ICollection)this._pendingVideos).SyncRoot) { if (this._pendingVideos.ContainsKey(streamId)) { this._pendingVideos[streamId].Decrement(); } } } base.MessageSent(packet); }
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); } }
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); } }
public override void Write(RtmpPacket packet) { _lock.AcquireReaderLock(); try { if (IsClosed || IsClosing || IsDisconnecting) { return; // Already shutting down. } } finally { _lock.ReleaseReaderLock(); } if (log.IsDebugEnabled) { log.Debug(__Res.GetString(__Res.Rtmp_WritePacket, _connectionId, packet)); } if (!this.IsTunneled) { //encode WritingMessage(packet); ByteBuffer outputStream = null; _lock.AcquireWriterLock(); try { outputStream = RtmpProtocolEncoder.Encode(this.Context, packet); } finally { _lock.ReleaseWriterLock(); } Write(outputStream); _rtmpServer.RtmpHandler.MessageSent(this, packet); } else { //We should never get here System.Diagnostics.Debug.Assert(false); } }
public override void Write(RtmpPacket packet) { if (!base.IsDisposed && this.IsActive) { if (log.get_IsDebugEnabled()) { log.Debug("Write " + packet.Header); } if (!this.IsTunneled) { this.WritingMessage(packet); ByteBuffer buf = RtmpProtocolEncoder.Encode(base.Context, packet); this.Send(buf); this._rtmpServer.RtmpHandler.MessageSent(this, packet); } else { Debug.Assert(false); } } }
internal void SetLastWritePacket(int channelId, RtmpPacket packet) { try { ReaderWriterLock.AcquireWriterLock(); RtmpPacket prevPacket = null; if (_writePackets.ContainsKey(channelId)) { prevPacket = _writePackets[channelId] as RtmpPacket; } if (prevPacket != null && prevPacket.Data != null) { prevPacket.Data = null; } _writePackets[channelId] = packet; } finally { ReaderWriterLock.ReleaseWriterLock(); } }
internal virtual void MessageSent(RtmpPacket packet) { if (packet.Message is VideoData) { int streamId = packet.Header.StreamId; AtomicInteger pending = null; _pendingVideos.TryGetValue(streamId, out pending); if (pending != null) pending.Decrement(); } _writtenMessages.Increment(); }
public abstract void Write(RtmpPacket packet);
/// <summary> /// Message recieved. /// </summary> /// <param name="connection">Connection object.</param> /// <param name="obj">Message object.</param> public void MessageReceived(RtmpConnection connection, object obj) { //Console.WriteLine("NEW MESSAGE"); 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; //Console.WriteLine("DATA TYPE: " + header.DataType); 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 //Console.WriteLine("NOTIFY MESSAGE"); 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: //Console.WriteLine("Package not WORKING or SENT"); #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); //Console.WriteLine("PACKET ERROR"); } #endif } }
protected virtual void WritingMessage(RtmpPacket packet) { }
public override void Write(RtmpPacket packet) { if (!IsClosed) { #if !SILVERLIGHT if (log.IsDebugEnabled) log.Debug("Write " + packet.Header); #endif //encode WritingMessage(packet); ByteBuffer outputStream = RtmpProtocolEncoder.Encode(Context, packet); Write(outputStream); _handler.MessageSent(this, packet); } }
internal virtual void MessageSent(RtmpPacket packet) { base._writtenMessages += 1L; }
public static RtmpPacket DecodePacket(RtmpContext context, ByteBuffer stream) { int num4; int num5; int remaining = stream.Remaining; if (remaining < 1) { context.SetBufferDecoding(1L); return(null); } int position = (int)stream.Position; byte num3 = stream.Get(); if ((num3 & 0x3f) == 0) { if (remaining < 2) { stream.Position = position; context.SetBufferDecoding(2L); return(null); } num4 = ((num3 & 0xff) << 8) | (stream.Get() & 0xff); num5 = 2; } else if ((num3 & 0x3f) == 1) { if (remaining < 3) { stream.Position = position; context.SetBufferDecoding(3L); return(null); } num4 = (((num3 & 0xff) << 0x10) | ((stream.Get() & 0xff) << 8)) | (stream.Get() & 0xff); num5 = 3; } else { num4 = num3 & 0xff; num5 = 1; } byte channelId = DecodeChannelId(num4, num5); if (channelId < 0) { throw new ProtocolException("Bad channel id: " + channelId); } int num8 = GetHeaderLength(DecodeHeaderSize(num4, num5)) + (num5 - 1); if (num8 > remaining) { if (log.get_IsDebugEnabled()) { log.Debug(__Res.GetString("Rtmp_HeaderBuffering", new object[] { remaining })); } stream.Position = position; context.SetBufferDecoding((long)num8); return(null); } stream.Position = position; RtmpHeader header = DecodeHeader(context, context.GetLastReadHeader(channelId), stream); log.Debug("Decoded header " + header); if (header == null) { throw new ProtocolException("Header is null, check for error"); } context.SetLastReadHeader(channelId, header); RtmpPacket lastReadPacket = context.GetLastReadPacket(channelId); if (lastReadPacket == null) { lastReadPacket = new RtmpPacket(header); context.SetLastReadPacket(channelId, lastReadPacket); } ByteBuffer data = lastReadPacket.Data; int num9 = 0; int num10 = (header.Size + num9) - ((int)data.Position); int readChunkSize = context.GetReadChunkSize(); int numBytesMax = (num10 > readChunkSize) ? readChunkSize : num10; if (stream.Remaining < numBytesMax) { if (log.get_IsDebugEnabled()) { log.Debug(__Res.GetString("Rtmp_ChunkSmall", new object[] { stream.Remaining, numBytesMax })); } stream.Position = position; context.SetBufferDecoding((long)(num8 + numBytesMax)); return(null); } ByteBuffer.Put(data, stream, numBytesMax); if (data.Position < (header.Size + num9)) { context.ContinueDecoding(); return(null); } data.Flip(); IRtmpEvent event2 = DecodeMessage(context, header, data); lastReadPacket.Message = event2; if (event2 is ChunkSize) { ChunkSize size = event2 as ChunkSize; context.SetReadChunkSize(size.Size); } context.SetLastReadPacket(channelId, null); return(lastReadPacket); }
public override void Write(RtmpPacket packet) { _lock.AcquireReaderLock(); try { if (IsClosed || IsClosing) return; } finally { _lock.ReleaseReaderLock(); } try { _lock.AcquireWriterLock(); ByteBuffer data; try { data = RtmpProtocolEncoder.Encode(this.Context, packet); } catch (Exception ex) { log.Error("Could not encode message " + packet, ex); return; } // Mark packet as being written WritingMessage(packet); if (_pendingMessages == null) _pendingMessages = new LinkedList(); _pendingMessages.Add(new PendingData(data, packet)); } finally { _lock.ReleaseWriterLock(); } }
public static ByteBuffer EncodePacket(RtmpContext context, RtmpPacket packet) { RtmpHeader header = packet.Header; int channelId = header.ChannelId; IRtmpEvent message = packet.Message; ByteBuffer data; if (message is ChunkSize) { ChunkSize chunkSizeMsg = (ChunkSize)message; context.SetWriteChunkSize(chunkSizeMsg.Size); } data = EncodeMessage(context, header, message); if(data.Position != 0) data.Flip(); else data.Rewind(); header.Size = (int)data.Limit; RtmpHeader lastHeader = context.GetLastWriteHeader(channelId); int headerSize = CalculateHeaderSize(header, lastHeader); context.SetLastWriteHeader(channelId, header); context.SetLastWritePacket(channelId, packet); int chunkSize = context.GetWriteChunkSize(); int chunkHeaderSize = 1; if (header.ChannelId > 320) chunkHeaderSize = 3; else if (header.ChannelId > 63) chunkHeaderSize = 2; int numChunks = (int)Math.Ceiling(header.Size / (float)chunkSize); int bufSize = (int)header.Size + headerSize + (numChunks > 0 ? (numChunks - 1) * chunkHeaderSize : 0); ByteBuffer output = ByteBuffer.Allocate(bufSize); EncodeHeader(header, lastHeader, output); if (numChunks == 1) { // we can do it with a single copy ByteBuffer.Put(output, data, output.Remaining); } else { for(int i = 0; i < numChunks - 1; i++) { ByteBuffer.Put(output, data, chunkSize); EncodeHeaderByte(output, (byte)HeaderType.HeaderContinue, header.ChannelId); } ByteBuffer.Put(output, data, output.Remaining); } //data.Close(); output.Flip(); return output; }
public static ByteBuffer EncodePacket(RtmpContext context, RtmpPacket packet) { RtmpHeader header = packet.Header; int channelId = header.ChannelId; IRtmpEvent message = packet.Message; ByteBuffer data; if (message is ChunkSize) { ChunkSize chunkSizeMsg = (ChunkSize)message; context.SetWriteChunkSize(chunkSizeMsg.Size); } data = EncodeMessage(context, header, message); if (data.Position != 0) { data.Flip(); } else { data.Rewind(); } header.Size = (int)data.Limit; RtmpHeader lastHeader = context.GetLastWriteHeader(channelId); int headerSize = CalculateHeaderSize(header, lastHeader); context.SetLastWriteHeader(channelId, header); context.SetLastWritePacket(channelId, packet); int chunkSize = context.GetWriteChunkSize(); int chunkHeaderSize = 1; if (header.ChannelId > 320) { chunkHeaderSize = 3; } else if (header.ChannelId > 63) { chunkHeaderSize = 2; } int numChunks = (int)Math.Ceiling(header.Size / (float)chunkSize); int bufSize = (int)header.Size + headerSize + (numChunks > 0 ? (numChunks - 1) * chunkHeaderSize : 0); ByteBuffer output = ByteBuffer.Allocate(bufSize); EncodeHeader(header, lastHeader, output); if (numChunks == 1) { // we can do it with a single copy ByteBuffer.Put(output, data, output.Remaining); } else { for (int i = 0; i < numChunks - 1; i++) { ByteBuffer.Put(output, data, chunkSize); EncodeHeaderByte(output, (byte)HeaderType.HeaderContinue, header.ChannelId); } ByteBuffer.Put(output, data, output.Remaining); } //data.Close(); output.Flip(); return(output); }
public override void Write(RtmpPacket packet) { _lock.AcquireReaderLock(); try { if (IsClosed || IsClosing || IsDisconnecting) return; // Already shutting down. } finally { _lock.ReleaseReaderLock(); } if (log.IsDebugEnabled) log.Debug(__Res.GetString(__Res.Rtmp_WritePacket, _connectionId, packet)); if (!this.IsTunneled) { //encode WritingMessage(packet); ByteBuffer outputStream = null; _lock.AcquireWriterLock(); try { outputStream = RtmpProtocolEncoder.Encode(this.Context, packet); } finally { _lock.ReleaseWriterLock(); } Write(outputStream); _rtmpServer.RtmpHandler.MessageSent(this, packet); } else { //We should never get here System.Diagnostics.Debug.Assert(false); } }
/// <summary> /// Decodes a RTMP packet. /// </summary> /// <param name="context">RTMP protocol state.</param> /// <param name="stream">Buffer to be decoded.</param> /// <returns>The decoded RTMP packet.</returns> public static RtmpPacket DecodePacket(RtmpContext context, ByteBuffer stream) { int remaining = stream.Remaining; // We need at least one byte if (remaining < 1) { #if !SILVERLIGHT if (log.IsDebugEnabled) { log.Debug(__Res.GetString(__Res.Rtmp_DataBuffering, remaining, 1)); } #endif context.SetBufferDecoding(1); return(null); } int position = (int)stream.Position; byte headerByte = stream.Get(); int headerValue; int byteCount; if ((headerByte & 0x3f) == 0) { // Two byte header if (remaining < 2) { stream.Position = position; #if !SILVERLIGHT if (log.IsDebugEnabled) { log.Debug(__Res.GetString(__Res.Rtmp_DataBuffering, remaining, 2)); } #endif context.SetBufferDecoding(2); return(null); } headerValue = ((int)headerByte & 0xff) << 8 | ((int)stream.Get() & 0xff); byteCount = 2; } else if ((headerByte & 0x3f) == 1) { // Three byte header if (remaining < 3) { stream.Position = position; #if !SILVERLIGHT if (log.IsDebugEnabled) { log.Debug(__Res.GetString(__Res.Rtmp_DataBuffering, remaining, 3)); } #endif context.SetBufferDecoding(3); return(null); } headerValue = ((int)headerByte & 0xff) << 16 | ((int)stream.Get() & 0xff) << 8 | ((int)stream.Get() & 0xff); byteCount = 3; } else { // Single byte header headerValue = (int)headerByte & 0xff; byteCount = 1; } byte channelId = DecodeChannelId(headerValue, byteCount); if (channelId < 0) { throw new ProtocolException("Bad channel id: " + channelId); } byte headerSize = DecodeHeaderSize(headerValue, byteCount); int headerLength = GetHeaderLength(headerSize); headerLength += byteCount - 1; //if(headerLength > remaining) if (headerLength + byteCount - 1 > remaining) { #if !SILVERLIGHT if (log.IsDebugEnabled) { log.Debug(__Res.GetString(__Res.Rtmp_HeaderBuffering, remaining)); } #endif stream.Position = position; //context.SetBufferDecoding(headerLength); context.SetBufferDecoding(headerLength + byteCount - 1); return(null); } // Move the position back to the start stream.Position = position; RtmpHeader header = DecodeHeader(context, context.GetLastReadHeader(channelId), stream); #if !SILVERLIGHT log.Debug("Decoded " + header); #endif if (header == null) { throw new ProtocolException("Header is null, check for error"); } // Save the header context.SetLastReadHeader(channelId, header); // Check to see if this is a new packet or continue decoding an existing one. RtmpPacket packet = context.GetLastReadPacket(channelId); if (packet == null) { packet = new RtmpPacket(header); context.SetLastReadPacket(channelId, packet); } ByteBuffer buf = packet.Data; int addSize = (header.Timer == 0xffffff ? 4 : 0); //int addSize = 0; int readRemaining = header.Size + addSize - (int)buf.Position; int chunkSize = context.GetReadChunkSize(); int readAmount = (readRemaining > chunkSize) ? chunkSize : readRemaining; if (stream.Remaining < readAmount) { #if !SILVERLIGHT if (log.IsDebugEnabled) { log.Debug(__Res.GetString(__Res.Rtmp_ChunkSmall, stream.Remaining, readAmount)); } #endif //Skip the position back to the start stream.Position = position; context.SetBufferDecoding(headerLength + readAmount); //string path = FluorineFx.Context.FluorineContext.Current.GetFullPath(@"log\chunk.bin"); //stream.Dump(path); return(null); } //http://osflash.org/pipermail/free_osflash.org/2005-September/000261.html //http://www.acmewebworks.com/Downloads/openCS/091305-initialMeeting.txt ByteBuffer.Put(buf, stream, readAmount); if (buf.Position < header.Size + addSize) { context.ContinueDecoding(); return(null); } if (buf.Position > header.Size + addSize) { #if !SILVERLIGHT log.Warn(string.Format("Packet size expanded from {0} to {1} ({2})", header.Size + addSize, buf.Position, header)); #endif } buf.Flip(); try { IRtmpEvent message = DecodeMessage(context, packet.Header, buf); packet.Message = message; if (message is ChunkSize) { ChunkSize chunkSizeMsg = message as ChunkSize; context.SetReadChunkSize(chunkSizeMsg.Size); } } finally { context.SetLastReadPacket(channelId, null); } #if !SILVERLIGHT if (log.IsDebugEnabled) { log.Debug("Decoded " + packet.ToString()); } #endif return(packet); }
/// <summary> /// Write a RTMP packet. /// </summary> /// <param name="packet">The RTMP packet.</param> public abstract void Write(RtmpPacket packet);
public PendingData(object buffer, RtmpPacket packet) { _buffer = buffer; _packet = packet; }
/// <summary> /// Mark message as being written. /// </summary> /// <param name="packet">The RTMP packet</param> protected virtual void WritingMessage(RtmpPacket packet) { if (packet.Message is VideoData) { int streamId = packet.Header.StreamId; AtomicInteger value = new AtomicInteger(); AtomicInteger old = _pendingVideos.AddIfAbsent(streamId, value) as AtomicInteger; if (old == null) old = value; old.Increment(); } }
/// <summary> /// Writes packet from event data to the RTMP connection using the specified stream id. /// </summary> /// <param name="message">Event data.</param> /// <param name="streamId">Stream id.</param> private void Write(IRtmpEvent message, int streamId) { RtmpHeader header = new RtmpHeader(); RtmpPacket packet = new RtmpPacket(header, message); header.ChannelId = _channelId; header.Timer = message.Timestamp; header.StreamId = streamId; header.DataType = message.DataType; if( message.Header != null ) header.IsTimerRelative = message.Header.IsTimerRelative; _connection.Write(packet); }
/// <summary> /// Decodes a RTMP packet. /// </summary> /// <param name="context">RTMP protocol state.</param> /// <param name="stream">Buffer to be decoded.</param> /// <returns>The decoded RTMP packet.</returns> public static RtmpPacket DecodePacket(RtmpContext context, ByteBuffer stream) { int remaining = stream.Remaining; // We need at least one byte if(remaining < 1) { #if !SILVERLIGHT if( log.IsDebugEnabled ) log.Debug(__Res.GetString(__Res.Rtmp_DataBuffering, remaining, 1)); #endif context.SetBufferDecoding(1); return null; } int position = (int)stream.Position; byte headerByte = stream.Get(); int headerValue; int byteCount; if((headerByte & 0x3f) == 0) { // Two byte header if (remaining < 2) { stream.Position = position; #if !SILVERLIGHT if (log.IsDebugEnabled) log.Debug(__Res.GetString(__Res.Rtmp_DataBuffering, remaining, 2)); #endif context.SetBufferDecoding(2); return null; } headerValue = ((int) headerByte & 0xff) << 8 | ((int) stream.Get() & 0xff); byteCount = 2; } else if ((headerByte & 0x3f) == 1) { // Three byte header if (remaining < 3) { stream.Position = position; #if !SILVERLIGHT if (log.IsDebugEnabled) log.Debug(__Res.GetString(__Res.Rtmp_DataBuffering, remaining, 3)); #endif context.SetBufferDecoding(3); return null; } headerValue = ((int) headerByte & 0xff) << 16 | ((int) stream.Get() & 0xff) << 8 | ((int) stream.Get() & 0xff); byteCount = 3; } else { // Single byte header headerValue = (int) headerByte & 0xff; byteCount = 1; } byte channelId = DecodeChannelId(headerValue, byteCount); if (channelId < 0) throw new ProtocolException("Bad channel id: " + channelId); byte headerSize = DecodeHeaderSize(headerValue, byteCount); int headerLength = GetHeaderLength(headerSize); headerLength += byteCount - 1; //if(headerLength > remaining) if (headerLength + byteCount - 1 > remaining) { #if !SILVERLIGHT if (log.IsDebugEnabled) log.Debug(__Res.GetString(__Res.Rtmp_HeaderBuffering, remaining)); #endif stream.Position = position; //context.SetBufferDecoding(headerLength); context.SetBufferDecoding(headerLength + byteCount - 1); return null; } // Move the position back to the start stream.Position = position; RtmpHeader header = DecodeHeader(context, context.GetLastReadHeader(channelId), stream); #if !SILVERLIGHT log.Debug("Decoded " + header); #endif if (header == null) throw new ProtocolException("Header is null, check for error"); // Save the header context.SetLastReadHeader(channelId, header); // Check to see if this is a new packet or continue decoding an existing one. RtmpPacket packet = context.GetLastReadPacket(channelId); if(packet == null) { packet = new RtmpPacket(header); context.SetLastReadPacket(channelId, packet); } ByteBuffer buf = packet.Data; int addSize = (header.Timer == 0xffffff ? 4 : 0); //int addSize = 0; int readRemaining = header.Size + addSize - (int)buf.Position; int chunkSize = context.GetReadChunkSize(); int readAmount = (readRemaining > chunkSize) ? chunkSize : readRemaining; if(stream.Remaining < readAmount) { #if !SILVERLIGHT if( log.IsDebugEnabled ) log.Debug(__Res.GetString(__Res.Rtmp_ChunkSmall, stream.Remaining, readAmount)); #endif //Skip the position back to the start stream.Position = position; context.SetBufferDecoding(headerLength + readAmount); //string path = FluorineFx.Context.FluorineContext.Current.GetFullPath(@"log\chunk.bin"); //stream.Dump(path); return null; } //http://osflash.org/pipermail/free_osflash.org/2005-September/000261.html //http://www.acmewebworks.com/Downloads/openCS/091305-initialMeeting.txt ByteBuffer.Put(buf, stream, readAmount); if(buf.Position < header.Size + addSize) { context.ContinueDecoding(); return null; } if (buf.Position > header.Size + addSize) { #if !SILVERLIGHT log.Warn(string.Format("Packet size expanded from {0} to {1} ({2})", header.Size + addSize, buf.Position, header)); #endif } buf.Flip(); try { IRtmpEvent message = DecodeMessage(context, packet.Header, buf); packet.Message = message; if (message is ChunkSize) { ChunkSize chunkSizeMsg = message as ChunkSize; context.SetReadChunkSize(chunkSizeMsg.Size); } } finally { context.SetLastReadPacket(channelId, null); } #if !SILVERLIGHT if (log.IsDebugEnabled) { log.Debug("Decoded " + packet.ToString()); } #endif return packet; }
internal void SetLastWritePacket(int channelId, RtmpPacket packet) { try { ReaderWriterLock.AcquireWriterLock(); RtmpPacket prevPacket = null; if (_writePackets.ContainsKey(channelId)) prevPacket = _writePackets[channelId] as RtmpPacket; if (prevPacket != null && prevPacket.Data != null) { prevPacket.Data = null; } _writePackets[channelId] = packet; } finally { ReaderWriterLock.ReleaseWriterLock(); } }
public void MessageReceived(RtmpConnection connection, object obj) { IRtmpEvent evt = null; try { RtmpPacket packet = obj as RtmpPacket; evt = packet.Message; RtmpHeader source = packet.Header; RtmpChannel channel = connection.GetChannel(source.ChannelId); IClientStream streamById = null; if (connection is IStreamCapableConnection) { streamById = (connection as IStreamCapableConnection).GetStreamById(source.StreamId); } FluorineContext.Current.Connection.SetAttribute("__@fluorinestreamid", source.StreamId); connection.MessageReceived(); if ((log != null) && log.get_IsDebugEnabled()) { log.Debug("RtmpConnection message received, type = " + source.DataType); } if (evt != null) { evt.Source = connection; } switch (source.DataType) { case 1: this.OnChunkSize(connection, channel, source, evt as ChunkSize); return; case 3: this.OnStreamBytesRead(connection, channel, source, evt as BytesRead); return; case 4: this.OnPing(connection, channel, source, evt as Ping); return; case 5: this.OnServerBW(connection, channel, source, evt as ServerBW); return; case 6: this.OnClientBW(connection, channel, source, evt as ClientBW); return; case 8: case 9: if (streamById != null) { ((IEventDispatcher)streamById).DispatchEvent(evt); } return; case 15: if (streamById != null) { (streamById as IEventDispatcher).DispatchEvent(evt); } return; case 0x10: case 0x13: this.OnSharedObject(connection, channel, source, evt as SharedObjectMessage); return; case 0x11: this.OnFlexInvoke(connection, channel, source, evt as FlexInvoke); if ((((evt.Header.StreamId != 0) && ((evt as Invoke).ServiceCall.ServiceName == null)) && ((evt as Invoke).ServiceCall.ServiceMethodName == "publish")) && (streamById != null)) { (streamById as IEventDispatcher).DispatchEvent(evt); } return; case 0x12: if (((evt as Notify).Data == null) || (streamById == null)) { break; } (streamById as IEventDispatcher).DispatchEvent(evt); return; case 20: this.OnInvoke(connection, channel, source, evt as Invoke); if ((((evt.Header.StreamId != 0) && ((evt as Invoke).ServiceCall.ServiceName == null)) && ((evt as Invoke).ServiceCall.ServiceMethodName == "publish")) && (streamById != null)) { (streamById as IEventDispatcher).DispatchEvent(evt); } return; default: goto Label_0304; } this.OnInvoke(connection, channel, source, evt as Notify); return; Label_0304: if ((log != null) && log.get_IsDebugEnabled()) { log.Debug("RtmpService event not handled: " + source.DataType); } } catch (Exception exception) { log.Error("Runtime error", exception); } }