package cluster import ( "context" "fmt" "net" "net/http" "net/url" "time" "github.com/go-faster/errors" "go.mau.fi/mautrix-telegram/pkg/gotd/tdsync" "go.mau.fi/mautrix-telegram/pkg/gotd/tg" "go.mau.fi/mautrix-telegram/pkg/gotd/transport" ) // Up runs all servers in a cluster. func (c *Cluster) Up(ctx context.Context) error { g := tdsync.NewCancellableGroup(ctx) listen := func(ctx context.Context, _ int) (net.Listener, error) { return newLocalListener(ctx) } if c.web { // Create local random listener l, err := newLocalListener(ctx) if err != nil { return err } mux := http.NewServeMux() srv := http.Server{ ReadHeaderTimeout: time.Second * 10, Handler: mux, BaseContext: func(net.Listener) context.Context { return ctx }, } g.Go(func(ctx context.Context) error { if err := srv.Serve(l); err != nil && !errors.Is(err, http.ErrServerClosed) { return errors.Wrap(err, "serve") } return nil }) g.Go(func(ctx context.Context) error { <-ctx.Done() return srv.Close() }) baseURL := url.URL{ Scheme: "http", Host: l.Addr().String(), } listen = func(ctx context.Context, dc int) (net.Listener, error) { listener, handler := transport.WebsocketListener(l.Addr()) path := fmt.Sprintf("/dc/%d", dc) mux.Handle(path, handler) dcURL := baseURL dcURL.Path = path c.domains[dc] = dcURL.String() return listener, nil } } for dcID, s := range c.setups { l, err := listen(ctx, dcID) if err != nil { return errors.Wrapf(err, "DC %d: listen port", dcID) } if !c.web { // Add TCP listeners to config. if addr, ok := l.Addr().(*net.TCPAddr); ok { c.cfg.DCOptions = append(c.cfg.DCOptions, tg.DCOption{ Ipv6: addr.IP.To16() != nil, Static: true, ID: dcID, IPAddress: addr.IP.String(), Port: addr.Port, }) } } // Copy iteration value. srv := s.srv g.Go(func(ctx context.Context) error { return srv.Serve(ctx, transport.ListenCodec(nil, l)) }) } c.ready.Signal() return g.Wait() }