Firstly, i want know if the PByte type is equivalent to a BYTE*(byte pointer) in C++. In negative case, what's could be on Delphi that more near to BYTE* of C++?
Well, suppose that i'm right about that PByte is BYTE* (C++), then based on following C++ code, how send() this data type (PByte) correctly using native WinSock?
See:
C++:
SOCKET sock;
BITMAPINFO bmpInfo;
BYTE *bytes = NULL;
BYTE *temp_bytes = NULL;
DWORD workSpaceSize, fragmntWorkSpaceSize, size;
RtlGetCompressionWorkSpaceSize(COMPRESSION_FORMAT_LZNT1, &workSpaceSize, &fragmntWorkSpaceSize);
bytes = (BYTE *) Alloc(bmpInfo.bmiHeader.biSizeImage);
temp_bytes = (BYTE *) Alloc(bmpInfo.bmiHeader.biSizeImage);
BYTE *memory = (BYTE *) Alloc(workSpaceSize);
RtlCompressBuffer(COMPRESSION_FORMAT_LZNT1,
bytes,
bmpInfo.bmiHeader.biSizeImage,
temp_bytes,
bmpInfo.bmiHeader.biSizeImage,
2048,
&size,
memory);
free(bytes);
free(memory);
if(Send(sock, (char *) temp_bytes, size, 0) <= 0) return;
free(temp_bytes);
Delphi:
var
Sock: TSocket;
bmpInfo: TBitMapInfo;
bytes: PByte = nil;
temp_bytes: PByte = nil;
memory: PByte;
workSpaceSize, fragmntWorkSpaceSize, Size: Cardinal;
//...
RtlGetCompressionWorkSpaceSize(COMPRESSION_FORMAT_LZNT1, #workSpaceSize, #fragmntWorkSpaceSize);
bytes := AllocMem(bmpInfo.bmiHeader.biSizeImage);
temp_bytes := AllocMem(bmpInfo.bmiHeader.biSizeImage);
memory := AllocMem(workSpaceSize);
RtlCompressBuffer(COMPRESSION_FORMAT_LZNT1, bytes, bmpInfo.bmiHeader.biSizeImage,
temp_bytes, bmpInfo.bmiHeader.biSizeImage, 2048, #Size, memory);
FreeMem(bytes);
FreeMem(memory);
if send(Sock, temp_bytes^, Size, 0) <= 0 then Exit;
FreeMem(temp_bytes);
Reference to RtlGetCompressionWorkSpaceSize() and RtlCompressBuffer() functions in C++.
Reference to RtlGetCompressionWorkSpaceSize() and RtlCompressBuffer() functions in Delphi.
Related
I am facing an error whenever I call a recvfrom() function for UDP in server side:
buffer overflow detected ***: terminated Aborted
What is the meaning of this error? I am not able to understand.
unsigned int len;
int rv,i;
int tmp;
//char msg[200],command=0;
unsigned short *Fptr;
float Float_Temp;
//make socket blocking
FD_ZERO(&readnbs);
FD_SET(g_iUDP_datalogger_soc, &readnbs);
g_UDP_Blocktimervalue.tv_sec = 0;
g_UDP_Blocktimervalue.tv_usec = UDP_REC_BLOCKTIME;
rv = select(g_iUDP_datalogger_soc + 1, &readnbs, NULL, NULL, &g_UDP_Blocktimervalue);
len = sizeof(g_UDP_ClientAddr);
if (rv == 1) {
printf(" \n\n\n\n\n rv=%d\n\n\n\n",rv);
tmp = recvfrom(g_iUDP_datalogger_soc, &tmp, SIZE_UDP_MSG, 0,(struct sockaddr *) &g_UDP_ClientAddr, &len);
tmp = recvfrom(g_iUDP_datalogger_soc, [YOUR BUFFER ?] , SIZE_UDP_MSG, 0,(struct sockaddr *)...
You're trying to buffer the received data into a single int (tmp) object, which you are also using as the return value from the recvfrom(), and even not checking in any way - either for error, nor for received data.
You are asking recvfrom() to read SIZE_UDP_MSG number of bytes into tmp, which is an int. You did not show what SIZE_UDP_MSG is defined as, but if SIZE_UDP_MSG > sizeof(int), you are going to be writing bytes past the bounds of tmp into surrounding memory, corrupting the memory. That is a buffer overflow.
Perhaps you meant to receive the bytes into your (commented out) msg buffer instead?
char msg[SIZE_UDP_MSG];
tmp = recvfrom(..., msg, SIZE_UDP_MSG, ...);
Thanks first for your time spent here. I have a question with snprintf() when size=0, with code below:
#include <stdio.h>
#include <stdlib.h>
int main(int ac, char **av)
{
char *str;
int len;
len = snprintf(NULL, 0, "%s %d", *av, ac);
printf("this string has length %d\n", len);
if (!(str = malloc((len + 1) * sizeof(char))))
return EXIT_FAILURE;
len = snprintf(str, len + 1, "%s %d", *av, ac);
printf("%s %d\n", str, len);
free(str);
return EXIT_SUCCESS;
}
when I run:
momo#xue5:~/TestCode$ ./Test_snprintf
The result is:
this string has length 17
./Test_snprintf 1 17
What confuses me is in the code, the size to be written is 0, why displayed 17?
What did I miss?
Thanks~~
The solution can be found in the man page under Return value;
The functions snprintf() and vsnprintf() do not write more than size bytes (including the terminating null byte ('\0')). If the output was truncated due to this limit then the return value is the number of characters (excluding the terminating null byte) which would have been written to the final string if enough space had been available.
This is so that you can do exactly what you do, a "trial print" to get the correct length, then allocate the buffer dynamically to get the whole output when you snprintf again to the allocated buffer.
I need to implement my own packets to send over UDP. I decided that I would do this by sending a char buffer which has the sequence number, checksum, size, and the data of the packet which is bytes from a file. The string i'm sending separates each field by a semicolon. Then, when I receive the string (which is my packet) I want to extract each felid, use them accordingly (the sequence number, size, and checksum) and write the bytes to a file. So far I have wrote a method to create 100 packets, and I'm trying to extract and write the bytes to a file (I'm not doing it in the receiver yet, first I'm testing the parsing in the sender). For some reason, the bytes written to my file are incorrect and I'm getting "JPEG DATATSTREAM CONTAINS NO IMAGE" error when I try to open it.
struct packetNode{
char packet[1052]; // this is the entire packet data including the header
struct packetNode *next;
};
This is how I'm creating my packets:
//populate initial window of size 100
for(i = 0; i < 100; i++){
memset(&data[0], 0, sizeof(data));
struct packetNode *p; // create packet node
p = (struct packetNode *)malloc(sizeof(struct packetNode));
bytes = fread(data, 1, sizeof(data), fp); // read 1024 bytes from file into data buffer
int b = fwrite(data, 1, bytes, fpNew);
printf("read: %d\n", bytes);
memset(&p->packet[0], 0, sizeof(p->packet));
sprintf(p->packet, "%d;%d;%d;%s", s, 0, numPackets, data); // create packet
//calculate checksum
int check = checksum8(p->packet, sizeof(p->packet));
sprintf(p->packet, "%d;%d;%d;%s", s, check, numPackets, data); //put checksum in packet
s++; //incremenet sequence number
if(i == 0){
head = p;
tail = p;
tail->next = NULL;
}
else{
tail->next = p;
tail = p;
tail->next = NULL;
}
}
fclose(fp);
and this is where I parse and write the bytes to a file:
void test(){
FILE *fpNew = fopen("test.jpg", "w");
struct packetNode *ptr = head;
char *tokens;
int s, c, size;
int i = 0;
char data[1024];
while(ptr != NULL){
memset(&data[0], 0, sizeof(data));
tokens = strtok(ptr->packet,";");
s = atoi(tokens);
tokens = strtok(NULL, ";");
c = atoi(tokens);
tokens = strtok(NULL, ";");
size = atoi(tokens);
tokens = strtok(NULL, ";");
if(tokens != NULL)
strcpy(data, tokens);
printf("sequence: %d, checksum: %d, size: %d\n", s,c,size);
int b = fwrite(data, 1, sizeof(data), fpNew);
ptr = ptr->next;
i++;
}
fclose(fpNew);
}
Since there is transfer of binary data, a JPEG stream, this data cannot be treated as a string. It's better to go all binary. For instance, instead of
sprintf(p->packet, "%d;%d;%d;%s", s, 0, numPackets, data); // create packet
you would do
sprintf(p->packet, "%d;%d;%d;", s, 0, numPackets);
memcpy(&p->packet[strlen(p->packet)], data, bytes);
but this leads to parsing problems: we would need to change this:
tokens = strtok(NULL, ";");
if(tokens != NULL)
strcpy(data, tokens);
to something like this:
tokens += 1 + ( size < 10 ? 1 : size < 100 ? 2 : size < 1000 ? 3 : size < 10000 ? 4 : 5 );
memcpy(data, tokens, sizeof(data));
#Binary Protocol
It's easier to use a binary packet:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#pragma push(pack,1)
typedef struct Packet {
int seq, maxseq, size;
unsigned short cksum;
unsigned char payload[];
} Packet;
#pragma pop(pack)
typedef struct PacketNode{
struct PacketNode * next;
Packet packet;
} PacketNode;
PacketNode * allocPacketNode(int maxPayloadSize) {
void * ptr = malloc(sizeof(PacketNode) + maxPayloadSize); // FIXME: error checking
memset(ptr, 0, sizeof(PacketNode) + maxPayloadSize); // mallocz wouldn't cooperate
return (PacketNode*) ptr;
}
PacketNode * prepare(FILE * fp, int fsize, int chunksize)
{
PacketNode * head = allocPacketNode(chunksize);
PacketNode * pn = head;
int rd, seq = 0;
int maxseq = fsize / chunksize + ( fsize % chunksize ? 1 : 0 );
while ( ( rd = fread(pn->packet.payload, 1, chunksize, fp ) ) > 0 )
{
printf("read %d bytes\n", rd);
pn->packet.seq = seq++;
pn->packet.maxseq = maxseq;
pn->packet.size = rd + sizeof(Packet);
pn->packet.cksum = 0;
pn->packet.cksum = ~checksum(&pn->packet, pn->packet.size);
if ( rd == chunksize )
pn = pn->next = allocPacketNode(chunksize);
}
return head;
}
int checksum(unsigned char * data, int len)
{
int sum = 0, i;
for ( i = 0; i < len; i ++ )
sum += data[i];
if ( sum > 0xffff )
sum = (sum & 0xffff) + (sum>>16);
return sum;
}
void test( PacketNode * ptr ) {
FILE *fpNew = fopen("test.jpg", "w");
while (ptr != NULL)
{
printf("sequence: %d/%d, checksum: %04x, size: %d\n",
ptr->packet.seq,
ptr->packet.maxseq,
ptr->packet.cksum,
ptr->packet.size - sizeof(Packet)
);
int b = fwrite(ptr->packet.payload, ptr->packet.size - sizeof(Packet), 1, fpNew);
ptr = ptr->next;
}
fclose(fpNew);
}
void fatal( const char * msg ) { printf("FATAL: %s\n", msg); exit(1); }
int main(int argc, char** argv)
{
if ( ! argv[1] ) fatal( "missing filename argument" );
FILE * fp = fopen( argv[1], "r" );
if ( ! fp ) fatal( "cannot open file" );
fseek( fp, 0, SEEK_END );
long fsize = ftell(fp);
fseek( fp, 0, SEEK_SET );
printf("Filesize: %d\n", fsize );
test( prepare(fp, fsize, 1024) );
}
The #pragma push(pack,1) changes how the compiler aligns fields of the struct. We want them to be compact, for network transport. Using 1 is byte-aligned. The #pragma pop(pack) restores the previous setting of the pack pragma.
A note on the checksum method
First we calculate the sum of all the bytes in the packet:
int sum = 0, i;
for ( i = 0; i < len; i ++ )
sum += data[i];
Since the packet uses an unsigned short (16 bits, max value 65535 or 0xffff) to store the checksum, we make sure that the result will fit:
if ( sum > 0xffff ) // takes up more than 16 bits.
Getting the low 16 bits of this int is done using sum & 0xffff, masking out everything but the low 16 bits. We could simply return this value, but we would loose the information from higher checksum bits. So, we will add the upper 16 bits to the lower 16 bits. Accessing the higher 16 bits is done by shifting the int to the right 16 bits, like so: sum >> 16. This is the same as sum / 65536, since 65536 = 216 = 1 << 16.
sum = (sum & 0xffff) + (sum>>16); // add low 16 bits and high 16 bits
I should note that network packet checksums are usually computed 2 bytes (or 'octets' as they like to call them there) at a time. For that, the data should be cast to an unsigned short *, and len should be divided by 2. However! len may be odd, so in that case we'll need to take special care of the last byte. For instance, assuming that the maximum packet size is even, and that the len argument is always <= max_packet_size:
unsigned short * in = (unsigned short *) data;
if ( len & 1 ) data[len] = 0; // make sure last byte is 0
len = (len + 1) / 2;
The rest of the checksum method can remain the same, except that it should operate on in instead of data.
Can anyone help converting the Int to char array
as i have buffer as
char *buffer = NULL;
int lengthOfComponent = -1;
char *obj;
buffer[index]= (char *)&lengthOfComponent;
if i do this it is thorwing EXCESS BAD ACCESS after the execution how to store the value of the obj to buffer using memcpy
Of course you cannot write in buffer[index], it is not allocated!
buffer = malloc(sizeof(char) * lengthOfBuffer);
should do it. After that you can write the buffer with memcpy or with an assignation, like you are doing.
buffer[index] = (char *)&lengthOfComponent;
buffer[index] is like dereferencing the pointer. But buffer is not pointing to any valid location. Hence the runtime error.
The C solution is using snprintf. Try -
int i = 11;
char buffer[10];
snprintf(buffer, sizeof(buffer), "%d", i);
I have a structure such as
typedef struct FT_Bitmap_
{
int rows;
int width;
int pitch;
unsigned char* buffer;
short num_grays;
char pixel_mode;
char palette_mode;
void* palette;
} FT_Bitmap;
defining my bitmap data
I want to create a valid bmp file from this structure. How can I do that?
Take a look at:
http://en.wikipedia.org/wiki/BMP_file_format
Write out the header, the palette and the data.
Just take care when you write the bitmap data. It's "upside-down" - the first pixel in data is the left-bottom corner pixel.
First declare three types of initializers you will mostly use:
typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned long dword;
As for the structs, i suggest you using three, each for the element of the BMP:
typedef struct BITMAPINFOHEADER
{
dword bmp_size;
word bmp_app1;
word bmp_app2;
dword bmp_offset;
} BMP;
typedef struct DIB_HEADER
{
dword dib_size;
dword dib_w;
dword dib_h;
word dib_planes;
word dib_bits;
dword dib_compression;
dword dib_rawsize;
dword dib_xres;
dword dib_yres;
dword dib_palette;
dword dib_important;
} DIB;
typedef struct PIXEL_ARRAY
{
byte B;
byte G;
byte R;
} PIX;
Then you can manipulate the image in many ways. You can make an 1D/2D array to contain the data or just manipulate the bmp directly. The following code makes 500x460 colored blank bmp directly:
void new (char NAME[] , byte RED , byte GREEN , byte BLUE)
{
char build_name[256];
const char* id = "BM";
int i, j;
char debug[128];
FILE* fp;
dword rsize = (500 * sizeof(PIX) + 3) / 4 * 4;
dword pad = rsize - 500 * sizeof(PIX);
dword rawsize = rsize * 460 * sizeof(PIX);
byte zero[3] = {0};
dword size = (2) + sizeof(BMP) + sizeof(DIB) + sizeof(PIX);
BMP bmp[] = { 2+sizeof(BMP)+sizeof(DIB)+(sizeof(rawsize)/4), 0, 0, 2+sizeof(BMP)+sizeof(DIB) }; //2+ [!]
DIB dib[] = { sizeof(DIB), 500, 460, 1, 24, 0, (sizeof(rawsize)/4), 2835, 2835, 0, 0 };
PIX pix;
pix.R = RED;
pix.G = GREEN;
pix.B = BLUE;
sprintf(build_name, "%s.bmp", NAME);
fp = fopen(build_name, "wb");
if(!fp) strcpy(debug, "Access Denied.");
else strcpy(debug, "Saved.");
fwrite(id, 1, 2, fp);
fwrite(&bmp, 1, sizeof(bmp), fp);
fwrite(&dib, 1, sizeof(dib), fp);
for(i = 0; i < 460; i++)
{
for(j = 0; j < 500; j++)
{
fwrite(&pix, sizeof(pix), 1, fp);
}
if (pad) fwrite(zero, 1, pad, fp);
}
fclose(fp);
}
The point is using fseek() to locate the pixel and fwrite() to write pixels directly.