using jpeglib for JPEG compressed byte stream - arrays

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!

Related

Monitoring Network Packets Using Network Kernal Extension

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);
}
}

WinDivert issue - redirecting DNS back to self on windows

I was looking at basil00's torwall, and for fun was trying to pare it down to just intercept DNS. (provide an answer back to myself of 127.0.0.1 for webfiltering purposes, learning project)
however, at this point, I have it hijacking the dns packet, but it does not return a correct address. for every "blocked" domain, it's different.
for example, I put cbc.ca in my hosts.deny file (blacklist), and it returns an address of 0.4.114.2
then blacklisting slashdot, it will return 0.4.0.1
this has been quite confusing and frustrating, and after three days of research, I am out of ideas.
Here is the code to the redirect portion of my program, which seems to be where things go awry.
(note some of the comments will be goofy as I was hacking down a program for a different purpose and haven't cleaned it up yet)
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "windivert.h"
#include "domain.h"
#include "main.h"
#include "redirect.h"
#define MAX_PACKET 4096
#define NUM_WORKERS 4
// DNS headers
#define DNS_MAX_NAME 254
struct dnshdr
{
uint16_t id;
uint16_t options;
uint16_t qdcount;
uint16_t ancount;
uint16_t nscount;
uint16_t arcount;
} __attribute__((__packed__));
struct dnsq
{
uint16_t type;
uint16_t class;
} __attribute__((__packed__));
struct dnsa
{
uint16_t name;
uint16_t type;
uint16_t class;
uint32_t ttl;
uint16_t length;
uint32_t addr;
} __attribute__((__packed__));
static DWORD redirect_worker(LPVOID arg);
static int handle_dns(HANDLE handle, PWINDIVERT_ADDRESS addr,
PWINDIVERT_IPHDR iphdr, PWINDIVERT_UDPHDR udphdr, char *data,
size_t data_len);
// State:
static bool redirect_on = false;
static HANDLE handle = INVALID_HANDLE_VALUE;
static HANDLE workers[NUM_WORKERS] = {NULL}; // Worker threads
// Send a packet asynchronously:
static void send_packet(HANDLE handle, void *packet, size_t packet_len,
PWINDIVERT_ADDRESS addr)
{
addr->Direction = WINDIVERT_DIRECTION_INBOUND;
WinDivertHelperCalcChecksums(packet, packet_len, 0);
if (!WinDivertSend(handle, packet, packet_len, addr, NULL))
debug("Send packet failed (err=%d)\n", (int)GetLastError());
}
// Start traffic redirect through Tor:
extern void redirect_start(void)
{
debug("DNS divert START\n");
if (handle != INVALID_HANDLE_VALUE)
return;
handle = WinDivertOpen(
"outbound and udp.DstPort == 53 or inbound and udp.DstPort = 53", 0, 0, 0);
// Launch threads:
redirect_on = true;
for (size_t i = 0; i < NUM_WORKERS; i++)
{
workers[i] = CreateThread(NULL, MAX_PACKET*3,
(LPTHREAD_START_ROUTINE)redirect_worker, (LPVOID)handle, 0, NULL);
if (workers[i] == NULL)
{
exit(EXIT_FAILURE);
}
}
}
// Stop traffic redirect through Tor:
extern void redirect_stop(void)
{
debug("DNS divert STOP\n");
if (handle == INVALID_HANDLE_VALUE)
return;
// Close the WinDivert handle; will cause the workers to exit.
redirect_on = false;
if (!WinDivertClose(handle))
{
exit(EXIT_FAILURE);
}
handle = INVALID_HANDLE_VALUE;
for (size_t i = 0; i < NUM_WORKERS; i++)
{
WaitForSingleObject(workers[i], INFINITE);
workers[i] = NULL;
}
}
// Redirect worker thread:
static DWORD redirect_worker(LPVOID arg)
{
HANDLE handle = (HANDLE)arg;
// Packet processing loop:
char packet[MAX_PACKET];
UINT packet_len;
WINDIVERT_ADDRESS addr;
while (redirect_on)
{
if (!WinDivertRecv(handle, packet, sizeof(packet), &addr, &packet_len))
{
// Silently ignore any error.
continue;
}
PWINDIVERT_IPHDR iphdr = NULL;
PWINDIVERT_TCPHDR tcphdr = NULL;
PWINDIVERT_UDPHDR udphdr = NULL;
PVOID data = NULL;
UINT data_len;
WinDivertHelperParsePacket(packet, packet_len, &iphdr, NULL, NULL,
NULL, &tcphdr, &udphdr, &data, &data_len);
int dnshandle = 0;
if (udphdr != NULL && ntohs(udphdr->DstPort) == 53)
dnshandle = handle_dns(handle, &addr, iphdr, udphdr, data, data_len);
if(dnshandle != 1)
{
if (!WinDivertSend(handle, packet, packet_len, &addr, NULL))
{
}
}
}
return 0;
}
// Handle DNS requests.
// NOTES:
// - If anything goes wrong, we simply drop the packet without error.
// - An alternative approach would be to let Tor resolve the address, however,
// this would be slow.
static int handle_dns(HANDLE handle, PWINDIVERT_ADDRESS addr,
PWINDIVERT_IPHDR iphdr, PWINDIVERT_UDPHDR udphdr, char *data,
size_t data_len)
{
struct dnshdr *dnshdr = (struct dnshdr *)data;
data += sizeof(struct dnshdr);
data_len -= sizeof(struct dnshdr);
char name[DNS_MAX_NAME + 8]; // 8 bytes extra.
size_t i = 0;
while (i < data_len && data[i] != 0)
{
size_t len = data[i];
if (i + len >= DNS_MAX_NAME)
return -1;
name[i++] = '.';
for (size_t j = 0; j < len; j++, i++)
name[i] = data[i];
}
name[i++] = '\0';
// Generate a fake IP address and associate it with this domain name:
uint32_t fake_addr = domain_lookup_addr(name);
if (fake_addr == 0)
{
// This domain is blocked; so ignore the request.
// Construct a query response:
size_t len = sizeof(struct dnshdr) + data_len + sizeof(struct dnsa);
if (len > 512) // Max DNS packet size.
return -1;
len += sizeof(WINDIVERT_IPHDR) + sizeof(WINDIVERT_UDPHDR) + len;
char buf[len + 8]; // 8 bytes extra.
PWINDIVERT_IPHDR riphdr = (PWINDIVERT_IPHDR)buf;
PWINDIVERT_UDPHDR rudphdr = (PWINDIVERT_UDPHDR)(riphdr + 1);
struct dnshdr *rdnshdr = (struct dnshdr *)(rudphdr + 1);
char *rdata = (char *)(rdnshdr + 1);
UINT local_ip;
DivertHelperParseIPv4Address("127.0.0.1",&local_ip);
memset(riphdr, 0, sizeof(WINDIVERT_IPHDR));
riphdr->Version = 4;
riphdr->HdrLength = sizeof(WINDIVERT_IPHDR) / sizeof(uint32_t);
riphdr->Length = htons(len);
riphdr->Id = htons(0xF00D);
WINDIVERT_IPHDR_SET_DF(riphdr, 1);
riphdr->TTL = 64;
riphdr->Protocol = IPPROTO_UDP;
riphdr->SrcAddr = iphdr->DstAddr;
riphdr->DstAddr = iphdr->SrcAddr;
memset(rudphdr, 0, sizeof(WINDIVERT_UDPHDR));
rudphdr->SrcPort = htons(53); // DNS
rudphdr->DstPort = udphdr->SrcPort;
rudphdr->Length = htons(len - sizeof(WINDIVERT_IPHDR));
rdnshdr->id = dnshdr->id;
rdnshdr->options = htons(0x8180); // Standard DNS response.
rdnshdr->qdcount = htons(0x0001);
rdnshdr->ancount = htons(0x0001);
rdnshdr->nscount = 0;
rdnshdr->arcount = 0;
memcpy(rdata, data, data_len);
struct dnsa *rdnsa = (struct dnsa *)(rdata + data_len);
rdnsa->name = htons(0xC00C);
rdnsa->type = htons(0x0001); // (A)
rdnsa->class = htons(0x0001); // (IN)
rdnsa->ttl = htonl(0x00000258) ; // 1 second
rdnsa->length = htons(0x0004);
rdnsa->addr = htonl(local_ip); // Fake address
send_packet(handle, &buf, len, addr);
debug("address: %u\n",addr->Direction);
debug("Intercept DNS %s\n", (name[0] == '.'? name+1: name));
return 1;
}
// Re-inject the matching packet.
/*
/
*/
return 0;
}
Here's the domain lookup side of it (mostly just hacked down to try to get the results I want:
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include "domain.h"
#include "main.h"
#define RATE_LIMIT 8000
#define rand16() \
(rand() & 0xFF) | ((rand() & 0xFF) << 8)
// Domain blacklist:
struct blacklist
{
size_t size;
size_t len;
char **names;
};
static struct blacklist *blacklist = NULL;
// State:
static struct name *names[UINT16_MAX] = {NULL};
static HANDLE names_lock = NULL;
// Prototypes:
static struct blacklist *domain_blacklist_read(const char *filename);
static bool domain_blacklist_lookup(struct blacklist *blacklist,
const char *name);
static int __cdecl domain_blacklist_compare_0(const void *x, const void *y);
static int domain_blacklist_compare(const char *name0, size_t len,
const char *name1);
// Initialize this module:
extern void domain_init(void)
{
// Load the domain blacklist.
blacklist = domain_blacklist_read("hosts.deny");
}
// Lookup an address given a domain name. If the name does not exist then
// create one.
extern uint32_t domain_lookup_addr(const char *name0)
{
if (name0[0] == '.')
name0++;
if (domain_blacklist_lookup(blacklist, name0))
{
debug("Block %s\n", name0);
return 0; // Blocked!
}
return;
}
// Read the blacklist file:
static struct blacklist *domain_blacklist_read(const char *filename)
{
struct blacklist *blacklist =
(struct blacklist *)malloc(sizeof(struct blacklist));
if (blacklist == NULL)
{
exit(EXIT_FAILURE);
}
blacklist->size = 0;
blacklist->len = 0;
blacklist->names = NULL;
FILE *stream = fopen(filename, "r");
if (stream == NULL)
{
return blacklist;
}
// Read blocked domains:
int c;
char buf[256];
while (true)
{
while (isspace(c = getc(stream)))
;
if (c == EOF)
break;
if (c == '#')
{
while ((c = getc(stream)) != '\n' && c != EOF)
;
continue;
}
size_t i = 0;
while (i < sizeof(buf)-1 && (c == '-' || c == '.' || isalnum(c)))
{
buf[i++] = c;
c = getc(stream);
}
if (i >= sizeof(buf)-1 || !isspace(c))
{
exit(EXIT_FAILURE);
}
buf[i] = '\0';
if (blacklist->len >= blacklist->size)
{
blacklist->size = (blacklist->size == 0? 32: 2 * blacklist->size);
blacklist->names = (char **)realloc(blacklist->names,
blacklist->size * sizeof(char *));
if (blacklist->names == NULL)
{
exit(EXIT_FAILURE);
}
}
size_t size = (i+1) * sizeof(char);
char *name = (char *)malloc(size);
if (name == NULL)
{
exit(EXIT_FAILURE);
}
for (size_t j = 0; j < i; j++)
name[j] = buf[i - 1 - j];
name[i] = '\0';
blacklist->names[blacklist->len++] = name;
}
fclose(stream);
qsort(blacklist->names, blacklist->len, sizeof(char *),
domain_blacklist_compare_0);
return blacklist;
}
// Check if a domain matches the blacklist or not:
static bool domain_blacklist_lookup(struct blacklist *blacklist,
const char *name)
{
if (blacklist->len == 0)
return false;
size_t len = strlen(name);
ssize_t lo = 0, hi = blacklist->len-1;
while (lo <= hi)
{
ssize_t mid = (lo + hi) / 2;
int cmp = domain_blacklist_compare(name, len, blacklist->names[mid]);
if (cmp > 0)
hi = mid-1;
else if (cmp < 0)
lo = mid+1;
else
return true;
}
return false;
}
// Domain compare function(s):
static int __cdecl domain_blacklist_compare_0(const void *x, const void *y)
{
const char *name0 = *(const char **)x;
const char *name1 = *(const char **)y;
return strcmp(name0, name1);
}
static int domain_blacklist_compare(const char *name0, size_t len,
const char *name1)
{
size_t i = 0;
ssize_t j = (ssize_t)len - 1;
for (; j >= 0 && name1[i] != '\0'; i++, j--)
{
int cmp = (int)name1[i] - (int)name0[j];
if (cmp != 0)
return cmp;
}
if (j < 0 && name1[i] != '\0')
return 1;
return 0;
}
any assistance is appreciated.
Also, I have uploaded the code to: Github
Thank you.
There's one of two things going on here. You're reading and writing DNS packets incorrectly, and or you're failing to convert the addresses to or from host to network order before working with them.
I'm going to bet on you reading and writing DNS packets incorrectly. I've implemented my own filtering systems using WinDivert where I was hijacking and passing all DNS traffic through my own local DNS server and I've seen these fudged addresses come out exactly as the results you're getting when I was parsing and writing DNS packets incorrectly.
The bad news is, I can't point you to a full DNS library in C/C++ as I know of none that actually make the job easier (maybe, see edits). I personally had my diversion code written in C++ with WinDivert and then use Arsoft.Tools.Net C# DNS library for actually running a local DNS server and manipulating DNS responses.
There is one project in C++ that calls itself boost::net::dns because I think the writer was hoping it would be part of boost, which it isn't and probably won't be. Avoid this library as the internal mechanism for parsing and storing multiple A Records is bugged out and broken and you'll get the same wacky results you're getting here. I tried to work with him to get it fixed but, he was only interested in blaming my code.
I'll have a gander again and update my answer if I can find a decent lib for working with DNS packets in C++. Don't try to do it yourself, we're talking about entire protocols with entire books of RFC's to do this properly yourself.
Update
As promised, here are some results from my search:
Mozilla Necko (Formerly Netlib)
http://mxr.mozilla.org/mozilla-central/source/netwerk/dns/
C-Ares:
https://github.com/bagder/c-ares
A list of alternative libraries C-Ares compiled:
http://c-ares.haxx.se/otherlibs.html
Also, it is linux specific but pretty clean code. You might be able to pilfer through libcrafter's DNS classes and move them to your own project.
https://github.com/pellegre/libcrafter/blob/master/libcrafter/crafter/Protocols/DNS.h
Again, unless your "learning project" is understanding and recreating one of the foundational pillars of the internet, don't implement this yourself. Try and use one of the previously listed libraries to handle your DNS packets.

Memory comparison causes system halt

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;
}

