code: func (tab *Table) addSeenNode(n *node) {
  	if n.ID() == tab.self().ID() {
  		return
  	}
  
  	tab.mutex.Lock()
  	defer tab.mutex.Unlock()
  	b := tab.bucket(n.ID())
  	if contains(b.entries, n.ID()) {
  		// Already in bucket, don't add.
  		return
  	}
  	if len(b.entries) >= bucketSize {
  		// Bucket full, maybe add as replacement.
  		tab.addReplacement(b, n)
  		return
  	}
  	if !tab.addIP(b, n.IP()) {
  		// Can't add: IP limit reached.
  		return
  	}
  	// Add to end of bucket:
  	b.entries = append(b.entries, n)
  	b.replacements = deleteNode(b.replacements, n)
  	n.addedAt = time.Now()
  	if tab.nodeAddedHook != nil {
  		tab.nodeAddedHook(n)
  	}
  }
docs: // addSeenNode adds a node which may or may not be live to the end of a bucket. If the
  // bucket has space available, adding the node succeeds immediately. Otherwise, the node is
  // added to the replacements list.
  //
  // The caller must not hold tab.mutex.