Program: 5621
Project: 5621
Buggy source:
synchronized void receive(TCPPacket tcpPacket){
  int plen=tcpPacket.payload == null ? 0 : tcpPacket.payload.length;
  if (tcpPacket.isAck()) {
    if (sentUnack <= tcpPacket.ackNo && sendNext >= tcpPacket.ackNo) {
      int noAcked=tcpPacket.ackNo - sentUnack;
      sentUnack=tcpPacket.ackNo;
      bufPos+=noAcked;
      if (bufPos >= outgoingBuffer.length)       bufPos-=outgoingBuffer.length;
      System.out.println("String_Node_Str" + noAcked + "String_Node_Str"+ bufPos+ "String_Node_Str"+ bufNextEmpty+ "String_Node_Str"+ Integer.toString(sentUnack & 0xffff,16)+ "String_Node_Str"+ Integer.toString(sendNext & 0xffff,16)+ "String_Node_Str"+ outSize()+ "String_Node_Str"+ (sendNext - sentUnack)+ "String_Node_Str"+ plen);
      notify();
      if (closing && sentUnack == sendNext) {
        sendFIN();
      }
    }
 else {
      System.out.println("String_Node_Str" + Integer.toString(tcpPacket.ackNo & 0xffff,16) + "String_Node_Str"+ Integer.toString(sendNext & 0xffff,16)+ "String_Node_Str"+ Integer.toString(sentUnack & 0xffff,16));
      if (tcpPacket.ackNo == sentUnack) {
        resend();
      }
    }
  }
  if (receiveNext == tcpPacket.seqNo) {
    receiveNext=tcpPacket.seqNo + plen;
    if (plen > 0) {
      sendAck(tcpPacket);
      if (tcpListener != null) {
        tcpListener.tcpDataReceived(this,tcpPacket);
      }
 else {
        System.out.println("String_Node_Str");
      }
    }
  }
 else {
    System.out.println("String_Node_Str" + Integer.toString(receiveNext & 0xffff,16) + "String_Node_Str"+ Integer.toString(tcpPacket.seqNo & 0xffff,16));
    sendAck(tcpPacket);
  }
  if (tcpPacket.isFin()) {
    if (plen == 0) {
      sendAck(tcpPacket);
    }
    if (tcpListener != null && plen > 0) {
      tcpListener.connectionClosed(this);
    }
  }
}

Fixed version (ground truth):
synchronized void receive(TCPPacket tcpPacket){
  int plen=tcpPacket.payload == null ? 0 : tcpPacket.payload.length;
  if (tcpPacket.isAck()) {
    if (sentUnack <= tcpPacket.ackNo && sendNext >= tcpPacket.ackNo) {
      int noAcked=tcpPacket.ackNo - sentUnack;
      sentUnack=tcpPacket.ackNo;
      bufPos+=noAcked;
      if (bufPos >= outgoingBuffer.length)       bufPos-=outgoingBuffer.length;
      System.out.println("String_Node_Str" + noAcked + "String_Node_Str"+ bufPos+ "String_Node_Str"+ bufNextEmpty+ "String_Node_Str"+ Integer.toString(sentUnack & 0xffff,16)+ "String_Node_Str"+ Integer.toString(sendNext & 0xffff,16)+ "String_Node_Str"+ outSize()+ "String_Node_Str"+ (sendNext - sentUnack)+ "String_Node_Str"+ plen);
      notify();
      if (state == ESTABLISHED && closing && outSize() == 0) {
        state=FIN_WAIT_1;
        sendFIN();
      }
    }
 else {
      System.out.println("String_Node_Str" + Integer.toString(tcpPacket.ackNo & 0xffff,16) + "String_Node_Str"+ Integer.toString(sendNext & 0xffff,16)+ "String_Node_Str"+ Integer.toString(sentUnack & 0xffff,16));
      if (tcpPacket.ackNo == sentUnack) {
        resend();
      }
    }
  }
  if (receiveNext == tcpPacket.seqNo) {
    receiveNext=tcpPacket.seqNo + plen;
    if (tcpPacket.isFin()) {
      receiveNext++;
      if (plen == 0)       sendAck(tcpPacket);
    }
    if (plen > 0) {
      sendAck(tcpPacket);
      if (tcpListener != null) {
        tcpListener.tcpDataReceived(this,tcpPacket);
      }
 else {
        System.out.println("String_Node_Str");
      }
    }
  }
 else {
    System.out.println("String_Node_Str" + Integer.toString(receiveNext & 0xffff,16) + "String_Node_Str"+ Integer.toString(tcpPacket.seqNo & 0xffff,16));
    sendAck(tcpPacket);
  }
}