So my knowledge of pointers is a bit rusty and I think thats where I'm getting messed up, I am trying to write a function that will grab hex values (an amount n) at a specified offset in the file. And write those values to an array.
File I'm reading from, Example
0 1 2 3 4 5 6 7 8 9 A B C D E F
0 F6 EA 9D DE D8 40 1C 44 19 24 59 D2 6A 2C 48 1D
1 FC 96 DE 94 AF 95 FC 42 9B 6D DA 15 D4 CE 88 BB
2 B8 24 99 8F 65 B5 D3 7E D9 5D 51 44 89 97 61 85
3 2D 40 1A DC D5 16 1F 70 84 F9 85 58 C8 0E 13 80
4 32 AC 10 97 61 B3 16 3B 40 67 7A CA FE E1 4F 2B
5 21 A9 07 F6 80 26 66 04 20 EC 5C E8 FA 70 68 2C
6 1C 78 C4 7E 5C DA B9 9C 41 38 66 3F 19 B6 6A 3A
Here's the function I've written thus far.
aDest point's to an array of size nBytes + 1
bAddr point's to firstbyte of the memory region
OffsetAmt is a location which is relative bAddr
nBytes is just the number of bytes that I want to copy
Heres the function
void getHexBytesAt(uint8_t* const aDest, const uint8_t* const bAddr,
uint16_t OffsetAmt, uint8_t nBytes)
{
const uint8_t *point1 = bAddr; //set he address of point1 to base address value
//front point1 shift until we get to the specified offset value
for (int i = 0; i < Offset; i++)
{
point1 = (point1 + 1);
}
//set the values of *aDest to the value of point1;
//increment point1
for (int k = 0; k < nBytes; k++)
{
*aDest = point1;
point1 = (point1 + 1);
}
The problem I'm having is im not even getting the first byte copied into the array correctly,
My output looks like this Getting 9 bytes,
starting at the offset 2C
MY OUTPUT: 84 CA CA CA CA CA CA CA CA
FILE: 89 97 61 85 2D 40 1A DC D5
If you want to read the data from the Memory bAddr then you must
dereference the pointer for reading
increment the Destination pointer
This would be implemented like this:
void getHexBytesAt(uint8_t* const aDest, const uint8_t* const bAddr,
uint16_t OffsetAmt, uint8_t nBytes)
{
const uint8_t *point1 = bAddr; //set he address of point1 to base address value
//front point1 shift until we get to the specified offset value
for (int i = 0; i < OffsetAmt; i++) // fixed typo
{
point1 = (point1 + 1);
}
//set the values of *aDest to the value of point1;
//increment point1
for (int k = 0; k < nBytes; k++)
{
*aDest = *point1; // copy data from address the point1 points to
aDest = aDest + 1; // increment destination pointer
point1 = (point1 + 1);
}
}
But this can be done much simpler:
void getHexBytesAt(uint8_t* const aDest, const uint8_t* const bAddr,
uint16_t OffsetAmt, uint8_t nBytes)
{
memcpy(aDest, bAddr + OffsetAmt, nBytes);
}
You should consider replacing the function with the one-liner that implements it in your code.
BTW: There is no file used in the code. You should review your question.
Related
Given a byte array buff of length n:
unsigned char buff[n] = "....." // len n
I want to delete m characters at position pos,
0 < pos, m, pos + m < n
I tried using memmove:
memmove(buff + pos, buff + pos + m, n - (pos + m) + 1);
But this doesn't work for byte array as we don't have '\0' terminator for this buff (but we know its length)
How do I delete bytes in between? Anyone please help
Edit: Sample input,
Pos Data
0000 03 00 02 ef 02 f0 80 64 00 08 03 eb 70 82 e0 40
0010 00 ff 30 00 00 00 00 b3 47 43 00 00 00 00 00 00
0020 00 1e 00 c4 00 00 00 00 00 00 00 44 00 65 00 66
0030 00 61 00 75 00 6c 00 74 00 41 00 6c 00 74 00 53
Say I want to delete the highlighted bytes from packet.
New paket,
Pos Data
0000 03 00 02 ef 02 f0 80 64 00 08 03 00 00 00 00 00
0010 00 00 44 00 65 00 66 00 61 00 75 00 6c 00 74 00
0020 41 00 6c 00 74 00 53
This would erase m chars in an array without terminating null character.
int main()
{
int pos = 1, m = 3;
unsigned char arr[8] = {1,2,3,4,5,6,7,8};
memmove(arr + pos, arr + pos + m, sizeof(arr)/sizeof(arr[0]) - pos - m);
// if required to zero-out the remaining elements
memset(arr + sizeof(arr)/sizeof(arr[0]) - m, 0, m);
for (int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++)
printf("%hhu ", arr[i]);
return 0;
}
Output: 1 5 6 7 8 0 0 0
You probably want something like this:
#include <stdio.h>
#include <string.h>
void Display(const char buff[], int nb)
{
for (int i = 0; i < nb; i++)
printf("%d ", buff[i]);
printf("\n");
}
int main()
{
unsigned char buff[20] = { 0,1,2,3,4,5 };
// buff has room for 20 elements
int nbelements = 6; // but there are only 6 meaningful elements
Display(buff, nbelements);
int pos = 1; // delete from element 1
int nbtodelete = 2; // delete 2 elements
memmove(buff + pos, buff + pos + nbtodelete, nbelements - pos - 1);
nbelements -= nbtodelete;
Display(buff, nbelements);
}
Output:
0 1 2 3 4 5
0 3 4 5
It's pretty self explanatory.
I have token (base64url) that i need to decrypt with aes-gcm. The token contains:
16 bytes for IV, 17 bytes for TAG and the rest is the binary that needs to be decrypted.
I can't seem to be able to figure out, this is my code:
{
unsigned char * source = "BASE64-ENCODED-BINARY";
unsigned char key_raw[] = "KEY";
unsigned char key[2048];
int key_len = 0;
unsigned char output[2048];
int output_len = 0;
unsigned char * plaintext;
int c, r;
size_t out;
int dest_len = 4*(sizeof(source)/3);
// int key_len = 4*(sizeof(key_raw)/3);
unsigned char iv[16];
unsigned char tag[16];
unsigned char content[2048];
int content_len = 0;
b64ud_t s;
EVP_CIPHER_CTX *ctx;
int outlen, tmplen, rv;
unsigned char outbuf[2048];
/* token decode */
base64url_decode_reset(&s);
//memset( output,0, dest_len );
base64url_decode( output, 2048, source, strlen(source), NULL );
/* Just look through the output to get the decode result len */
for(;;)
{
if( output[output_len] )
{
output_len++;
} else {
break;
}
}
printf("decoded-token: [length: %d]\n", output_len );
BIO_dump_fp(stdout, output, output_len);
/* ket decode */
base64url_decode_reset(&s);
memset( key, 0, key_len );
base64url_decode( key, key_len-1, key_raw, strlen(key_raw), NULL );
/* Just look through the key to get the decode result len */
for(;;)
{
if( key[key_len] )
{
key_len++;
} else {
break;
}
}
printf("decoded-key: [Length: %d]\n", key_len );
BIO_dump_fp(stdout, key, key_len);
/*
The token is composed like so:
[16bytes IV] + [16 bytes TAG] + [Encrypted Message]
*/
printf("getting 16 bytes out of the decode output and storing them in IV\n");
for(int v=0;v<16;v++)
{
iv[v] = output[v];
}
printf("getting the NEXT 16 bytes out of the decode output and storing them in TAG\n");
for(int v=16;v<32;v++)
{
tag[v-16] = output[v];
}
printf("Just count haw many non-00 bytes remain and store it in content_len\n");
for(int i=32;i<output_len;i++)
{
if(output[i])
{
content_len++;
} else {
break;
}
}
printf("%d\n", content_len);
printf("We now use content_len and get the remaining bytes and store them in content\n");
for(int v=0; v<content_len;v++)
{
content[v] = output[v+32];
}
printf( "iv:\n" );
BIO_dump_fp(stdout, iv, sizeof(iv));
printf("tag:\n" );
BIO_dump_fp(stdout, tag, sizeof(tag));
printf("content :\n" );
BIO_dump_fp(stdout, content, content_len);
printf("AES GCM Decrypt:\n");
unsigned char * key_final;
key_final = key;
unsigned char * ciphertext;
ciphertext = content;
printf("Ciphertext:\n");
BIO_dump_fp(stdout, content, content_len);
ctx = EVP_CIPHER_CTX_new();
/* Select cipher */
EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
/* Set IV length, omit for 96 bits */
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, sizeof(iv), NULL);
/* Specify key and IV */
EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv);
/* Zero or more calls to specify any AAD */
//EVP_DecryptUpdate(ctx, NULL, &outlen, gcm_aad, sizeof(gcm_aad));
/* Decrypt plaintext */
EVP_DecryptUpdate(ctx, outbuf, &outlen, ciphertext, content_len);
/* Output decrypted block */
printf("Plaintext:\n");
BIO_dump_fp(stdout, outbuf, outlen);
/* Set expected tag value. */
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, sizeof(tag), (void *)tag);
/* Finalise: note get no output for GCM */
rv = EVP_DecryptFinal_ex(ctx, outbuf, &outlen);
/*
* Print out return value. If this is not successful authentication
* failed and plaintext is not trustworthy.
*/
printf("outbuf: %s", outbuf);
printf("Tag Verify %s\n", rv > 0 ? "Successful!" : "Failed!");
EVP_CIPHER_CTX_free(ctx);
return 0;
}
My output is:
decoded-token: [length: 57]
0000 - ae 3f d9 92 46 54 39 93-31 64 e7 ce 98 ba 44 50 .?..FT9.1d....DP
0010 - 1d ec 89 4e ee e9 18 d9-15 e3 3d b3 e8 1b ff 10 ...N......=.....
0020 - 91 e7 a5 85 28 50 09 88-cc 85 d9 3e 82 05 19 a5 ....(P.....>....
0030 - 87 f4 b2 d2 2f e5 7f 24-fd ..../..$.
decoded-key: [Length: 33]
0000 - 0e 0b e4 0a b9 32 04 d4-b2 f7 21 cf d5 8c e7 c9 .....2....!.....
0010 - cd 83 90 74 c8 51 76 8e-e8 d9 44 c3 80 92 ab 40 ...t.Qv...D....#
0020 - e3 .
doing iv
doing tag
getting content length: 25
copying content length to content var
iv:
0000 - ae 3f d9 92 46 54 39 93-31 64 e7 ce 98 ba 44 50 .?..FT9.1d....DP
tag:
0000 - 1d ec 89 4e ee e9 18 d9-15 e3 3d b3 e8 1b ff 10 ...N......=.....
content :
0000 - 91 e7 a5 85 28 50 09 88-cc 85 d9 3e 82 05 19 a5 ....(P.....>....
0010 - 87 f4 b2 d2 2f e5 7f 24-fd ..../..$.
AES GCM Decrypt:
Ciphertext:
0000 - 91 e7 a5 85 28 50 09 88-cc 85 d9 3e 82 05 19 a5 ....(P.....>....
0010 - 87 f4 b2 d2 2f e5 7f 24-fd ..../..$.
Plaintext:
0000 - f3 6d 72 13 d9 dd 5b a3-b6 af 73 8d a2 93 8b f7 .mr...[...s.....
0010 - 0e 9e 2a 87 6c 82 84 bd-46 ..*.l...F
outbuf: �mr��[���s������*�l���FTag Verify Failed!
I can't be 100% I'm doing it right, but anyway i'm getting Verify Failed!
Help is GREATLY appreciated!
I'm not very familiar with AES, but this code looks suspicious:
int dest_len = 4*(sizeof(source)/3);
because source is defined as:
unsigned char * source = "BASE64-ENCODED-BINARY";
and in consequence sizeof(source) gives you the size of a pointer.
Try:
int dest_len = 4*(strlen(source)/3);
or define source as:
const unsigned char source[] = "BASE64-ENCODED-BINARY";
I want to create a function in c, which creates every 8 increments (to be exact, when an integer holds the value 8) a paragraph/new line (and also prints an offset).
In this case, i've got an array
for (int i = 0; i < sizeof(myarray); i++){
printf(" %02hhX", myarray[i]);
}
Now i want to implement my function like this
int row = 0;
for (int i = 0; i < sizeof(myarray); i++){
printf(" %02hhX", myarray[i]);
check_newline(row);
}
The function 'check_newline' has this structure:
void check_newline(int row){
row++;
if(row==8){
offset = offset + 8;
row= 0;
printf("\n%06X", offset);
}
}
Everytime, the integer 'row' reaches the value 8 a new offset will be printed and the value of 'row' will be reset to 0.
Now, i don't know how to implement the return; and with this code, my output looks like this
000008 E0 60 66 64 38 7D E0 60 66 64 38 7D 80000008 80 00 FF FF FF FF FF FF 000010 E0 60 66 64 38 7D E0 60 66 64 38 7D 80000010 80 00 FF FF FF FF FF FF
(totaly wrong)
When i 'put the function inside my code' (so basicaly don't use a function), everything is nice, because of the missing return statement.
for (int i = 0; i < sizeof(myarray); i++){
printf(" %02hhX", myarray[i]);
row++;
if(row==8){
offset = offset + 8;
row= 0;
printf("\n%06X", offset);
}
000000 80 00 FF FF FF FF FF FF
000008 E0 60 66 64 38 7D E0 60
I have to use this kind of calculation often in my code, so a function will be more sleek.
You are over complicating things. You don't need the extra variables as you can make use of i and the % (modulo operator) to work out when you're at the beginning or end of a row like this.
for (int i = 0; i < sizeof(myarray); i++) {
if (i % 8==0) {
printf("%06X",i);
}
printf(" %02hhX", myarray[i]);
if (i % 8==7) {
printf("\n");
}
}
I tried to imitate a struct with a unsigned char array or pointer, but I am not able to obtain the same hex values.
.input is correct with print().
I am trying to get the same effect from stringBytes_Data or data_hexStrFormatted with print().
Can anyone advise?
Given
struct _vector {
char *input;
unsigned char len;
};
static struct _vector tv2 = {
.input = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
"\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
"\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
"\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
"\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
"\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
"\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
"\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
.len = 64,
};
And function to view the data:
static void print(char *intro_message, unsigned char *text_addr,
unsigned int size) {
unsigned int i;
for (i = 0; i < size; i++) {
printf("%2x ", text_addr[i]);
if ((i & 0xf) == 0xf)
printf("\n");
}
printf("\n");
}
How may I get the same effect with:
char* stringBytes_Data = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710";
I tried, but the result is wrong :
unsigned char* data_hexStrFormatted;
int lengthOfStr = strlen(stringBytes_Data);
int charCounterForNewStr = 0;
int formattedLength = (2*lengthOfStr)+1;
data_hexStrFormatted = (unsigned char*) malloc((formattedLength)*sizeof(unsigned char)); // x2 as we add \x to XX, and 1 for NULL end char
for(i=0; i<lengthOfStr; i=i+2) {
// prepend \x
data_hexStrFormatted[charCounterForNewStr++] = '\\';
data_hexStrFormatted[charCounterForNewStr++] = 'x';
data_hexStrFormatted[charCounterForNewStr++] = stringBytes_Data[i];
data_hexStrFormatted[charCounterForNewStr++] = stringBytes_Data[i+1];
}
data_hexStrFormatted[formattedLength-1] = '\0';
printf("%s\n", data_hexStrFormatted);
printf("%d byte length \n", strlen(data_hexStrFormatted)/4);
print("data_hexStrFormatted",
(unsigned char *)
data_hexStrFormatted,
(formattedLength)/4);
You seem to be asking:
Given a string containing pairs of hex digits, convert the hex digits to byte values?
If so, then code similar to the following can be used:
static inline int hexit(const unsigned char c)
{
static const char hex_digits[] = "0123456789ABCDEF";
return strchr(hex_digits, toupper(c)) - hex_digits;
}
This function works correctly for valid hex digits; it will produce nonsense for invalid inputs. If you decide you need to detect erroneous input, you'll need to improve it. There are other ways to write this function (lots of them, in fact). One that can be effective is an array of 256 bytes statically initialized with the correct values, so you simply write return hex_array[c];.
char* stringBytes_Data = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710";
size_t len = strlen(stringBytes_Data);
char buffer[len / 2];
assert(len % 2 == 0);
for (size_t i = 0; i < len; i += 2)
buffer[i / 2] = hexit(stringBytes_Data[i]) << 4 | hexit(stringBytes_Data[i+1]);
printf("%.*s\n", (int)len/2, buffer);
This code sets the array buffer to contain the converted code. It won't work correctly if there's an odd number of characters in the array (that's what the assertion states).
Working code - #2
Using the print() function from the question with the info_message argument removed since it is unused:
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
struct Vector
{
char *input;
unsigned char len;
};
static struct Vector tv2 =
{
.input = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
"\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
"\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
"\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
"\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
"\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
"\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
"\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
.len = 64,
};
static inline int hexit(const unsigned char c)
{
static const char hex_digits[] = "0123456789ABCDEF";
return strchr(hex_digits, toupper(c)) - hex_digits;
}
static void print(unsigned char *text_addr, unsigned int size)
{
unsigned int i;
for (i = 0; i < size; i++)
{
printf("%2x ", text_addr[i]);
if ((i & 0xf) == 0xf)
printf("\n");
}
printf("\n");
}
static void print2(const char *tag, const unsigned char *data, size_t size)
{
printf("%s:\n", tag);
for (size_t i = 0; i < size; i++)
{
printf("%2x ", data[i]);
if ((i & 0x0F) == 0x0F)
printf("\n");
}
printf("\n");
}
static void print_text(const char *tag, const char *data, size_t datalen)
{
char buffer[datalen / 2];
assert(datalen % 2 == 0);
for (size_t i = 0; i < datalen; i += 2)
buffer[i / 2] = hexit(data[i]) << 4 | hexit(data[i + 1]);
//printf("%s: [[%.*s]]\n", tag, (int)datalen / 2, buffer);
assert(memcmp(buffer, tv2.input, tv2.len) == 0);
print((unsigned char *)buffer, datalen / 2);
print2(tag, (unsigned char *)buffer, datalen / 2);
}
int main(void)
{
char *stringBytes_Data =
"6bc1bee22e409f96e93d7e117393172a"
"ae2d8a571e03ac9c9eb76fac45af8e51"
"30c81c46a35ce411e5fbc1191a0a52ef"
"f69f2445df4f9b17ad2b417be66c3710"
;
print_text("buffer", stringBytes_Data, strlen(stringBytes_Data));
return 0;
}
Sample output:
6b c1 be e2 2e 40 9f 96 e9 3d 7e 11 73 93 17 2a
ae 2d 8a 57 1e 3 ac 9c 9e b7 6f ac 45 af 8e 51
30 c8 1c 46 a3 5c e4 11 e5 fb c1 19 1a a 52 ef
f6 9f 24 45 df 4f 9b 17 ad 2b 41 7b e6 6c 37 10
buffer:
6b c1 be e2 2e 40 9f 96 e9 3d 7e 11 73 93 17 2a
ae 2d 8a 57 1e 3 ac 9c 9e b7 6f ac 45 af 8e 51
30 c8 1c 46 a3 5c e4 11 e5 fb c1 19 1a a 52 ef
f6 9f 24 45 df 4f 9b 17 ad 2b 41 7b e6 6c 37 10
Working code - #1
Redone — previous versions had various 'off by a factor of two' errors which were partially concealed by the system zeroing a buffer.
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
struct Vector
{
char *input;
unsigned char len;
};
static struct Vector tv2 =
{
.input = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
"\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
"\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
"\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
"\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
"\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
"\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
"\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
.len = 64,
};
static inline int hexit(const unsigned char c)
{
static const char hex_digits[] = "0123456789ABCDEF";
return strchr(hex_digits, toupper(c)) - hex_digits;
}
static void print(const char *tag, const unsigned char *data, size_t size)
{
printf("%s:\n", tag);
for (size_t i = 0; i < size; i++)
{
printf("%2x ", data[i]);
if ((i & 0x0F) == 0x0F)
printf("\n");
}
printf("\n");
}
static void print_text(const char *tag, const char *data, size_t datalen)
{
char buffer[datalen / 2];
assert(datalen % 2 == 0);
for (size_t i = 0; i < datalen; i += 2)
buffer[i / 2] = hexit(data[i]) << 4 | hexit(data[i + 1]);
printf("%s: [[%.*s]]\n", tag, (int)datalen / 2, buffer);
assert(memcmp(buffer, tv2.input, tv2.len) == 0);
print(tag, (unsigned char *)buffer, datalen / 2);
}
int main(void)
{
char *stringBytes_Data =
"6bc1bee22e409f96e93d7e117393172a"
"ae2d8a571e03ac9c9eb76fac45af8e51"
"30c81c46a35ce411e5fbc1191a0a52ef"
"f69f2445df4f9b17ad2b417be66c3710"
;
print_text("buffer", stringBytes_Data, strlen(stringBytes_Data));
return 0;
}
Raw output on a UTF-8 terminal (it isn't valid UTF-8 data, hence the question marks):
buffer: [[k???.#???=~s?*?-?W????o?E??Q0?F?\????
R???$E?O??+A{?l7]]
buffer:
6b c1 be e2 2e 40 9f 96 e9 3d 7e 11 73 93 17 2a
ae 2d 8a 57 1e 3 ac 9c 9e b7 6f ac 45 af 8e 51
30 c8 1c 46 a3 5c e4 11 e5 fb c1 19 1a a 52 ef
f6 9f 24 45 df 4f 9b 17 ad 2b 41 7b e6 6c 37 10
Raw output converted into UTF-8 as if it was ISO 8859-15 (or 8859-1):
buffer: [[kÁŸâ.#é=~s*®-W¬·o¬E¯Q0ÈF£\äåûÁ
Rïö$EßO+A{æl7]]
buffer:
6b c1 be e2 2e 40 9f 96 e9 3d 7e 11 73 93 17 2a
ae 2d 8a 57 1e 3 ac 9c 9e b7 6f ac 45 af 8e 51
30 c8 1c 46 a3 5c e4 11 e5 fb c1 19 1a a 52 ef
f6 9f 24 45 df 4f 9b 17 ad 2b 41 7b e6 6c 37 10
The data doesn't seem to have any particular meaning, but beauty is in the eye of the beholder.
I am developing a Client/Server based on UDP I want to send different messages to the client from the server. There are different C structures defined for each message.
I would like to understand what is wrong in the way I am serializing the data.
struct Task
{
int mType;
int tType;
int cCnt;
int* cId;
char data[128];
};
Serialization/Deserialization functions
unsigned char * serialize_int(unsigned char *buffer, int value)
{
buffer[0] = value >> 24;
buffer[1] = value >> 16;
buffer[2] = value >> 8;
buffer[3] = value;
return buffer + 4;
}
unsigned char * serialize_char(unsigned char *buffer, char value)
{
buffer[0] = value;
return buffer + 1;
}
int deserialize_int(unsigned char *buffer)
{
int value = 0;
value |= buffer[0] << 24;
value |= buffer[1] << 16;
value |= buffer[2] << 8;
value |= buffer[3];
return value;
}
char deserialize_char(unsigned char *buffer)
{
return buffer[0];
}
Sender side code to serialize the structure
unsigned char* serializeTask(unsigned char* msg, const Task* t)
{
msg = serialize_int(msg,t->mType);
msg = serialize_int(msg,t->tkType);
msg = serialize_int(msg,t->cCnt);
for(int i=0; i<t->cCnt; i++)
msg = serialize_int(msg,t->cId[i*4]);
for(int i=0; i<strlen(data); i++)
msg = serialize_char(msg,t->data[i]);
return msg;
}
Receiver side code to de-serialize data
printf("Msg type:%d\n", deserialize_int(message) );
printf("Task Type:%d\n", deserialize_int(message+4) );
printf("Task Count:%d\n", deserialize_int(message+8));
Output
Msg type:50364598 //Expected value is 3
Task Type:-2013036362 //Expected value is 1
Task Count:1745191094 //Expected value is 3
Question 1:
Why is the de-serialized value not same as expected?
Question 2:
How is serialization/de-serialization method different from memcpy?
Task t;
memcpy(&t, msg, sizeof(t)); //msg is unsigned char* holding the struct data
EDIT
Code which invokes serializeTask
void addToDatabase(unsigned char* message, int msgSize, Task* task)
{
message = new unsigned char[2*msgSize+1];
unsigned char* msg = message; //To preserve start address of message
message = serializeTask(message, task); //Now message points to end of the array
//Insert serialized data to DB
//msg is inserted to DB
}
Serialized data stored in DB
Message:
00
03 70 B6 88 03 70 B6 68 05 70 B6 68 05 70 B6 00
00 00 00 00 00 00 00 A8 05 70 B6 AC 05 70 B6 B4
05 70 B6 C9 05 70 B6 DE 05 70 B6 E6 05 70 B6 EE
05 70 B6 FB 05 70 B6 64 65 66 00 63 6F 68 6F 72
74 73 00 70 65 6E 64 69 6E 67 5F 61 73 73 69 67
6E 5F 74 61 73 6B 73 00 70 65 6E 64 69 6E 67 5F
61 73 73 69 67 6E 5F 74 61 73 6B 73 00 6D 65 73
73 61 67 65 00 6D 65 73 73 61 67 65 00 3F 00 FF
FF 00 00 FC 90 00 00 00 00 00 00 00 C9 2D B7 00
00 00 00 10 06 70 B6 00 00 00 00 00 00 00 00 30
06 70 B6 34 06 70 B6 3C 06 70 B6
OP has 2 problems in serializeTask()
for(int i=0; i<t->cCnt; i++)
msg = serialize_int(msg,t->cId[i*4]); [i*4]
...
for(int i=0; i<strlen(data); i++)
msg = serialize_char(msg,t->data[i]); strlen(data)
Should be (assuming i<strlen(data) should have been i<strlen(t->data)
for(int i=0; i<t->cCnt; i++)
msg = serialize_int(msg,t->cId[i]); // [i]
...
for(int i=0; i<strlen(t->data); i++) // strlen(data) + 1
msg = serialize_char(msg,t->data[i]);
The first for loop serialize every 4th cId[]. OP certainly wanted to serialize consecutive cId[].
Only the length of the data string was serialized. OP certainly wanted to serialize all that and a NUL terminating byte.
The data in the posted buffer is more likely the below, which does not match the serialization code. This implies the higher level code populating Task* t is wrong. I am confident that the values seen in fields mType and tkType are either pointers or float, again Task* t is likely amiss before the serialization.
0xb6700300 or -3.576453e-06
0xb6700388 or -3.576484e-06
0xb6700568 or -3.576593e-06
0xb6700568 or -3.576593e-06
0x000000 or 0.000000e+00
0x000000 or 0.000000e+00
0xb67005a8 or -3.576608e-06
0xb67005ac or -3.576609e-06
0xb67005b4 or -3.576611e-06
0xb67005c9 or -3.576615e-06
0xb67005de or -3.576620e-06
0xb67005e6 or -3.576622e-06
0xb67005ee or -3.576624e-06
0xb67005fb or -3.576627e-06
def\0cohorts\0pending_assign_tasks\0pending_assign_tasks\0message\0message\0?\0
...