code: func (e *endpoint) Close() {
  	// Issue a shutdown so that the peer knows we won't send any more data
  	// if we're connected, or stop accepting if we're listening.
  	e.Shutdown(tcpip.ShutdownWrite | tcpip.ShutdownRead)
  
  	e.mu.Lock()
  
  	// For listening sockets, we always release ports inline so that they
  	// are immediately available for reuse after Close() is called. If also
  	// registered, we unregister as well otherwise the next user would fail
  	// in Listen() when trying to register.
  	if e.state == stateListen && e.isPortReserved {
  		if e.isRegistered {
  			e.stack.UnregisterTransportEndpoint(e.boundNICID, e.effectiveNetProtos, ProtocolNumber, e.id, e)
  			e.isRegistered = false
  		}
  
  		e.stack.ReleasePort(e.effectiveNetProtos, ProtocolNumber, e.id.LocalAddress, e.id.LocalPort)
  		e.isPortReserved = false
  	}
  
  	// Either perform the local cleanup or kick the worker to make sure it
  	// knows it needs to cleanup.
  	tcpip.AddDanglingEndpoint(e)
  	if !e.workerRunning {
  		e.cleanupLocked()
  	} else {
  		e.workerCleanup = true
  		e.notifyProtocolGoroutine(notifyClose)
  	}
  
  	e.mu.Unlock()
  }
docs: // Close puts the endpoint in a closed state and frees all resources associated
  // with it. It must be called only once and with no other concurrent calls to
  // the endpoint.