Adding custom message header
-
14-11-2019 - |
Question
Can anyone tell me: "How To Construct A Header?" I am writing an FTP Client-Server Code. And I want to add a Header at Client Side for all data packets I have to send to server with information like the size of my data,etc.
I have seen some examples at SO but cant' figure out the exact way. Any pointers towards sample/example code would be appreciated.
Solution 3
Define a struct with members you want to be in your Header at both Client-Server( Better to include a Header file with the struct in both ). Send the Header prior to original message. recv at server with parameter of the fixed length of struct.
typedef struct
{
DWORD dwMsgType ;
DWORD dwMsgSize ;
}MSG_HEADER, *PMSG_HEADER ;
OTHER TIPS
Check out scapy, a library for constructing packets. I think it's what you need.
The best way to build up protocol data is to have a buffer of uint8_t
somewhere and fill it as specified in the protocol.
For FTP proper, this is rather simple, as there are only ASCII strings in the control connection. Something like this may work:
bool append_literal(uint8_t **cursor, uint8_t *end, uint8_t const *data, size_t size) {
assert(cursor);
assert(*cursor);
assert(end);
assert(*cursor < end);
assert(data);
if((end - *cursor) < size) // Check buffer limit
return false;
memcpy(*cursor, data, size); // Copy
*cursor += size; // Increment cursor
return true;
}
bool append_number(uint8_t **cursor, uint8_t *end, uint64_t number) {
assert(cursor);
assert(*cursor);
assert(end);
assert(*cursor < end);
if((end - *cursor) < 17) // Max number of base 10 digits in uint64_t
return false;
*cursor += sprintf(*cursor, "%" PRIu64, number);
return true;
}
bool append_uint32_binary(uint8_t **cursor, uint8_t *end, uint32_t value) {
assert(cursor);
assert(*cursor);
assert(end);
assert(*cursor < end);
if((end - *cursor) < 4) // Bytes needed for uint32 value
return false;
*(*cursor)++ = (value >> 24) & 0xff;
*(*cursor)++ = (value >> 16) & 0xff;
*(*cursor)++ = (value >> 8) & 0xff;
*(*cursor)++ = value & 0xff;
return true;
}
// Specific FTP commands
bool append_size_command(uint8_t **cursor, uint8_t *end, uint64_t size) {
return append_literal(cursor, end, "SIZE ", 5) &&
append_number(cursor, end, size) &&
append_literal(cursor, end, "\r\n", 2);
}
// [...]
bool send_size_command(int fd, uint64_t size) {
uint8_t buffer[32];
uint8_t *cursor = buffer;
uint8_t *const end = buffer + sizeof buffer;
if(!append_size_command(&cursor, end, size))
return false;
size_t length = cursor - buffer;
ssize_t sent = send(fd, buffer, length, 0);
return (sent == length);
}
The "assert" statements test things that will always be true if your program is written correctly, that is, the pointers are valid. Any function returns true
on success, and false
if it failed.
I've used the standard POSIX functions for the sockets, because WinSock implements these, and they are fairly portable.
Your homework is to find the headers you need to include for PRIu64
:)