Serialization of packages with C

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?

libjpeg crash in jpeg_read_scanlines

When I run this code to load a jpeg file I get a crash in jpeg_read_scanlines
I'm using windows 7 64 bit with VC++ 2010
The image I'm loading is a 100x75 jpg image.
If you need any more details just ask
The crash message is:
Unhandled exception at 0x012db29e in LibTest.exe: 0xC0000005: Access violation writing location 0xcdcdcdcd.
void JPG_Load (const char *path, image_t *img)
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
int infile;
JSAMPARRAY buffer;
int row_stride;
unsigned char *out;
infile = fopen(path,"rb");
if (infile == 0) {
memset (img, 0, sizeof(image_t));
return;
}
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo, (FILE *)infile);
jpeg_read_header(&cinfo, TRUE);
jpeg_start_decompress(&cinfo);
row_stride = cinfo.output_width * cinfo.output_components;
out = malloc(cinfo.output_width*cinfo.output_height*cinfo.output_components);
img->pixels = out;
img->width = cinfo.output_width;
img->height = cinfo.output_height;
img->bytesPerPixel = cinfo.out_color_components;
while (cinfo.output_scanline < cinfo.output_height) {
buffer = (JSAMPARRAY)out+(row_stride*cinfo.output_scanline);
jpeg_read_scanlines(&cinfo, buffer, 1);
}
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
fclose(infile);
}
image_t is defined as:
typedef struct {
int width;
int height;
int bytesPerPixel;
byte *pixels;
} image_t;
Don't do this.
buffer = (JSAMPARRAY)out+(row_stride*cinfo.output_scanline); // WRONG
You are casting to JSAMPARRAY, which is basically void **. The result is garbage, since that's not the kind of data you have: you have an array of bytes.
The jpeg_read_scanlines function, if you look at the documentation, does not take a pointer to your buffer. It takes a pointer to an array of scanlines, and each scanline is a pointer to row data.
while (cinfo.output_scanline < cinfo.output_height) {
unsigned char *rowp[1];
rowp[0] = (unsigned char *) out + row_stride * cinfo.output_scanline;
jpeg_read_scanlines(&cinfo, rowp, 1);
}
Recommendation: Adding a cast to fix a compiler error only works if you know the cast is correct. Don't cast to any type unless you know what the type is.

Resources