/* 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; }
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); } } }
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); } } }