Exemplo n.º 1
0
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;
		}
	}
}
Exemplo n.º 2
0
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);
}
Exemplo n.º 3
0
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);
}
Exemplo n.º 4
0
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;
				}
			}
		}
	}
}
Exemplo n.º 5
0
/**
 * 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;
}
Exemplo n.º 6
0
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;
}