/// <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); }
private void Reset(ReadingState state = ReadingState.SkipControlChars) { _message = null; _interleavedPacket = null; _chunkSize = 0; _bufferIdx = 0; _state = state; }
public RtspMessageDecoder(IPEndPoint remoteEndpoint) { _message = null; _chunkSize = 0; _bufferIdx = 0; _interleavedPacket = null; _remoteEndpoint = remoteEndpoint; _lineReader = new LineReader(); _state = ReadingState.SkipControlChars; }
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); }
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); }
public RtspMessageEventArgs(RtspMessage message) { Message = message; }
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); }