int write_serial_packet(serial_source src, const void *packet, int len) /* Effects: writes len byte packet to serial source src Returns: 0 if packet successfully written, 1 if successfully written but not acknowledged, -1 otherwise */ { struct timeval deadline; src->send.seqno++; if (write_framed_packet(src, P_PACKET_ACK, src->send.seqno, packet, len) < 0) return -1; gettimeofday(&deadline, NULL); add_timeval(&deadline, ACK_TIMEOUT); for (;;) { struct packet_list *entry; read_and_process(src); entry = pop_protocol_packet(src, P_ACK); if (entry) { uint8_t acked = entry->packet[0]; free(entry->packet); free(entry); if (acked == src->send.seqno) return 0; } else if (source_wait(src, &deadline) < 0) return 1; } }
static void process_packet(serial_source src, uint8_t *packet, int len) { int packet_type = packet[0], offset = 1; if (packet_type == P_PACKET_ACK) { /* send ack */ write_framed_packet(src, P_ACK, packet[1], NULL, 0); /* And merge with un-acked packets */ packet_type = P_PACKET_NO_ACK; offset = 2; } /* packet must remain a valid pointer to pass to free. So we move the data rather than pass an internal pointer */ memmove(packet, packet + offset, len - offset); push_protocol_packet(src, packet_type, packet, len - offset); }