c - sendto/recvfrom not getting correct information on some end

67 Views Asked by At

I'm coding a server/client TCP implementation in c for class and I'm stuck, unsure why I'm not getting the correct data on one of the ends of my implementation. This only needs to work on a loopback address so I'm not too concerned with it working over an actual internet connection.

The struct storing header information that I am using in both programs is below, and my declaration of one of the struct...

struct header
{
  u_int16_t segnumber;
  u_int16_t ack;
  u_int8_t flags;
  u_int8_t window;
  u_int16_t size;
  char data[MAXPAYLOADSIZE];
};
struct header* window = (struct header*)malloc(sizeof(struct header));

I get to this portion of the code in the client where the server has sent as many messages as I have advertised that the client can receive all at once. The print debug statement here lets me know that the fields in the struct are exactly what I am expecting to send with all 0's in the struct except the window which is 5.

else if (((window->flags >> RWAFLAG) & 1U) == 1)
  {
    memset(ackno, 0, sizeof(*ackno));
    ackno->window = WINDOW_SIZE;
    fprintf(stderr, "Fields sent: segnum: %d, ack: %d, flags... EOM: %d, RWA: %d, ACK: %d, DAT: %d, window: %d, msg: %s\n", ackno->segnumber, ackno->ack, ((ackno->flags >> EOMFLAG) & 1U),((ac    kno->flags >> RWAFLAG) & 1U),((ackno->flags >> ACKFLAG) & 1U),((ackno->flags >> DATFLAG) & 1U), ackno->window, ackno->data);
    sendto(endpoint, &ackno, sizeof(struct header),  0, (const struct sockaddr *) &source, len);
  }

I get stuck in this portion of the server code where I am expecting the window size to be sent from the client to let the server know it is ready to receive more segments. I'm expecting that I would receive all 0's except a window of 5 but the debug message lets me know that I am receiving a random segnum and random ack value (random between runs, but the same exact number during a single run) and 0's for every other field of the struct.

while (receiversWindowSize < 1) {
  memset(bphfirst, 0 , sizeof(*bphnext));
  bphfirst->flags |= 1U << RWAFLAG;
  sendto(endpoint, bphfirst, sizeof(struct header), 0, (const struct sockaddr *) &dest,  sizeof(dest));
  memset(bphwindow, 0 , sizeof(*bphwindow));
  alarm(10);
  if (err == 69)
  {
    signal(SIGALRM, send);
    err = 0;
    alarm(10);
  }
  n = recvfrom(endpoint, (struct header *) bphwindow, sizeof(struct header), 0, (struct sockaddr *) &sender, (socklen_t *)&len);
  fprintf(stderr, "Fields received: segnum: %d, ack: %d, flags... EOM: %d, RWA: %d, ACK: %d, DAT: %d, window: %d, msg: %s\n", bphwindow->segnumber, bphwindow->ack, ((bphwindow->flags >> E    OMFLAG) & 1U),((bphwindow->flags >> RWAFLAG) & 1U),((bphwindow->flags >> ACKFLAG) & 1U),((bphwindow->flags >> DATFLAG) & 1U), bphwindow->window, bphwindow->data);
  if (n < 0 ) {
    perror("No data received");
  }
  else
  {
    receiversWindowSize = bphwindow->window;
    //fprintf(stderr, "receiversWindowSize: %d\n", receiversWindowSize);
  }

  if (((bphwindow->flags >> ACKFLAG) & 1U) == 1 && bphwindow->ack == bphnext->segnumber) {
    if (lastSegAccepted == 1) {
      lastSegAccepted = 2;
      break;
    }
    if (segCount++ >  65535) {
      segCount = 0;
    }
    readBytes = fread(buf, 1, 512, stdin);
    if (readBytes != MAXPAYLOADSIZE) {
      bphnext->flags |= 1UL << EOMFLAG;
      //printf("%d\n", next.EOM);
      lastSegAccepted = 1;
    }
    memset(bphnext, 0 , sizeof(*bphnext));
    bphnext->segnumber = (uint16_t) segCount;
    bphnext->flags |= 1UL << DATFLAG;
    bphnext->size = (uint16_t) readBytes;
    memcpy(bphnext->data, buf, readBytes);
  }
}

I have an earlier exchange between these two where the sendto/recvfrom exchange an RWA flag and window size with no issue and the first windowSize worth of sendto messages from the server are received by the client without issue. The problem crops up when attempting to reset the windowSize.

I am including the alarm sighandler here just in case it is relevant

void send(int signum)
{
  fprintf(stderr, "Sending RWA again\n");
  //fprintf(stderr, "n: %d\n", n);
  fprintf(stderr, "bphwindow->window: %d\n", bphwindow->window);
  sendto(endpoint, bphfirst, sizeof(struct header), 0, (const struct sockaddr *) &dest, sizeof(dest));
  err = 69;
}

Thanks in advance for any help, please let me know if you need any more information.

0

There are 0 best solutions below