summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Chabowski <kevin@kch42.de>2014-03-24 20:53:46 +0100
committerKevin Chabowski <kevin@kch42.de>2014-03-24 20:53:46 +0100
commitef1ba61ca79e8348d782a3298fcbd97a0bdb7dc5 (patch)
tree74d2bf499fb116da1a22de1f79256530f5d7b79a
parent79fed0e58753d50c613d15589b8f687474c2224c (diff)
downloadsimplechat-ef1ba61ca79e8348d782a3298fcbd97a0bdb7dc5.tar.gz
simplechat-ef1ba61ca79e8348d782a3298fcbd97a0bdb7dc5.tar.bz2
simplechat-ef1ba61ca79e8348d782a3298fcbd97a0bdb7dc5.zip
Chatrooms roughly implemented
-rw-r--r--buddy.go10
-rw-r--r--main.go9
-rw-r--r--rooms.go96
3 files changed, 115 insertions, 0 deletions
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
+}