Stream Filter Problems
Posted: 01 Apr 2013 14:13
Hi! I'm making an stream filter plugin to view AES encrypted files. I see that this kind of plugin is undocumented in the wiki, but I'm looking the source code of the existing plugins.
For the moment I'm making a test file with this command:
That generates an AES 128 chunk preceded by "HELLO", to recognize the stream.
For the moment, I'm not decrypting the file in the plugin, instead of this I'm reading the original file (test.mp3 in the example) and returning this content.
Here is my plugin description and my stream_sys_t struct:
My open function:
And there are my callbacks:
My problems are...
- My read callback always has readBuffer == NULL
- My peek allocation buffer routines fails randomly on free
- Really I don't understand what is supposed to return in read and peek callbacks... Testing the Gzip plugin, I see that peek always return the first returnBufferLength bytes of the uncompresed file and read returns readBufferLength bytes of the first non peeked chunk of uncompresed data, but this plugin never receives readBuffer == NULL :S
Someone can help me explaining a bit what is supposed to return in this functions please?
Thank you very much in advance!!
For the moment I'm making a test file with this command:
Code: Select all
openssl enc -aes-128-cbc -in test.mp3 -out protected.mp3 -K "01020304050607080900010203040506" -iv "01020304050607080900010203040506" && echo -n 'HELLO' | cat - protected.mp3 > temp && mv temp protected.mp3
For the moment, I'm not decrypting the file in the plugin, instead of this I'm reading the original file (test.mp3 in the example) and returning this content.
Here is my plugin description and my stream_sys_t struct:
Code: Select all
vlc_module_begin()
set_shortname("Test")
set_description(N_("Plugin to see encrypted files"))
set_category(CAT_INPUT)
set_subcategory(SUBCAT_INPUT_STREAM_FILTER)
set_capability("stream_filter", 20)
set_callbacks(callbackOpen, callbackClose)
vlc_module_end()
struct stream_sys_t
{
/*!
Handler to read contents of the protected file.
*/
FILE *fileHandler;
/*!
The size of the file to play.
*/
uint64_t fileSize;
/*!
Current offset of the readed data.
*/
uint64_t peekOffset;
uint64_t readOffset;
/*!
Buffer where save the data and their size.
*/
uint8_t *buffer;
uint64_t bufferLength;
};
Code: Select all
static int callbackOpen(vlc_object_t *streamObj)
{
stream_t *stream = (stream_t *)streamObj;
const uint8_t *peek;
if (stream_Peek(stream->p_source, &peek, 100) < 5) {
LOGERROR(streamObj, "stream_Peek fails reading the HELLO mark");
return VLC_EGENERIC;
}
if (memcmp(peek, "HELLO", 5) != 0) {
return VLC_EGENERIC;
} else {
LOG(streamObj, "File protected detected");
// Open the protected file to be able to get data
//FILE *fileHandler = fopen(stream->psz_path, "rb");
/* TODO TEST */ FILE *fileHandler = fopen("/Users/jose/Desktop/test.mp3", "rb");
if (!fileHandler) {
LOGERROR(streamObj, "Can not open protected file");
return VLC_EGENERIC;
}
// Set the stream p_sys
stream_sys_t *info = (stream_sys_t *)malloc(sizeof(*info));
info->fileHandler = fileHandler;
info->peekOffset = 0;
info->readOffset = 0;
info->buffer = NULL;
info->bufferLength = 0;
fseek(fileHandler, 0, SEEK_END);
info->fileSize = ftell(fileHandler);
fseek(fileHandler, 0, SEEK_SET);
stream->p_sys = info;
// Set the callbacks
stream->pf_read = callbackRead;
stream->pf_peek = callbackPeek;
stream->pf_control = callbackControl;
// Init the mutex
vlc_mutex_init(&mutex);
running = true;
return VLC_SUCCESS;
}
}
Code: Select all
static int callbackRead(stream_t *stream, void *readBuffer, unsigned int readBufferLength)
{
stream_sys_t *info = stream->p_sys;
uint64_t offset = (info->readOffset == 0)
? info->peekOffset
: info->readOffset;
if (offset >= info->fileSize) {
LOG(stream, "##################### EOF #####################");
vlc_mutex_unlock(&mutex);
return 0;
}
size_t bytesToRead = (offset + readBufferLength > info->fileSize)
? info->fileSize - offset
: readBufferLength;
info->readOffset += offset + bytesToRead;
// Caller skips data
if (readBuffer == NULL) {
LOG(stream, "\treadBuffer == NULL");
const uint8_t *nothing;
callbackPeek(stream, ¬hing, readBufferLength);
return readBufferLength;
}
info->readOffset += offset + bytesToRead;
fseek(info->fileHandler, PROTON_MARK_LENGTH+offset, SEEK_SET);
fread(readBuffer, bytesToRead, bytesToRead, info->fileHandler);
return bytesToRead;
}
static int callbackPeek(stream_t *stream, const uint8_t **returnBuffer, unsigned int returnBufferLength)
{
stream_sys_t *info = stream->p_sys;
if (info->buffer == NULL) {
info->buffer = (uint8_t *)malloc(returnBufferLength);
info->bufferLength = returnBufferLength;
} else if (info->bufferLength < returnBufferLength) {
uint8_t *tempBuffer = (uint8_t *)malloc(returnBufferLength);
memcpy(tempBuffer, info->buffer, info->bufferLength);
free(info->buffer);
info->buffer = tempBuffer;
info->bufferLength = returnBufferLength;
}
size_t bytesToRead = (returnBufferLength > info->fileSize)
? info->fileSize
: returnBufferLength;
fseek(info->fileHandler, PROTON_MARK_LENGTH, SEEK_SET);
fread(info->buffer, bytesToRead, bytesToRead, info->fileHandler);
info->peekOffset = (info->peekOffset > bytesToRead) ? info->peekOffset : bytesToRead;
*returnBuffer = info->buffer;
return bytesToRead;
}
- My read callback always has readBuffer == NULL
- My peek allocation buffer routines fails randomly on free
- Really I don't understand what is supposed to return in read and peek callbacks... Testing the Gzip plugin, I see that peek always return the first returnBufferLength bytes of the uncompresed file and read returns readBufferLength bytes of the first non peeked chunk of uncompresed data, but this plugin never receives readBuffer == NULL :S
Someone can help me explaining a bit what is supposed to return in this functions please?
Thank you very much in advance!!