// New creates a new server with the given config. The server will call `cfg.SSHConfig()` to setup // the server. If an error occurs it will be returned. If the Bind address is empty or invalid // an error will be returned. If there is an error starting the TCP server, the error will be returned. func New(cfg *Config) (server SSHServer, err error) { if cfg.Context == nil { return SSHServer{}, errors.New("Config has no context") } // Create ssh config for server sshConfig := cfg.SSHConfig() cfg.sshConfig = sshConfig // Validate the ssh bind addr if cfg.Bind == "" { err = fmt.Errorf("ssh server: Empty SSH bind address") return } // Open SSH socket listener sshAddr, e := net.ResolveTCPAddr("tcp", cfg.Bind) if e != nil { err = fmt.Errorf("ssh server: Invalid tcp address") return } // Create listener listener, e := net.ListenTCP("tcp", sshAddr) if e != nil { err = e return } server.listener = listener server.Addr = listener.Addr().(*net.TCPAddr) server.config = cfg server.reaper = grim.ReaperWithContext(cfg.Context) return }
func (t *tcpHandler) Execute(c context.Context) { select { case <-c.Done(): t.conn.Close() return default: } // Create reaper g := grim.ReaperWithContext(c) defer g.Wait() // Convert to SSH connection sshConn, channels, requests, err := ssh.NewServerConn(t.conn, t.config) if err != nil { t.logger.Warn("SSH handshake failed:", "addr", t.conn.RemoteAddr().String(), "error", err) t.conn.Close() g.Kill() return } // Close connection on exit t.logger.Debug("Handshake successful") defer sshConn.Close() defer sshConn.Wait() // Discard all out-of-channel requests if t.requestHandler != nil { go t.requestHandler.Consume(requests) } else { go ssh.DiscardRequests(requests) } OUTER: for { select { case <-c.Done(): break OUTER case <-g.Dead(): break OUTER case ch := <-channels: // Check if chan was closed if ch == nil { break OUTER } // Handle the channel g.SpawnFunc(func(ctx context.Context) { t.dispatcher.Dispatch(ctx, sshConn, ch) return }) } } g.Kill() }
// New creates an implementation of the Yamuxer interface using the given // context and config. func New(context context.Context, c *Config) Yamuxer { return &yamuxer{ grim: grim.ReaperWithContext(context), listener: c.Listener, dispatcher: c.Dispatcher, deadline: c.Deadline, tlsConfig: c.TLSConfig, logger: log.NewLogger(c.LogOutput, "yamuxer"), logOutput: c.LogOutput, } }
func (f *ForwardingHandler) Handle(c context.Context, conn net.Conn) { f.logger.Info("Accepted raft connection", "addr", conn.RemoteAddr().String()) g := grim.ReaperWithContext(c) defer g.Wait() messages := make(chan namedtuple.Tuple, 1) g.SpawnFunc(func(ctx context.Context) { defer conn.Close() for { select { case <-ctx.Done(): case msg, ok := <-messages: if !ok { return } if err := f.applier.Apply(msg); err != nil { f.logger.Warn("error applying message") } } } }) g.SpawnFunc(func(ctx context.Context) { defer close(messages) decoder := namedtuple.NewDecoder(namedtuple.DefaultRegistry, conn) for { tuple, err := decoder.Decode() if err != nil { return } if tuple.Is(nodeStatus) { messages <- tuple } } }) return }
func New(c *Config) (cer Cerebrum, err error) { // Create logger if c.LogOutput == nil { c.LogOutput = log.NewConcurrentWriter(os.Stderr) } logger := log.NewLogger(c.LogOutput, "kappa") // Create data directory if err = os.MkdirAll(c.DataPath, 0755); err != nil { logger.Warn("Could not create data directory", "err", err) return } // Setup reconciler serfEventCh := make(chan serf.Event, 256) reconcilerCh := make(chan serf.Member, 32) ctx, cancel := context.WithCancel(context.Background()) cereb := &cerebrum{ config: c, logger: logger, dialer: NewDialer(NewPool(c.LogOutput, 5*time.Minute, c.TLSConfig)), serfEventCh: serfEventCh, reconcileCh: reconcilerCh, grim: grim.ReaperWithContext(ctx), context: ctx, cancel: cancel, } // Create serf server err = cereb.setupRaft() if err != nil { err = logger.Error("Failed to start serf: %v", err) return nil, err } isLeader := func() bool { return cereb.raft.State() == raft.Leader } reconciler := &Reconciler{reconcilerCh, isLeader} cereb.serfer = serfer.NewSerfer(serfEventCh, serfer.SerfEventHandler{ Logger: log.NewLogger(c.LogOutput, CerebrumEventPrefix), ServicePrefix: CerebrumEventPrefix, ReconcileOnJoin: true, ReconcileOnLeave: true, ReconcileOnFail: true, ReconcileOnUpdate: true, ReconcileOnReap: true, NodeJoined: c.NodeJoined, NodeUpdated: c.NodeUpdated, NodeLeft: c.NodeLeft, NodeFailed: c.NodeFailed, NodeReaped: c.NodeReaped, UserEvent: c.UserEvent, UnknownEventHandler: c.UnknownEventHandler, Reconciler: reconciler, IsLeader: isLeader, IsLeaderEvent: func(name string) bool { return name == CerebrumLeaderEvent }, LeaderElectionHandler: cereb, }) // Create serf server cereb.serf, err = cereb.setupSerf() if err != nil { err = logger.Error("Failed to start serf: %v", err) return nil, err } cer = cereb return cer, nil }