I have to create a request datagram (RRQ) for a Tftp client like this:
But i can't use a struct because the fields have variable length.
i tried the struct and something iterating on a char.
Create an array of bytes and append to it. You can make this easier by using pointer arithmetic to keep track of where you've written, kind of like a cursor.
We can make life easier for ourselves by tracking where in the request memory the archive and mode strings start so we can easily find them later.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <inttypes.h>
typedef struct {
char *archive;
char *mode;
char *request;
} Read_Request;
Read_Request *read_request_create(const char *archive, const char *mode) {
Read_Request *rrq = malloc(sizeof(Read_Request));
// Allocate sufficient memory for the opcode and both strings,
// including the terminating nulls.
rrq->request = malloc(2 + strlen(archive) + 1 + strlen(mode) + 1);
// Start the request with the opcode.
// 2 byte network byte order integer.
uint16_t opcode = htons(1);
memcpy(rrq->request, &opcode, sizeof(opcode));
// Put the start of the archive 2 bytes in, just after the opcode.
rrq->archive = rrq->request + 2;
// Copy the archive string into position.
strcpy(rrq->archive, archive);
// Put the start of the mode just after the archive and its null byte.
rrq->mode = rrq->archive + strlen(archive) + 1;
// Append the mode.
strcpy(rrq->mode, mode);
return rrq;
}
Then printing is easy. Print the 2 byte opcode. Then since a C string stops at a null byte, we can simply print the archive and mode strings.
void read_request_print(Read_Request *rrq) {
// Turn the first two bytes (the opcode) into two hex characters.
unsigned char *opcode = (unsigned char *)rrq->request;
printf("opcode: %0x%0x\n", opcode[0], opcode[1]);
printf("archive: '%s'\n", rrq->archive);
printf("mode: '%s'\n", rrq->mode);
}
int main() {
Read_Request *rrq = read_request_create("archive", "mode");
read_request_print(rrq);
}