nsqlookup/handler.go
func (h TCPHandler) ServeConn(ctx context.Context, conn net.Conn) {
	const bufSize = 2048

	var r = bufio.NewReaderSize(conn, bufSize)
	var w = bufio.NewWriterSize(conn, bufSize)

	if h.ReadTimeout == 0 {
		h.ReadTimeout = DefaultReadTimeout
	}

	if h.WriteTimeout == 0 {
		h.WriteTimeout = DefaultWriteTimeout
	}

	if h.EngineTimeout == 0 {
		h.EngineTimeout = DefaultEngineTimeout
	}

	if ctx == nil {
		ctx = context.Background()
	}

	host, port, _ := net.SplitHostPort(conn.LocalAddr().String())

	if h.Info.TcpPort == 0 {
		h.Info.TcpPort, _ = strconv.Atoi(port)
	}

	if len(h.Info.BroadcastAddress) == 0 {
		h.Info.BroadcastAddress = host
	}

	if len(h.Info.Hostname) == 0 {
		h.Info.Hostname, _ = os.Hostname()
	}

	if len(h.Info.Version) == 0 {
		info, _ := h.Engine.LookupInfo(ctx)
		h.Info.Version = info.Version
	}

	var node Node
	var cmdChan = make(chan Command)
	var resChan = make(chan Response)
	var errChan = make(chan error, 2)
	var doneChan = ctx.Done()

	defer func() {
		if node != nil {
			err := node.Unregister(ctx)
			log.Printf("UNREGISTER node = %s, err = %s", node, err)
		}
	}()
	defer close(resChan)

	go h.readLoop(ctx, conn, r, cmdChan, errChan)
	go h.writeLoop(ctx, conn, w, resChan, errChan)

	for {
		var cmd Command
		var res Response
		var err error

		select {
		case <-doneChan:
			return
		case <-errChan:
			return
		case cmd = <-cmdChan:
		}

		switch c := cmd.(type) {
		case Ping:
			res, err = h.ping(ctx, node)

		case Identify:
			node, res, err = h.identify(ctx, node, c.Info, conn)

		case Register:
			res, err = h.register(ctx, node, c.Topic, c.Channel)

		case Unregister:
			node, res, err = h.unregister(ctx, node, c.Topic, c.Channel)

		default:
			res = makeErrInvalid("unknown command")
		}

		if err != nil {
			switch e := err.(type) {
			case Error:
				res = e
			default:
				log.Print(err)
				return
			}
		}

		select {
		case <-doneChan:
			return
		case <-errChan:
			return
		case resChan <- res:
		}
	}
}
func (h TCPHandler) ServeConn(ctx context.Context, conn net.Conn) {
	const bufSize = 2048

	var r = bufio.NewReaderSize(conn, bufSize)
	var w = bufio.NewWriterSize(conn, bufSize)

	if h.ReadTimeout == 0 {
		h.ReadTimeout = DefaultReadTimeout
	}

	if h.WriteTimeout == 0 {
		h.WriteTimeout = DefaultWriteTimeout
	}

	if h.EngineTimeout == 0 {
		h.EngineTimeout = DefaultEngineTimeout
	}

	if ctx == nil {
		ctx = context.Background()
	}

	host, port, _ := net.SplitHostPort(conn.LocalAddr().String())

	if h.Info.TcpPort == 0 {
		h.Info.TcpPort, _ = strconv.Atoi(port)
	}

	if len(h.Info.BroadcastAddress) == 0 {
		h.Info.BroadcastAddress = host
	}

	if len(h.Info.Hostname) == 0 {
		h.Info.Hostname, _ = os.Hostname()
	}

	if len(h.Info.Version) == 0 {
		info, _ := h.Engine.LookupInfo(ctx)
		h.Info.Version = info.Version
	}

	var node Node
	var cmdChan = make(chan Command)
	var resChan = make(chan Response)
	var errChan = make(chan error, 2)
	var doneChan = ctx.Done()

	defer func() {
		if node != nil {
			err := node.Unregister(ctx)
			log.Printf("UNREGISTER node = %s, err = %s", node, err)
		}
	}()
	defer close(resChan)

	go h.readLoop(ctx, conn, r, cmdChan, errChan)
	go h.writeLoop(ctx, conn, w, resChan, errChan)

	for {
		var cmd Command
		var res Response
		var err error

		select {
		case <-doneChan:
			return
		case <-errChan:
			return
		case cmd = <-cmdChan:
		}

		switch c := cmd.(type) {
		case Ping:
			res, err = h.ping(ctx, node)

		case Identify:
			node, res, err = h.identify(ctx, node, c.Info, conn)

		case Register:
			res, err = h.register(ctx, node, c.Topic, c.Channel)

		case Unregister:
			node, res, err = h.unregister(ctx, node, c.Topic, c.Channel)

		default:
			res = makeErrInvalid("unknown command")
		}

		if err != nil {
			switch e := err.(type) {
			case Error:
				res = e
			default:
				log.Print(err)
				return
			}
		}

		select {
		case <-doneChan:
			return
		case <-errChan:
			return
		case resChan <- res:
		}
	}
}
// ServeConn takes ownership of the conn object and starts service the commands
// that the client sends to the discovery handler.