void rel_output (rel_t *r) { if (r->outputEOF) { return; } int buff = conn_bufspace(r->c); int dataOut = 0; while (outputCheck (r, dataOut, buff)) { int currentOut = ntohs(r->receiverBuff->packet->len) - 16 - r->recvBuffOffset; if (currentOut == 0 || currentOut < 0) { break; } if (buff > dataOut + currentOut) { char* start_of_data = r->receiverBuff->packet->data + r->recvBuffOffset; conn_output(r->c, start_of_data, currentOut); dequeue(&r->receiverBuff); dataOut += currentOut; } else{ currentOut = buff - dataOut; char* start_of_data = r->receiverBuff->packet->data + r->recvBuffOffset; conn_output(r->c, start_of_data, currentOut); r->recvBuffOffset += currentOut; dataOut += currentOut; } } }
void rel_output (rel_t *r) { // printf("rel_output\n"); int numPacketsInWindow = r->LAST_PACKET_SENT - r->LAST_PACKET_ACKED; int i; // fprintf(stderr, "lastpacksent: %d, lackPackacked: %d\n", r->LAST_PACKET_SENT, r->LAST_PACKET_ACKED); for (i = 0; i < r->windowSize; i++) { // fprintf(stderr, "Recvpacket of %d has ack %d\n", i, r->recvPackets[i]->acked); if(r->recvPackets[i]->acked == 0) { break; } packet_t *pkt = r->recvPackets[i]->packet; uint16_t packet_len = ntohs(pkt->len); size_t len = conn_bufspace(r->c); // fprintf(stderr, "Packet len: %d\n", (int) packet_len); if(len >= packet_len - HEADER_SIZE) { if(packet_len == HEADER_SIZE) { r->eofRecv = 1; } // fprintf(stderr, "Outputting packet %d from recvPackets \n", i); conn_output(r->c, pkt->data, packet_len - HEADER_SIZE); r->recvPackets[i]->acked = 0; } else { break; } } // fprintf(stderr, "value of i: %d\n", i); // fprintf(stderr, "Next Packet Expected Before: %d\n", r->NEXT_PACKET_EXPECTED ); r->NEXT_PACKET_EXPECTED += i; struct ack_packet *ack = createAckPacket(r, r->NEXT_PACKET_EXPECTED); // fprintf(stderr, "Next Packet Expected: %d\n", r->NEXT_PACKET_EXPECTED); conn_sendpkt(r->c, (packet_t *)ack, ACK_PACKET_SIZE); free(ack); // fprintf(stderr, "reloutput -- numPackets: %d, eofRecv: %d, eofSend: %d\n", numPacketsInWindow, r->eofRecv, r->eofSent); if(numPacketsInWindow == 0 && r->eofRecv == 1 && r->eofSent == 1) { rel_destroy(r); return; } shiftRecvPacketList(r); }
void rel_output (rel_t *r) { size_t left = conn_bufspace(r->c); int index = (r->LSR + 1) % r->window_size; packet_t * cur = &r->recvWindow[index]; int data_len = ntohs(cur->len) - 12; while ((uint16_t)left >= data_len) { conn_output (r->c, cur->data, data_len); r->recvState[index] = 2; r->LSR ++ ; r->LAS = r->LSR + r->RWS; index = (r->LSR + 1) % r->window_size; if (r->recvState[index] == 1) { cur = &r->recvWindow[index]; } else { break; } data_len = ntohs(cur->len) - 12; left = conn_bufspace(r->c); } send_ack(r); }
void rel_output(rel_t *r) { int i; int shift = r->receiver.buffer_position; for (i = shift; i < r->windowSize + shift; i++) { if (r->receiverWindowBuffer[i].isFull == 0) { return; } if (r->receiverWindowBuffer[i].isFull == 1) { if (r->receiverWindowBuffer[i].outputted == 0) { int availableSpace = conn_bufspace(r->c); struct WindowBuffer *packet = malloc(sizeof(struct WindowBuffer)); packet = &r->receiverWindowBuffer[i]; if (availableSpace >= packet->ptr->len) { conn_output(r->c, packet->ptr->data, packet->ptr->len); r->receiver.buffer_position++; r->receiverWindowBuffer[i].outputted = 1; } } } } }
/** * Writes a buffer to STDOUT or the program associated with this connection. * If called with a length of 0, an EOF is recorded. * * conn: The associated connection object. * buf: The buffer to output. * len: Number of bytes to write out. * returns: -1 if error, otherwise the number of bytes written out. */ int conn_output(conn_t *conn, const char *buf, size_t len) { ASSERT_CONN; /* If already wrote EOF, can't write more. */ if (conn->wrote_eof) return 0; /* Writing EOF. */ if (len == 0) { conn->wrote_eof = true; return 0; } /* If already wrote out an error, can't continue writing. */ if (conn->wrote_err) { fprintf(stderr, "[ERROR] Attempting to write after error\n"); return -1; } int left = len; int w = 0; /* See if there is actually room to output. */ if (!conn_bufspace(conn)) return 0; /* Nothing in the output queue. Output immediately to the appropriate interface. */ if (!conn->out_queue) { if (run_program) w = write(conn->stdin, buf, len); else w = write(STDOUT_FILENO, buf, len); if (w < 0) { if (errno != EAGAIN) { if (run_program) fprintf(stderr, "[INFO] Program exited\n"); conn->wrote_err = true; return -1; } } /* Write as much as possible. Keep track of how much was written. */ else { buf += w; left -= w; } } /* Put the rest in an output queue. */ if (left > 0) { chunk_t *chunk = calloc(offsetof(chunk_t, buf[left]), 1); chunk->next = NULL; chunk->size = left; chunk->used = 0; memcpy(chunk->buf, buf, left); /* Update pointers. */ *conn->out_queue_tail = chunk; conn->out_queue_tail = &chunk->next; } /* If there is stuff in the queue, create an event. */ if (conn->out_queue) { if (run_program) events[conn->stdin].events |= POLLOUT; else events[STDOUT_FILENO].events |= POLLOUT; } return len; }
int rel_output (rel_t *r) { assert(r); int sent_ack = 0; /* If we've already printed an EOF, then we're done. */ if (r->printed_eof) return 0; while (1) { /* Read from the head of the received packets buffer queue, * if we have any received packets waiting */ int rec_seqno = bq_get_head_seq(r->rec_bq); if (!bq_element_buffered(r->rec_bq, rec_seqno)) break; packet_t *pkt = bq_get_element(r->rec_bq, rec_seqno); int bufspace = conn_bufspace(r->c); /* Print the whole packet, then ack */ if (bufspace > pkt->len-12) { conn_output(r->c, pkt->data, pkt->len-12); bq_increase_head_seq_to(r->rec_bq, rec_seqno + 1); sent_ack = pkt->seqno + 1; /* If we just printed out an EOF, update our status */ if (pkt->len == 12) { r->printed_eof = 1; /* If we just printed an EOF, we should be done. */ break; } } /* Edge case: only enough buffer to print part of the packet */ else if (bufspace > 0) { conn_output(r->c, pkt->data, bufspace); /* Shift the packet data over, removing what we've already printed */ memcpy(&(pkt->data[0]), &(pkt->data[bufspace]), pkt->len - bufspace); pkt->len -= bufspace; break; } /* If we have no buffer space left, time to quit */ else if (bufspace == 0) break; } if (sent_ack != 0) rel_send_ack(r, sent_ack); /* We could have just printed an eof, so just in case, * we should try destroying the rel_t. If we do, we return * 1 to prevent our caller from producing a redundant ack. */ if (rel_check_finished(r)) return 1; return sent_ack; }