diff --git a/Makefile b/Makefile index 6e26b4b..f2dbb15 100644 --- a/Makefile +++ b/Makefile @@ -28,5 +28,5 @@ debug: $(BINARY) $(KEY) ./$(BINARY) --pprof 6060 -i $(KEY) --bind ":$(PORT)" -vv test: - go test . - golint + go test ./... + golint ./... diff --git a/cmd.go b/cmd.go index 212e3f2..3fbef43 100644 --- a/cmd.go +++ b/cmd.go @@ -71,7 +71,7 @@ func main() { } privateKeyPath := options.Identity - if strings.HasPrefix(privateKeyPath, "~") { + if strings.HasPrefix(privateKeyPath, "~/") { user, err := user.Current() if err == nil { privateKeyPath = strings.Replace(privateKeyPath, "~", user.HomeDir, 1) @@ -101,7 +101,8 @@ func main() { } defer s.Close() - go Serve(s) + host := NewHost(s) + go host.Serve() /* TODO: for _, fingerprint := range options.Admin { diff --git a/host.go b/host.go new file mode 100644 index 0000000..885ef0d --- /dev/null +++ b/host.go @@ -0,0 +1,99 @@ +package main + +import ( + "fmt" + "io" + + "github.com/shazow/ssh-chat/chat" + "github.com/shazow/ssh-chat/sshd" +) + +// Host is the bridge between sshd and chat modules +// TODO: Should be easy to add support for multiple channels, if we want. +type Host struct { + listener *sshd.SSHListener + channel *chat.Channel +} + +// NewHost creates a Host on top of an existing listener +func NewHost(listener *sshd.SSHListener) *Host { + h := Host{ + listener: listener, + channel: chat.NewChannel(), + } + return &h +} + +// Connect a specific Terminal to this host and its channel +func (h *Host) Connect(term *sshd.Terminal) { + defer term.Close() + name := term.Conn.User() + term.SetPrompt(fmt.Sprintf("[%s] ", name)) + // TODO: term.AutoCompleteCallback = ... + + user := chat.NewUserScreen(name, term) + defer user.Close() + + err := h.channel.Join(user) + if err != nil { + logger.Errorf("Failed to join: %s", err) + return + } + + for { + // TODO: Handle commands etc? + line, err := term.ReadLine() + if err == io.EOF { + // Closed + break + } else if err != nil { + logger.Errorf("Terminal reading error: %s", err) + break + } + m := chat.NewMessage(line).From(user) + h.channel.Send(*m) + } + + err = h.channel.Leave(user) + if err != nil { + logger.Errorf("Failed to leave: %s", err) + return + } +} + +// Serve our chat channel onto the listener +func (h *Host) Serve() { + terminals := h.listener.ServeTerminal() + + for term := range terminals { + go h.Connect(term) + } +} + +/* TODO: ... +func (h *Host) AutoCompleteFunction(line string, pos int, key rune) (newLine string, newPos int, ok bool) { + if key != 9 { + return + } + + shortLine := strings.Split(line[:pos], " ") + partialNick := shortLine[len(shortLine)-1] + nicks := h.channel.users.ListPrefix(&partialNick) + if len(nicks) == 0 { + return + } + + nick := nicks[len(nicks)-1] + posPartialNick := pos - len(partialNick) + if len(shortLine) < 2 { + nick += ": " + } else { + nick += " " + } + newLine = strings.Replace(line[posPartialNick:], partialNick, nick, 1) + newLine = line[:posPartialNick] + newLine + newPos = pos + (len(nick) - len(partialNick)) + ok = true + return +} +*/ diff --git a/serve.go b/serve.go deleted file mode 100644 index 0e97ca8..0000000 --- a/serve.go +++ /dev/null @@ -1,53 +0,0 @@ -package main - -import ( - "fmt" - - "github.com/shazow/ssh-chat/chat" - "github.com/shazow/ssh-chat/sshd" -) - -func HandleTerminal(term *sshd.Terminal, channel *chat.Channel) { - defer term.Close() - name := term.Conn.User() - term.SetPrompt(fmt.Sprintf("[%s] ", name)) - // TODO: term.AutoCompleteCallback = ... - - user := chat.NewUserScreen(name, term) - defer user.Close() - - err := channel.Join(user) - if err != nil { - logger.Errorf("Failed to join: %s", err) - return - } - defer func() { - err := channel.Leave(user) - if err != nil { - logger.Errorf("Failed to leave: %s", err) - } - }() - - for { - // TODO: Handle commands etc? - line, err := term.ReadLine() - if err != nil { - // TODO: Catch EOF specifically? - logger.Errorf("Terminal reading error: %s", err) - return - } - m := chat.NewMessage(line).From(user) - channel.Send(*m) - } -} - -// Serve a chat service onto the sshd server. -func Serve(listener *sshd.SSHListener) { - terminals := listener.ServeTerminal() - channel := chat.NewChannel() - - for term := range terminals { - go HandleTerminal(term, channel) - } - -}