func()

in internal/command/command_monitor.go [169:239]


func (c *Server) start(ctx context.Context) error {
	if c.srv != nil {
		return errors.New("server already listening")
	}
	galog.Debugf("Starting command server at %q", c.pipe)
	srv, err := listen(ctx, c.pipe, c.pipeMode, c.pipeGroup)
	if err != nil {
		return err
	}
	go func() {
		defer srv.Close()
		for {
			if ctx.Err() != nil {
				return
			}
			conn, err := srv.Accept()
			if err != nil {
				if errors.Is(err, net.ErrClosed) {
					break
				}
				galog.Errorf("error on connection to pipe %s: %v", c.pipe, err)
				continue
			}
			go func(conn net.Conn) {
				defer conn.Close()
				// Go has lots of helpers to read json from an io.Reader but none of
				// them return the byte slice afterwards and we need it for the handler.
				deadline := time.Now().Add(c.timeout)
				if err := conn.SetDeadline(deadline); err != nil {
					galog.Errorf("could not set deadline on command request: %v", err)
					return
				}
				message, ok := readOrError(conn)
				if !ok {
					return
				}
				var req Request
				for err := json.Unmarshal(message, &req); err != nil; err = json.Unmarshal(message, &req) {
					b, ok := readOrError(conn)
					if !ok {
						return
					}
					message = append(message, b...)
				}
				c.monitor.handlersMu.RLock()
				defer c.monitor.handlersMu.RUnlock()
				handler, ok := c.monitor.handlers[req.Command]
				if !ok {
					if b, err := json.Marshal(CmdNotFoundError); err != nil {
						conn.Write(internalError)
					} else {
						conn.Write(b)
					}
					return
				}
				resp, err := handler(ctx, message)
				if err != nil {
					re := Response{Status: HandlerError.Status, StatusMessage: err.Error()}
					if b, err := json.Marshal(re); err != nil {
						resp = internalError
					} else {
						resp = b
					}
				}
				conn.Write(resp)
			}(conn)
		}
	}()
	c.srv = srv
	return nil
}