-1

I have to create a request datagram (RRQ) for a Tftp client like this:

enter image description here

But i can't use a struct because the fields have variable length.

i tried the struct and something iterating on a char.

Weather Vane
  • 33,872
  • 7
  • 36
  • 56
TusMuela
  • 3
  • 2
  • 1
    What exactly are you asking? I mean, the natural thing to do appears to be to use an array of `char` or of `unsigned char`, and it kinda sorta seems like you already have that in mind. What's the hangup? – John Bollinger Nov 22 '22 at 20:34
  • you are going to have to marshall the data into a char buffer – pm100 Nov 22 '22 at 20:35
  • @JohnBollinger i want to do something like this: create a char datagram[length], then add the opcode (datagram=htons(1) i think), then add the second field, then the 0... – TusMuela Nov 22 '22 at 20:43
  • @JohnBollinger i dont know how to add them one by one. – TusMuela Nov 22 '22 at 20:45
  • 1
    @TusMuela, `sprintf()`, `strcpy()`, `memcpy()`, .... – John Bollinger Nov 22 '22 at 20:46
  • If the image is text (I can't check, it's blocked on my computer) it should be pasted into the question. – unwind Nov 22 '22 at 20:46
  • Are you trying to use the TFTP spec literally or are you trying to create your own (similar) protocol? – Craig Estey Nov 22 '22 at 20:48

1 Answers1

0

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);
}
Schwern
  • 153,029
  • 25
  • 195
  • 336