diff --git a/chat/channel.go b/chat/channel.go index 180dada..b52fb47 100644 --- a/chat/channel.go +++ b/chat/channel.go @@ -7,7 +7,6 @@ const channelBuffer = 10 // Channel definition, also a Set of User Items type Channel struct { - id string topic string history *History users *Set @@ -15,11 +14,10 @@ type Channel struct { } // Create new channel and start broadcasting goroutine. -func NewChannel(id string) *Channel { +func NewChannel() *Channel { broadcast := make(chan Message, channelBuffer) ch := Channel{ - id: id, broadcast: broadcast, history: NewHistory(historyLen), users: NewSet(), @@ -27,8 +25,14 @@ func NewChannel(id string) *Channel { go func() { for m := range broadcast { + // TODO: Handle commands etc? ch.users.Each(func(u Item) { - u.(*User).Send(m) + user := u.(*User) + if m.from == user { + // Skip + return + } + user.Send(m) }) } }() diff --git a/chat/channel_test.go b/chat/channel_test.go index f261081..3e16030 100644 --- a/chat/channel_test.go +++ b/chat/channel_test.go @@ -11,7 +11,7 @@ func TestChannel(t *testing.T) { s := &MockScreen{} u := NewUser("foo") - ch := NewChannel("") + ch := NewChannel() defer ch.Close() err := ch.Join(u) diff --git a/chat/command.go b/chat/command.go index 73ffa2f..896e524 100644 --- a/chat/command.go +++ b/chat/command.go @@ -8,7 +8,7 @@ import ( var ErrInvalidCommand error = errors.New("invalid command") var ErrNoOwner error = errors.New("command without owner") -type CmdHandler func(host Host, msg Message, args []string) error +type CmdHandler func(msg Message, args []string) error type Commands map[string]CmdHandler @@ -18,7 +18,7 @@ func (c Commands) Add(cmd string, handler CmdHandler) { } // Execute command message, assumes IsCommand was checked -func (c Commands) Run(host Host, msg Message) error { +func (c Commands) Run(msg Message) error { if msg.from == nil { return ErrNoOwner } @@ -29,7 +29,7 @@ func (c Commands) Run(host Host, msg Message) error { return ErrInvalidCommand } - return handler(host, msg, args) + return handler(msg, args) } var defaultCmdHandlers Commands @@ -37,7 +37,7 @@ var defaultCmdHandlers Commands func init() { c := Commands{} - c.Add("me", func(host Host, msg Message, args []string) error { + c.Add("me", func(msg Message, args []string) error { me := strings.TrimLeft(msg.Body, "/me") if me == "" { me = " is at a loss for words." diff --git a/chat/host.go b/chat/host.go deleted file mode 100644 index 9834ed4..0000000 --- a/chat/host.go +++ /dev/null @@ -1,28 +0,0 @@ -package chat - -// Host knows about all the commands and channels. -type Host struct { - defaultChannel *Channel - commands Commands - done chan struct{} -} - -func NewHost() *Host { - h := Host{ - commands: defaultCmdHandlers, - } - h.defaultChannel = h.CreateChannel("") - return &h -} - -func (h *Host) handleCommand(m Message) { - // TODO: ... -} - -func (h *Host) broadcast(ch *Channel, m Message) { - // TODO: ... -} - -func (h *Host) CreateChannel(id string) *Channel { - return NewChannel(id) -} diff --git a/chat/message.go b/chat/message.go index aee5d38..5281b1a 100644 --- a/chat/message.go +++ b/chat/message.go @@ -9,8 +9,9 @@ import ( // Container for messages sent to chat type Message struct { Body string - from *User // Not set for Sys messages - to *User // Only set for PMs + from *User // Not set for Sys messages + to *User // Only set for PMs + channel *Channel // Not set for global commands timestamp time.Time themeCache *map[*Theme]string } @@ -35,6 +36,12 @@ func (m *Message) From(u *User) *Message { return m } +// Set channel +func (m *Message) Channel(ch *Channel) *Message { + m.channel = ch + return m +} + // Render message based on the given theme func (m *Message) Render(*Theme) string { // TODO: Return []byte? diff --git a/cmd.go b/cmd.go index 89ad01a..6491cdc 100644 --- a/cmd.go +++ b/cmd.go @@ -1,7 +1,6 @@ package main import ( - "bufio" "fmt" "io/ioutil" "net/http" @@ -13,6 +12,10 @@ import ( "github.com/alexcesaro/log" "github.com/alexcesaro/log/golog" "github.com/jessevdk/go-flags" + "golang.org/x/crypto/ssh" + + "github.com/shazow/ssh-chat/chat" + "github.com/shazow/ssh-chat/sshd" ) import _ "net/http/pprof" @@ -52,9 +55,6 @@ func main() { }() } - // Initialize seed for random colors - RandomColorInit() - // Figure out the log level numVerbose := len(options.Verbose) if numVerbose > len(logLevels) { @@ -78,12 +78,55 @@ func main() { return } - server, err := NewServer(privateKey) + signer, err := ssh.ParsePrivateKey(privateKey) if err != nil { - logger.Errorf("Failed to create server: %v", err) + logger.Errorf("Failed to prase key: %v", err) return } + // TODO: MakeAuth + config := sshd.MakeNoAuth() + config.AddHostKey(signer) + + s, err := sshd.ListenSSH(options.Bind, config) + if err != nil { + logger.Errorf("Failed to listen on socket: %v", err) + return + } + defer s.Close() + + terminals := s.ServeTerminal() + channel := chat.NewChannel() + + // TODO: Move this elsewhere + go func() { + for term := range terminals { + go func() { + defer term.Close() + name := term.Conn.User() + term.SetPrompt(fmt.Sprintf("[%s]", name)) + // TODO: term.AutoCompleteCallback = ... + user := chat.NewUserScreen(name, term) + channel.Join(user) + + for { + // TODO: Handle commands etc? + line, err := term.ReadLine() + if err != nil { + break + } + m := chat.NewMessage(line).From(user) + channel.Send(*m) + } + + // TODO: Handle disconnect sooner (currently closes channel before removing) + channel.Leave(user) + user.Close() + }() + } + }() + + /* TODO: for _, fingerprint := range options.Admin { server.Op(fingerprint) } @@ -109,23 +152,17 @@ func main() { return } motdString := string(motd[:]) - /* hack to normalize line endings into \r\n */ + // hack to normalize line endings into \r\n motdString = strings.Replace(motdString, "\r\n", "\n", -1) motdString = strings.Replace(motdString, "\n", "\r\n", -1) server.SetMotd(motdString) } + */ // Construct interrupt handler sig := make(chan os.Signal, 1) signal.Notify(sig, os.Interrupt) - err = server.Start(options.Bind) - if err != nil { - logger.Errorf("Failed to start server: %v", err) - return - } - <-sig // Wait for ^C signal logger.Warningf("Interrupt signal detected, shutting down.") - server.Stop() } diff --git a/sshd/doc.go b/sshd/doc.go index 4d94d8b..aacbcac 100644 --- a/sshd/doc.go +++ b/sshd/doc.go @@ -11,6 +11,7 @@ package sshd if err != nil { // Handle opening socket error } + defer s.Close() terminals := s.ServeTerminal() @@ -21,7 +22,7 @@ package sshd term.AutoCompleteCallback = nil // ... for { - line, err := term.Readline() + line, err := term.ReadLine() if err != nil { break }