Exemple #1
0
        /// <summary>
        /// <see cref="IRtspConnection.WriteMessage(RtspMessage)"/>
        /// </summary>
        public bool WriteMessage(RtspMessage msg)
        {
            if (msg == null)
            {
                throw new ArgumentNullException("Cannot send null message");
            }

            var message = msg.ToString();

            if (LOG.IsDebugEnabled)
            {
                LOG.Debug($"Sending RTSP message\n {message}");
            }

            try
            {
                var data = Encoding.UTF8.GetBytes(message);
                Write(data, 0, data.Length);
            }
            catch (Exception e)
            {
                LOG.Error($"Unable to send RTSP message to '{Endpoint}', reason: {e.Message}");
                return(false);
            }

            return(true);
        }
Exemple #2
0
 private void Reset(ReadingState state = ReadingState.SkipControlChars)
 {
     _message           = null;
     _interleavedPacket = null;
     _chunkSize         = 0;
     _bufferIdx         = 0;
     _state             = state;
 }
Exemple #3
0
 public RtspMessageDecoder(IPEndPoint remoteEndpoint)
 {
     _message           = null;
     _chunkSize         = 0;
     _bufferIdx         = 0;
     _interleavedPacket = null;
     _remoteEndpoint    = remoteEndpoint;
     _lineReader        = new LineReader();
     _state             = ReadingState.SkipControlChars;
 }
Exemple #4
0
        public virtual object Clone()
        {
            RtspMessage msg = CreateInstanceForClone();

            foreach (var entry in Headers)
            {
                msg.Headers[entry.Key] = entry.Value;
            }

            if (Body.Length > 0)
            {
                Body.CopyTo(msg.Body, 0);
            }

            return(msg);
        }
Exemple #5
0
        private ReadingState ReadHeaders(RtspMessage msg, BinaryReader stream)
        {
            string name  = null;
            string value = null;

            var line = _lineReader.Read(stream);

            if (line.Length > 0)
            {
                msg.Headers.Clear();

                do
                {
                    char firstChar = line[0];
                    if (name != null && (firstChar == ' ' || firstChar == '\t'))
                    {
                        value = new StringBuilder(value).Append(' ').Append(line.Trim()).ToString();
                    }
                    else
                    {
                        if (name != null)
                        {
                            msg.Headers[name] = value;
                        }

                        string[] header = SlitHeader(line);
                        name  = header[0];
                        value = header[1];
                    }

                    line = _lineReader.Read(stream);
                }while (line.Length > 0);

                // Make sure we add the last header.
                if (name != null)
                {
                    msg.Headers[name] = value;
                }
            }

            var length = msg.ContentLength;

            return(length >= 0 ? ReadingState.ReadFixedContentLength : ReadingState.SkipControlChars);
        }
Exemple #6
0
 public RtspMessageEventArgs(RtspMessage message)
 {
     Message = message;
 }
Exemple #7
0
        public bool Decode(MemoryStream stream, out RtspChunk chunk)
        {
            chunk = null;

            using (var reader = new BinaryReader(stream, Encoding.UTF8, true))
            {
                switch (_state)
                {
                case ReadingState.SkipControlChars:
                {
                    SkipControlCharacters(reader);
                    _state = ReadingState.ReadInitial;
                    break;
                }

                case ReadingState.ReadInitial:
                {
                    char currentChar = Convert.ToChar(reader.PeekChar());
                    if (currentChar == INTERLEAVED_MARKER)
                    {
                        _state = ReadingState.ReadInterleavedData;
                        return(false);
                    }
                    else
                    {
                        try
                        {
                            string   line  = _lineReader.Read(reader);
                            string[] parts = SplitInitialLine(line);
                            if (parts.Length < 3)
                            {
                                // This is an invalid initial line just ignore it.
                                LOG.Warn($"Invalid start of RTSP message: '{line}', ignoring...");
                                _state = ReadingState.SkipControlChars;
                                return(false);
                            }
                            else
                            {
                                _message = RtspMessage.CreateNewMessage(parts, _remoteEndpoint);
                                _state   = ReadingState.ReadHeader;
                            }
                        }
                        catch (Exception e)
                        {
                            LOG.Error($"Failed to parse RTSP message, reason: {e.Message}");
                            _state = ReadingState.BadMessage;
                        }
                    }

                    break;
                }

                case ReadingState.ReadHeader:
                {
                    _state = ReadHeaders(_message, reader);

                    // If the check size is greater than zero it will be decreased as the
                    // ReadFixedContentLength state reads the body chunk by chunk.
                    _chunkSize = _message.ContentLength;

                    if (_state == ReadingState.SkipControlChars || (_chunkSize <= 0))
                    {
                        // No content data expected.
                        // TODO(frank.lamar):  Add support for chunking.  Not important
                        // at the moment because I have yet to see a device use chunking.
                        chunk = _message;
                        Reset();

                        return(true);
                    }

                    break;
                }

                case ReadingState.ReadFixedContentLength:
                {
                    if (_bufferIdx == 0)
                    {
                        // We are reading the first chunk of data. We need to first
                        // allocate the message's data array.
                        _message.Body = new byte[_chunkSize];
                    }

                    int bytesRead = reader.Read(_message.Body, _bufferIdx, _chunkSize);
                    _chunkSize -= bytesRead;         // Decrement the bytes read from the chunk size.
                    _bufferIdx += bytesRead;         // Increment the index to write next chunk to.

                    if (_chunkSize == 0)
                    {
                        chunk = _message;
                        Reset();

                        return(true);
                    }

                    break;
                }

                case ReadingState.ReadInterleavedData:
                {
                    if (_chunkSize == 0 && _bufferIdx == 0)
                    {
                        reader.ReadByte();         // Consume the '$' marker left in the buffer.

                        byte channel = reader.ReadByte();
                        _chunkSize = GetUint16(reader);

                        _interleavedPacket         = new InterleavedData(channel);
                        _interleavedPacket.Payload = new byte[_chunkSize];
                    }

                    int bytesRead = reader.Read(_interleavedPacket.Payload, _bufferIdx, _chunkSize);
                    _chunkSize -= bytesRead;         // Decrement the bytes read from the chunk size.
                    _bufferIdx += bytesRead;         // Increment the index to write next chunk to.

                    if (_chunkSize == 0)
                    {
                        chunk = _interleavedPacket;
                        Reset();

                        return(true);
                    }

                    break;
                }

                case ReadingState.BadMessage:
                {
                    LOG.Debug("Unable to decode RTSP message, ignoring messsage");
                    stream.Seek(0, SeekOrigin.End);         // Skip the remaining buffer.
                    Reset();
                    break;
                }

                default:
                {
                    LOG.Warn($"Unknown state: {_state}");
                    Reset();
                    break;
                }
                }
            }

            return(false);
        }