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.

Was it helpful?

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 :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top