Im new here and Ill love your help.
Im trying to serialize and deserialize a package (to use it in sockets) and the results are not the ones that I expect but I cant find the mistake. HereĀ“s the code.
typedef struct {
int32_t size;
char data[1024];
} t_socket_buffer;
typedef struct {
int16_t payloadLength;
int8_t type;
char *path;
} ReadRequestPackage;
The function that serializes
t_socket_buffer *Open_serializer(ReadRequestPackage *ReadPackage){
char data[1024];
t_socket_buffer *stream = malloc(sizeof(t_socket_buffer));
int8_t offset = 0, tmp_size = 0;
memcpy(data, &ReadPackage->payloadLength, tmp_size = sizeof(int16_t));
offset = tmp_size;
memcpy(data + offset,&ReadPackage->type, tmp_size = sizeof(int8_t));
offset+= tmp_size;
memcpy(data + offset, ReadPackage->path,tmp_size = strlen(ReadPackage->path)+1);
stream->size = offset + tmp_size;
memcpy(stream->data, data,strlen(data)+1);
return stream;
}
The function that DEserializes
ReadRequestPackage *Open_deserializer(t_socket_buffer *stream)
{
ReadRequestPackage *ReadPackage = malloc(sizeof(ReadRequestPackage));
int32_t offset = 0, tmp_size = 0;
memcpy(&ReadPackage->payloadLength,stream->data,tmp_size = sizeof(int16_t));
offset = tmp_size;
memcpy(&ReadPackage->type, stream->data + offset, tmp_size = sizeof(int8_t));
offset += tmp_size;
for(tmp_size = 1; (stream->data + offset)[tmp_size-1]!='\0';tmp_size++);
ReadPackage->path = malloc(tmp_size);
memcpy(ReadPackage->path, stream->data + offset, tmp_size);
return ReadPackage;
}
When I test it with this main()
int main (void){
ReadRequestPackage *pqt1 = malloc(sizeof(ReadRequestPackage));
ReadRequestPackage *pqt2;
t_socket_buffer *stream;
pqt1->path=malloc(sizeof("directory"));
strcpy(pqt1->path,"directory");
pqt1->payloadLength = strlen("directory")+1+sizeof(int8_t);
pqt1->type = 1;
stream = Open_serializer(pqt1);
pqt2 = Open_deserializer(stream);
printf("path 1: ");
puts(pqt1->path);
printf("path 2: ");
puts(pqt2->path);
printf("\ntype1:%d ",pck1->type);
printf("\ntype2:%d ",pck2->type);
printf("\nize:%d ",pck1->payloadLength);
printf("\nsize:%d ",pck2->payloadLength);
return 1;
}
The results are not the same and they should!
Thank you very much!
memcpy(stream->data, data,strlen(data)+1);
This line is not doing what you think it's doing. data is not a string.
BTW, have you thought about using a proper serialization library?
Related
I have an array of numbers which i want to compress and store in a file then decompress and put data in a buffer.
RAM->FILE compressing
FILE->RAM decompressing
I used LzmaEncode for compressing and then write compress buffer in a file.
lzmaencoder.c
int main(void){
int data[] = {1,2,3,4,5};
size_t src_len = sizeof(data);
const Byte * src = (Byte *) data;
size_t compressed_size = src_len*1.5;
Byte * compressed_data = malloc(compressed_size);
CLzmaEncProps props;
LzmaEncProps_Init(&props);
Byte header[LZMA_PROPS_SIZE];
size_t headerSize = LZMA_PROPS_SIZE;
// Call encoding function:
SRes res;
res = LzmaEncode(compressed_data, &compressed_size, src, src_len,
&props, header, &headerSize, 0, NULL, &g_Alloc, &g_Alloc);
if(res == SZ_OK){
FILE * file = fopen("lzma_file","wb");
fwrite(compressed_data, sizeof(Byte), compressed_size, file);
}
free(compressed_data);
return (0);
}
I read compress file and write data in a buffer, then use LzmaDecode for decompressing.
lzmadecoder.c
int main(int argc, char * argv[]){
// I know the original data size
size_t uncompress_size = 20;
Byte * uncompress = malloc(uncompress_size);
// open compressed file
size_t compress_size;
FILE * compress_file = fopen("lzma_file", "rb");
if(!compress_file){
printf("Error: can not open lzma_file file.");
}
// get compressed file size
fseek(compress_file, 0, SEEK_END);
compress_size = ftell(compress_file);
fseek(compress_file, 0, SEEK_SET);
Byte *compress_data = malloc(compress_size);
// put compressed file data on RAM
if(!fread(compress_data, sizeof(Byte), compress_size, compress_file)){
printf("Error: can not read lzma_file file.");
}
fclose(compress_file);
ELzmaStatus status;
// RAM->RAM decompressing
int res = LzmaDecode(uncompress, &uncompress_size,
compress_data, &compress_size,
compress_data, 5,
LZMA_FINISH_END, &status, &g_Alloc);
if(res==SZ_OK){
printf("SZ_OK!\n");
} else if(res==SZ_ERROR_DATA){
printf("SZ_ERROR_DATA!\n");
}
free(uncompress);
free(compress_data);
return (0);
}
but LzmaDecode return SZ_ERROR_DATA. I cant find my problem.
LZMA compression---------------- Version: 9.35
Use the Lib API generated by the project "lzma1900\C\Util\LzmaLib": LzmaCompress and LzmaUncompress.
int main()
{
Byte outProps[5];
size_t outPropsSize = 5; /* *outPropsSize must be = 5 */
int r =RawEncode(out,&tmpLen,bnInfo, len1,outProps,&outPropsSize);
Pkt init =RawDecode(out2,$outLen2, out, tmpLen, &outPropsSize);
return 0;
}
int RawEncode(char* out, int *ol, char *buf, uint32_t l, char* outProps, size_t* outPropsSize)
{
int res = 0;
m_l = 8;
int level = m_level; /* 0 <= level <= 9, default = 5 */
unsigned dictSize = 1 << 24; /* default = (1 << 24) */
int lc = 3; /* 0 <= lc <= 8, default = 3 */
int lp = 0; /* 0 <= lp <= 4, default = 0 */
int pb = 2; /* 0 <= pb <= 4, default = 2 */
int fb = 32; /* 5 <= fb <= 273, default = 32 */
int numThreads = 1; /* 1 or 2, default = 2 */
int r = LzmaCompress(out,ol,buf,l,outProps, outPropsSize, m_level, dictSize, lc, lp, pb, fb, 1);
olen = l;
return r;
}
void RawDecode(char* out, int* oLen, char* buf, int len, unsigned char* props, size_t* propsSize)
{
char out[outLen];
SizeT srcLen = pkt.first.len - 8;
int r = LzmaUncompress(out, oLen, buf, &len, props, *propsSize);
if(SZ_OK != r)
{
printf("LzmaUncompress error %d.", r);
delete [] tmp.second;
tmp.second = NULL;
}
}
I am building NKE(Network Kernal Extension) for filtering and modifying the packets on the fly. myipfilter_output_redirect callback gives mbuf_t pointer and based on the researched knowledge it has every information related to the network call.
I want to read the html from this mbuf_t and inject one css/html into it. how can I achieve it?
static errno_t myipfilter_output(void* cookie, mbuf_t* data, ipf_pktopts_t options) {
if (data)
log_ip_packet(data, kMyFiltDirOut);
return 0;
}
static errno_t myipfilter_input(void* cookie, mbuf_t* data, int offset, u_int8_t protocol) {
if (data)
log_ip_packet(data, kMyFiltDirIn);
return 0;
}
static void myipfilter_detach(void* cookie) {
/* cookie isn't dynamically allocated, no need to free in this case */
struct myfilter_stats* stats = (struct myfilter_stats*)cookie;
printf("UDP_IN %lu UDP OUT: %lu TCP_IN: %lu TCP_OUT: %lu ICMP_IN: %lu ICMP OUT: %lu OTHER_IN: %lu OTHER_OUT: %lu\n",
stats->udp_packets[kMyFiltDirIn],
stats->udp_packets[kMyFiltDirOut],
stats->tcp_packets[kMyFiltDirIn],
stats->tcp_packets[kMyFiltDirOut],
stats->icmp_packets[kMyFiltDirIn],
stats->icmp_packets[kMyFiltDirOut],
stats->other_packets[kMyFiltDirIn],
stats->other_packets[kMyFiltDirOut]);
g_filter_detached = TRUE;
}
static struct ipf_filter g_my_ip_filter = {
&g_filter_stats,
"com.xxx.NetworKext",
myipfilter_input,
myipfilter_output_redirect, // myipfilter_output,
myipfilter_detach
};
kern_return_t MyIPFilter_start () {
printf("MyIPFilter_start called");
int result;
result = ipf_addv4(&g_my_ip_filter, &g_filter_ref);
return result;
}
kern_return_t MyIPFilter_stop () {
printf("MyIPFilter_stop called");
ipf_remove(g_filter_ref);
return KERN_SUCCESS;
}
static errno_t myipfilter_output_redirect(void* cookie, mbuf_t* data, ipf_pktopts_t options)
{
// not printing all html and css tags
printf("myipfilter_output_redirect called");
unsigned char* dataString = NULL;
for (mbuf_t mb = *data; mb; mb = mbuf_next(mb))
{
dataString = mbuf_data(mb);
size_t len = mbuf_len(mb);
for (size_t i = 0; i < len; i++)
{
printf("%c", dataString[i]);
}
}
printf("dataString: %s", dataString);
}
I have made a sample repo if you can help here anything.
you should choose socket filter and in order to retrieve HTML payload you should read mbuf_t using mbuf_t data. Below method prints every bytes from the starts so put it in your sf_data_in_func call back.
print_mbuf_data(*data);
This would work for you.
static void print_mbuf_data(mbuf_t mb){
// unsigned char *tmp_buffer = (unsigned char *) mbuf_datastart(mb);
unsigned char *tmp_buffer = (unsigned char *) mbuf_data(mb);
unsigned long line = 0, index = 0, character = 0, hex_length = 0x80; // hex_length has limit of 64 decimal
unsigned long length = mbuf_len(mb);
unsigned char hex_temp [0x80]; // buffer has limit of 64 decimal
for (index = 0; index < length; index += 0x80)
{
memset(hex_temp, 0, hex_length);
line = length - index > 0x80 ? 0x80 : length - index;
for (character = 0; character < line; character++)
{
snprintf(((char *) hex_temp + strlen((char *) hex_temp)),
hex_length - strlen((char *) hex_temp), "%c", tmp_buffer[index + character]);
}
printf("%s", hex_temp);
}
}
Running my program, I appear to not be writing the correct amount of frames according to the index.
$ ./test
Now recording!! Please speak into the microphone.
index = 0
Writing to: test.flac
audio.h:
#include <stdint.h>
#include <string.h>
typedef struct
{
uint32_t duration;
uint16_t format_type;
uint16_t number_of_channels;
uint32_t sample_rate;
uint32_t frameIndex; /* Index into sample array. */
uint32_t maxFrameIndex;
char* recordedSamples;
} AudioData;
int recordFLAC(AudioData* data, const char *fileName);
AudioData* initAudioData(uint32_t sample_rate, uint16_t channels, uint32_t duration);
capture.c:
#include <stdio.h>
#include <stdlib.h>
#include <portaudio.h>
#include <sndfile.h>
#include "audio.h"
AudioData* initAudioData(uint32_t sample_rate, uint16_t channels, uint32_t duration)
{
AudioData* data = malloc(sizeof(*data));
if (!data) return NULL;
data->duration = duration;
data->format_type = 1;
data->number_of_channels = channels;
data->sample_rate = sample_rate;
data->frameIndex = 0;
data->maxFrameIndex = sample_rate * duration;
data->recordedSamples = malloc(sizeof(data->maxFrameIndex));
if(!data->maxFrameIndex) return NULL;
return data;
}
static int recordCallback(const void *inputBuffer, void *outputBuffer, unsigned long frameCount, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void *userData)
{
AudioData* data = (AudioData*)userData;
const char* buffer_ptr = (const char*)inputBuffer;
char* index_ptr = &data->recordedSamples[data->frameIndex];
(void) outputBuffer;
(void) timeInfo;
(void) statusFlags;
long framesToCalc;
long i;
int finished;
unsigned long framesLeft = data->maxFrameIndex - data->frameIndex;
if(framesLeft < frameCount){
framesToCalc = framesLeft;
finished = paComplete;
}else{
framesToCalc = frameCount;
finished = paContinue;
}
if(!inputBuffer){
for(i = 0; i < framesToCalc; i++){
*index_ptr++ = 0;
}
}else{
for(i = 0; i < framesToCalc; i++){
*index_ptr++ = *buffer_ptr++;
}
}
data->frameIndex += framesToCalc;
return finished;
}
int recordFLAC(AudioData* data, const char *fileName)
{
PaStreamParameters inputParameters;
PaStream* stream;
int err = 0;
int totalFrames = data->maxFrameIndex;
int numSamples;
int numBytes;
char max, val;
double average;
numSamples = totalFrames * data->number_of_channels;
numBytes = numSamples;
data->recordedSamples = malloc(numBytes);
if(!data->recordedSamples)
{
printf("Could not allocate record array.\n");
goto done;
}
for(int i = 0; i < numSamples; i++) data->recordedSamples[i] = 0;
if((err = Pa_Initialize())) goto done;
inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
if (inputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default input device.\n");
goto done;
}
inputParameters.channelCount = data->number_of_channels; /* stereo input */
inputParameters.sampleFormat = data->format_type;
inputParameters.suggestedLatency = Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency;
inputParameters.hostApiSpecificStreamInfo = NULL;
/* Record some audio. -------------------------------------------- */
err = Pa_OpenStream(&stream, &inputParameters, NULL, data->sample_rate, paFramesPerBufferUnspecified, paClipOff, recordCallback, &data);
if(err) goto done;
if((err = Pa_StartStream(stream))) goto done;
puts("Now recording!! Please speak into the microphone.");
while((err = Pa_IsStreamActive(stream)) == 1)
{
Pa_Sleep(1000);
printf("index = %d\n", data->frameIndex);
}
if( err < 0 ) goto done;
err = Pa_CloseStream(stream);
if(err) goto done;
/* Measure maximum peak amplitude. */
max = 0;
average = 0.0;
for(int i = 0; i < numSamples; i++)
{
val = data->recordedSamples[i];
val = abs(val);
if( val > max )
{
max = val;
}
average += val;
}
average /= (double)numSamples;
done:
Pa_Terminate();
if(err)
{
fprintf(stderr, "An error occured while using the portaudio stream\n");
fprintf(stderr, "Error number: %d\n", err);
fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err));
err = 1; /* Always return 0 or 1, but no other return codes. */
}
else
{
SF_INFO sfinfo;
sfinfo.channels = 1;
sfinfo.samplerate = data->sample_rate;
sfinfo.format = SF_FORMAT_FLAC | SF_FORMAT_PCM_16;
// open to file
printf("Writing to: %s\n", fileName);
SNDFILE * outfile = sf_open(fileName, SFM_WRITE, &sfinfo);
if (!outfile) return -1;
// prepare a 3 second long buffer (sine wave)
const int size = data->sample_rate * 3;
// write the entire buffer to the file
sf_write_raw(outfile, data->recordedSamples, size);
// force write to disk
sf_write_sync(outfile);
// don't forget to close the file
sf_close(outfile);
}
return err;
}
I'm not quite sure where I am going wrong, I know I need to be writing more frames. Any suggestions?
There seems to be something wrong with your assumptions about the sample format. In the callback you are using char * (single bytes) for the sample format, but in your libsndfile call you're opening a 16 bit file with SF_FORMAT_PCM_16.
This is not so good:
data->format_type = 1;
I recommend using one of the symbolic constants in the PortAudio library for sample formatting. Maybe you want a 16 bit one? And if so, you want to be using short* not char* in the PA callback.
Finally, if your channel count is not 1, the copy loops are incorrect:
for(i = 0; i < framesToCalc; i++){
*index_ptr++ = 0;
}
A "frame" contains data for all channels, so for example, if it's a stereo input your iteration needs to deal with both left and right channels like this:
for(i = 0; i < framesToCalc; i++){
*index_ptr++ = 0; // left
*index_ptr++ = 0; // right
}
Same for the other loops.
I am working on a kernel module and I need to compare two buffers to find out if they are equivalent. I am using the memcmp function defined in the Linux kernel to do so. My first buffer is like this:
cache_buffer = (unsigned char *)vmalloc(4097);
cache_buffer[4096] = '/0';
The second buffer is from a page using the page_address() function.
page = bio_page(bio);
kmap(page);
write_buffer = (char *)page_address(page);
kunmap(page);
I have printed the contents of both buffers before hand and not only to they print correctly, but they also have the same content. So next, I do this:
result = memcmp(write_buffer, cache_buffer, 2048); // only comparing up to 2048 positions
This causes the kernel to freeze up and I cannot figure out why. I checked the implementation of memcmp and saw nothing that would cause the freeze. Can anyone suggest a cause?
Here is the memcmp implementation:
int memcmp(const void *cs, const void *ct, size_t count)
{
const unsigned char *su1, *su2;
int res = 0;
for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
if ((res = *su1 - *su2) != 0)
break;
return res;
}
EDIT: The function causing the freeze is memcmp. When I commented it out, everything worked. Also, when I did I memcmp as follows
memcmp(write_buffer, write_buffer, 2048); //comparing two write_buffers
Everything worked as well. Only when I throw the cache_buffer into the mix is when I get the error. Also, above is a simplification of my actual code. Here is the entire function:
static int compare_data(sector_t location, struct bio * bio, struct cache_c * dmc)
{
struct dm_io_region where;
unsigned long bits;
int segno;
struct bio_vec * bvec;
struct page * page;
unsigned char * cache_data;
char * temp_data;
char * write_data;
int result, length, i;
cache_data = (unsigned char *)vmalloc((dmc->block_size * 512) + 1);
where.bdev = dmc->cache_dev->bdev;
where.count = dmc->block_size;
where.sector = location << dmc->block_shift;
printk(KERN_DEBUG "place: %llu\n", where.sector);
dm_io_sync_vm(1, &where, READ, cache_data, &bits, dmc);
length = 0;
bio_for_each_segment(bvec, bio, segno)
{
if(segno == 0)
{
page = bio_page(bio);
kmap(page);
write_data = (char *)page_address(page);
//kunmap(page);
length += bvec->bv_len;
}
else
{
page = bio_page(bio);
kmap(page);
temp_data = strcat(write_data, (char *)page_address(page));
//kunmap(page);
write_data = temp_data;
length += bvec->bv_len;
}
}
printk(KERN_INFO "length: %u\n", length);
cache_data[dmc->block_size * 512] = '\0';
for(i = 0; i < 2048; i++)
{
printk("%c", write_data[i]);
}
printk("\n");
for(i = 0; i < 2048; i++)
{
printk("%c", cache_data[i]);
}
printk("\n");
result = memcmp(write_data, cache_data, length);
return result;
}
EDIT #2: Sorry guys. The problem was not memcmp. It was the result of memcmp. When ever it returned a positive or negative number, the function that called my function would play with some pointers, one of which was uninitialized. I don't know why I didn't realize it before. Thanks for trying to help though!
I'm no kernel expert, but I would assume you need to keep this memory mapped while doing the comparison? In other words, don't call kunmap until after the memcmp is complete. I would presume that calling it before will result in write_buffer pointing to a page which is no longer mapped.
Taking your code in the other question, here is a rough attempt at incremental. Still needs some cleanup, I'm sure:
static int compare_data(sector_t location, struct bio * bio, struct cache_c * dmc)
{
struct dm_io_region where;
unsigned long bits;
int segno;
struct bio_vec * bvec;
struct page * page;
unsigned char * cache_data;
char * temp_data;
char * write_data;
int length, i;
int result = 0;
size_t position = 0;
size_t max_size = (dmc->block_size * 512) + 1;
cache_data = (unsigned char *)vmalloc(max_size);
where.bdev = dmc->cache_dev->bdev;
where.count = dmc->block_size;
where.sector = location << dmc->block_shift;
printk(KERN_DEBUG "place: %llu\n", where.sector);
dm_io_sync_vm(1, &where, READ, cache_data, &bits, dmc);
bio_for_each_segment(bvec, bio, segno)
{
// Map the page into memory
page = bio_page(bio);
write_data = (char *)kmap(page);
length = bvec->bv_len;
// Make sure we don't go past the end
if(position >= max_size)
break;
if(position + length > max_size)
length = max_size - position;
// Compare the data
result = memcmp(write_data, cache_data + position, length);
position += length;
kunmap(page);
// If the memory is not equal, bail out now and return the result
if(result != 0)
break;
}
cache_data[dmc->block_size * 512] = '\0';
return result;
}
I have JPEG compressed byte stream stored in a variable called "Image" and I want to convert this byte stream to RGB.
Eg: unsigned char *Image;
My question is: Is there any way to pass "Image" to jpeg_stdio_src() to get the RGB color values?
Can anyone tell me how I could use jpeglib library to get RGB from byte stream "Image"?
Thank you
Try something like this. This uses an object currImage to store the results (not declared here).
typedef struct {
struct jpeg_source_mgr pub; // public fields
JOCTET * buffer; // start of buffer
boolean start_of_file; // have we gotten any data yet?
} my_source_mgr;
typedef my_source_mgr * my_src_ptr;
static void jpg_memInitSource(j_decompress_ptr cinfo)
{
my_src_ptr src = (my_src_ptr) cinfo->src;
src->start_of_file = true;
}
static boolean jpg_memFillInputBuffer(j_decompress_ptr cinfo)
{
my_src_ptr src = (my_src_ptr) cinfo->src;
src->start_of_file = FALSE;
return TRUE;
}
static void jpg_memSkipInputData(j_decompress_ptr cinfo, long num_bytes)
{
my_src_ptr src = (my_src_ptr) cinfo->src;
if (num_bytes > 0) {
src->pub.next_input_byte += (size_t) num_bytes;
src->pub.bytes_in_buffer -= (size_t) num_bytes;
}
}
static void jpg_memTermSource(j_decompress_ptr cinfo)
{
// no work necessary here
}
void decompressJpeg(uint8 const *compressed, size_t len)
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
my_src_ptr src;
// ToDo: change error handling to work with our return codes
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
cinfo.src = (struct jpeg_source_mgr *)
(*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
sizeof(my_source_mgr));
src = (my_src_ptr) cinfo.src;
src->buffer = (JOCTET *)compressed;
src->pub.init_source = jpg_memInitSource;
src->pub.fill_input_buffer = jpg_memFillInputBuffer;
src->pub.skip_input_data = jpg_memSkipInputData;
src->pub.resync_to_restart = jpeg_resync_to_restart;
src->pub.term_source = jpg_memTermSource;
src->pub.bytes_in_buffer = len;
src->pub.next_input_byte = compressed;
jpeg_read_header(&cinfo, true);
jpeg_start_decompress(&cinfo);
// check: cinfo.out_color_space == JCS_RGB
currImage.setSize(
(int)cinfo.output_width, (int)cinfo.output_height));
size_t w = currImage.getWidth() * 3;
uint8 *p = (uint8*)currImage.getPixels();
while (cinfo.output_scanline < cinfo.output_height) {
jpeg_read_scanlines(&cinfo, &p, 1);
p += w;
}
jpeg_finish_decompress(&cinfo); // Do this even under error conditions
jpeg_destroy_decompress(&cinfo); // Do this even under error conditions
}
EDIT: Added some of the missing support code. Thanks, Edu Filipe!