void mySendFrame(unsigned char* databuff, int size) {//add crc and cooperate with physical layer. databuff should be ready to send. size shoule be without crc if (databuff[0] != FRAME_NAK) { //piggyback ack short i = (receiverLeft - 1) % windowSize;//log the last ack arrived if (i < 0) i += windowSize; for (short j = 0; j < bufferSize; j++) { if (receiver[(receiverLeft + j) % bufferSize].frameArrived) i = (receiverLeft + j) % windowSize; else break; } databuff[0] == FRAME_DATA ? databuff[2] = i : databuff[1] = i; } //append crc *(unsigned int*)(databuff + size) = crc32(databuff, size); size += 4;//add length if (databuff[0] == FRAME_DATA) //add timer start_timer(databuff[1], retimer); //piggyback ack timer if (databuff[0] != FRAME_NAK) { stop_ack_timer(); start_ack_timer(acktimer); } send_frame(databuff, size); }
static void send_ack_frame(void) { struct FRAME s; s.kind = FRAME_ACK; s.ack = (frame_expected + MAX_SEQ)%(MAX_SEQ + 1); dbg_frame("Send ACK %d\n", s.ack); put_frame((unsigned char *)&s, 3); stop_ack_timer(); }
static void send_frame(frame_kind fk, seq_nr frame_nr, seq_nr frame_expected, packet buffer[]) { /* Construct and send a data, ack, or nak frame. */ frame s; /* scratch variable */ s.kind = fk; /* kind == data, ack, or nak */ if (fk == data) s.info = buffer[frame_nr % NR_BUFS]; s.seq = frame_nr; /* only meaningful for data frames */ s.ack = (frame_expected + MAX_SEQ) % (MAX_SEQ + 1); if (fk == nak) no_nak = false; /* one nak per frame, please */ to_physical_layer(&s); /* transmit the frame */ if (fk == data) start_timer(frame_nr % NR_BUFS); stop_ack_timer(); /* no need for separate ack frame */ }
static void send_data_frame(void) { struct FRAME s; s.kind = FRAME_DATA; s.seq = next_frame_to_send; s.ack = (frame_expected + MAX_SEQ) % (MAX_SEQ + 1); memcpy(s.data, buffer[next_frame_to_send], PKT_LEN); dbg_frame("Send DATA %d %d, ID %d\n", s.seq, s.ack, *(short *)s.data); put_frame((unsigned char *)&s, 3 + PKT_LEN); // the extra 3 bytes are ack,kind,seq start_timer(next_frame_to_send, DATA_TIMER); stop_ack_timer(); }