@@ -100,6 +100,7 @@ export class TcpState {
100100 // Buffer of data received
101101 private readBuffer = new BytesBuffer ( MAX_BUFFER_SIZE ) ;
102102 private readChannel = new AsyncQueue < number > ( ) ;
103+ private readClosedSeqnum = - 1 ;
103104 private readClosed = false ;
104105
105106 // Buffer of data to be sent
@@ -443,6 +444,7 @@ export class TcpState {
443444 }
444445
445446 if ( flags . fin ) {
447+ this . readClosedSeqnum = this . recvNext ;
446448 this . recvNext = ( this . recvNext + 1 ) % u32_MODULUS ;
447449 this . readClosed = true ;
448450 this . readChannel . push ( 0 ) ;
@@ -646,27 +648,37 @@ export class TcpState {
646648 }
647649
648650 private async mainLoop ( ) {
651+ let lastAcked = this . sendUnacknowledged ;
652+
649653 let recheckPromise = this . cmdQueue . pop ( ) ;
650654 let receivedSegmentPromise = this . tcpQueue . pop ( ) ;
651655 let retransmitPromise = this . retransmissionQueue . pop ( ) ;
652656
653- while ( ! this . readClosed || ! this . writeClosed ) {
657+ while (
658+ ! this . readClosed ||
659+ ! this . writeClosed ||
660+ // This ensures we send the last ACK
661+ lastAcked !== this . readClosedSeqnum + 1
662+ ) {
654663 const result = await Promise . race ( [
655664 recheckPromise ,
656665 receivedSegmentPromise ,
657666 retransmitPromise ,
658667 ] ) ;
659668
660669 if ( result === Command . SEND_ACK ) {
670+ console . debug ( "[" + this . srcHost . id + "] [TCP] Processing SEND_ACK" ) ;
661671 recheckPromise = this . cmdQueue . pop ( ) ;
662672 this . notifiedSendPackets = false ;
663673 } else if ( result === Command . ABORT ) {
674+ console . debug ( "[" + this . srcHost . id + "] [TCP] Processing ABORT" ) ;
664675 // Send RST and quit
665676 const segment = this . newSegment ( this . sendNext , 0 ) ;
666677 segment . withFlags ( new Flags ( ) . withRst ( ) ) ;
667678 sendIpPacket ( this . srcHost , this . dstHost , segment ) ;
668679 break ;
669680 } else if ( "segment" in result ) {
681+ console . debug ( "[" + this . srcHost . id + "] [TCP] Processing segments" ) ;
670682 receivedSegmentPromise = this . tcpQueue . pop ( ) ;
671683 let segment = result . segment ;
672684
@@ -699,6 +711,7 @@ export class TcpState {
699711 }
700712 continue ;
701713 } else if ( "seqNum" in result ) {
714+ console . debug ( "[" + this . srcHost . id + "] [TCP] Processing timeout" ) ;
702715 retransmitPromise = this . retransmissionQueue . pop ( ) ;
703716 // Retransmit the segment
704717 this . resendPacket ( result . seqNum , result . size ) ;
@@ -709,6 +722,7 @@ export class TcpState {
709722 const segment = this . newSegment ( this . sendNext , this . recvNext ) . withFlags (
710723 new Flags ( ) . withAck ( ) ,
711724 ) ;
725+ lastAcked = this . recvNext ;
712726
713727 const sendSize = Math . min ( this . sendWindowSize ( ) , MAX_SEGMENT_SIZE ) ;
714728 if ( sendSize > 0 ) {
@@ -728,6 +742,7 @@ export class TcpState {
728742 this . sendNext = ( this . sendNext + 1 ) % u32_MODULUS ;
729743 segment . flags . withFin ( ) ;
730744 }
745+ console . debug ( "[" + this . srcHost . id + "] [TCP] sending segment" , segment ) ;
731746
732747 // Ignore failed sends
733748 if ( sendIpPacket ( this . srcHost , this . dstHost , segment ) ) {
0 commit comments