From ef1ba61ca79e8348d782a3298fcbd97a0bdb7dc5 Mon Sep 17 00:00:00 2001 From: Kevin Chabowski Date: Mon, 24 Mar 2014 20:53:46 +0100 Subject: Chatrooms roughly implemented --- buddy.go | 10 +++++++ main.go | 9 ++++++ rooms.go | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 115 insertions(+) create mode 100644 buddy.go create mode 100644 rooms.go diff --git a/buddy.go b/buddy.go new file mode 100644 index 0000000..0d1fb0c --- /dev/null +++ b/buddy.go @@ -0,0 +1,10 @@ +package main + +type Buddy struct { + Nick string + Receive chan Message +} + +func NewBuddy(nick string, room *Room) *Buddy { + // TODO: Implement me! +} diff --git a/main.go b/main.go index c18959a..b546da4 100644 --- a/main.go +++ b/main.go @@ -3,6 +3,8 @@ package main import ( "flag" "github.com/gorilla/mux" + "log" + "math" "net/http" ) @@ -10,11 +12,18 @@ var ( laddr = flag.String("laddr", ":8080", "Listen on this address") tplpath = flag.String("tplpath", "tpls", "Path to templates") staticpath = flag.String("staticpath", "static", "Path to static page elements") + perroom = flag.Int("perroom", -1, "Maximum amount of users per room (negative for unlimited)") ) func main() { flag.Parse() + if *perroom < 0 { + *perroom = math.MaxInt32 + } else if *perroom == 0 { + log.Fatalln("flag perroom must not be 0") + } + r := mux.NewRouter() r.HandleFunc("/", Home) r.PathPrefix("/static").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir(*staticpath)))) diff --git a/rooms.go b/rooms.go new file mode 100644 index 0000000..4aa8542 --- /dev/null +++ b/rooms.go @@ -0,0 +1,96 @@ +package main + +import ( + "encoding/json" + "errors" +) + +type MsgType int + +const ( + MsgChat MsgType = iota // Default + MsgJoin + MsgLeave +) + +func (mt *MsgType) MarshalJSON() ([]byte, error) { + switch *mt { + case MsgChat: + return json.Marshal("chat") + case MsgJoin: + return json.Marshal("join") + case MsgLeave: + return json.Marshal("leave") + } + + return nil, errors.New("Unknown message type") +} + +type Message struct { + Type MsgType `json:"type"` + User string `json:"user"` + Text string `json:"text,omitempty"` +} + +type Room struct { + Messages chan Message + Buddies map[string]Buddy +} + +func NewRoom() (r *Room) { + r = new(Room) + r.Messages = make(chan Message) + r.Buddies = make(map[string]Buddy) + go r.Broadcast() +} + +func (r *Room) Leave(nick string) { + if _, ok := r.Buddies[nick]; !ok { + return + } + + delete(r.Buddies[nick]) + if len(r.Buddies) == 0 { + close(r.Messages) + } else { + r.Messages <- Message{ + Type: MsgLeave, + From: nick, + } + } +} + +func (r *Room) Broadcast() { + for m := range r.Messages { + for _, buddy := range r.Buddies { + buddy.Receive <- m // TODO: What happens when this locks? + } + } +} + +var rooms = make(map[string]Room) + +func Join(room, nick string) (*Buddy, error) { + r, ok := rooms[room] + if !ok { + r = NewRoom() + rooms[room] = r + } + + if _, there := r.Buddies[nick]; there { + return nil, errors.New("Nickname is already in use") + } + + if len(r.Buddies) >= *perroom { + return nil, errors.New("Room is full") + } + + r.Messages <- Message{ + Type: MsgJoin, + From: nick, + } + + b := NewBuddy(nick, r) + r.Buddies[nick] = b + return b, nil +} -- cgit v1.2.3-54-g00ecf