Ejemplo n.º 1
0
/* return TRUE if the packet should be retransmitted */
gboolean udp_processPacket(UDP* udp, Packet* packet) {
	MAGIC_ASSERT(udp);

	/* UDP packet contains data for user and can be buffered immediately */
	if(packet_getPayloadLength(packet) > 0) {
		return socket_addToInputBuffer((Socket*)udp, packet);
	}
	return FALSE;
}
Ejemplo n.º 2
0
void udp_processPacket(UDP* udp, Packet* packet) {
	MAGIC_ASSERT(udp);

	/* UDP packet contains data for user and can be buffered immediately */
	if(packet_getPayloadLength(packet) > 0) {
		if(!socket_addToInputBuffer((Socket*)udp, packet)) {
			packet_addDeliveryStatus(packet, PDS_RCV_SOCKET_DROPPED);
		}
	}
}
Ejemplo n.º 3
0
static void _tcp_flush(TCP* tcp) {
	MAGIC_ASSERT(tcp);

	/* make sure our information is up to date */
	_tcp_updateReceiveWindow(tcp);
	_tcp_updateSendWindow(tcp);

	/* flush packets that can now be sent to socket */
	while(g_queue_get_length(tcp->throttledOutput) > 0) {
		/* get the next throttled packet, in sequence order */
		Packet* packet = g_queue_pop_head(tcp->throttledOutput);

		/* break out if we have no packets left */
		if(!packet) {
			break;
		}

		guint length = packet_getPayloadLength(packet);

		if(length > 0) {
			PacketTCPHeader header;
			packet_getTCPHeader(packet, &header);

			/* we cant send it if our window is too small */
			gboolean fitsInWindow = (header.sequence < (tcp->send.unacked + tcp->send.window)) ? TRUE : FALSE;

			/* we cant send it if we dont have enough space */
			gboolean fitsInBuffer = (length <= socket_getOutputBufferSpace(&(tcp->super))) ? TRUE : FALSE;

			if(!fitsInBuffer || !fitsInWindow) {
				/* we cant send the packet yet */
				g_queue_push_head(tcp->throttledOutput, packet);
				break;
			} else {
				/* we will send: store length in virtual retransmission buffer
				 * so we can reduce buffer space consumed when we receive the ack */
				_tcp_addRetransmit(tcp, header.sequence, length);
			}
		}

		/* packet is sendable, we removed it from out buffer */
		tcp->throttledOutputLength -= length;

		/* update TCP header to our current advertised window and acknowledgement */
		packet_updateTCP(packet, tcp->receive.next, tcp->receive.window);

		/* keep track of the last things we sent them */
		tcp->send.lastAcknowledgement = tcp->receive.next;
		tcp->send.lastWindow = tcp->receive.window;

		 /* socket will queue it ASAP */
		gboolean success = socket_addToOutputBuffer(&(tcp->super), packet);

		/* we already checked for space, so this should always succeed */
		g_assert(success);
	}

	/* any packets now in order can be pushed to our user input buffer */
	while(g_queue_get_length(tcp->unorderedInput) > 0) {
		Packet* packet = g_queue_pop_head(tcp->unorderedInput);

		PacketTCPHeader header;
		packet_getTCPHeader(packet, &header);

		if(header.sequence == tcp->receive.next) {
			/* move from the unordered buffer to user input buffer */
			gboolean fitInBuffer = socket_addToInputBuffer(&(tcp->super), packet);

			if(fitInBuffer) {
				tcp->unorderedInputLength -= packet_getPayloadLength(packet);
				(tcp->receive.next)++;
				continue;
			}
		}

		/* we could not buffer it because its out of order or we have no space */
		g_queue_push_head(tcp->unorderedInput, packet);
		break;
	}

	/* check if user needs an EOF signal */
	gboolean wantsEOF = ((tcp->flags & TCPF_LOCAL_CLOSED) || (tcp->flags & TCPF_REMOTE_CLOSED)) ? TRUE : FALSE;
	if(wantsEOF) {
		/* if anyone closed, can't send anymore */
		tcp->error |= TCPE_SEND_EOF;

		if((tcp->receive.next >= tcp->receive.end) && !(tcp->flags & TCPF_EOF_SIGNALED)) {
			/* user needs to read a 0 so it knows we closed */
			tcp->error |= TCPE_RECEIVE_EOF;
			descriptor_adjustStatus((Descriptor*)tcp, DS_READABLE, TRUE);
		}
	}
}