diff options
| -rw-r--r-- | buddy.go | 10 | ||||
| -rw-r--r-- | main.go | 9 | ||||
| -rw-r--r-- | rooms.go | 96 | 
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! +} @@ -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 +} | 
