code: func (sm *Manager) handleConn(ctx context.Context, conn net.Conn, opts map[string][]string) error {
  	ctx, cancel := context.WithCancel(ctx)
  	defer cancel()
  
  	opts = canonicalHeaders(opts)
  
  	h := http.Header(opts)
  	id := h.Get(headerSessionID)
  	name := h.Get(headerSessionName)
  	sharedKey := h.Get(headerSessionSharedKey)
  
  	ctx, cc, err := grpcClientConn(ctx, conn)
  	if err != nil {
  		sm.mu.Unlock()
  		return err
  	}
  
  	c := &client{
  		Session: Session{
  			id:        id,
  			name:      name,
  			sharedKey: sharedKey,
  			ctx:       ctx,
  			cancelCtx: cancel,
  			done:      make(chan struct{}),
  		},
  		cc:        cc,
  		supported: make(map[string]struct{}),
  	}
  
  	for _, m := range opts[headerSessionMethod] {
  		c.supported[strings.ToLower(m)] = struct{}{}
  	}
  	sm.sessions[id] = c
  	sm.updateCondition.Broadcast()
  	sm.mu.Unlock()
  
  	defer func() {
  		sm.mu.Lock()
  		delete(sm.sessions, id)
  		sm.mu.Unlock()
  	}()
  
  	<-c.ctx.Done()
  	conn.Close()
  	close(c.done)
  
  	return nil
  }
docs: // caller needs to take lock, this function will release it