all repos — felt @ 8c5eeeaa080929e00dce35525e8b849cf3e930b7

virtual tabletop for dungeons and dragons (and similar) using Go, MongoDB, and websockets

server, adapter: starting to put things together
Iris Lightshard nilix@nilfm.cc
PGP Signature
-----BEGIN PGP SIGNATURE-----

iQIzBAABCAAdFiEEkFh6dA+k/6CXFXU4O3+8IhROY5gFAmODiMAACgkQO3+8IhRO
Y5gQWQ/+Jbu/e6hyteV6pjXqQJicTZ1QpJpYRkK7RCMwbZoTQKSX5x0Tm0adtLqJ
zS6qwGygkaOBNZL9q97REJYhJE/meAAoTg5FW+ofcc0OvYMoFWZlGMDlmnp+MCV+
L5JVGcJrw9BFV8YASyoij5IXPjTILVdzm0H1yWTVeizD7XlFqM367B0Vwmu9al7u
7wWJ3g6B5P7iJ4FIo72z2DQ2ODOLESilvTWS+If7LDFyW3zcDcdvZtYdTa0V1/fI
YKgpzSZHK0NKpR3LszMILKafVgQaFj7mm+fNRHBz72eZfs9q22enUDjs5ZQj7asi
ugHZmQ9h1poXcRgytqNNic9zizWCwWpXLAq7o+rnrsmYFTYYiGBq0TbetvxzSBrs
ML3hFaaghVvCFDckalWrBx1J2CXmqVKgP36ppJeRTpMdhUazbyFhBUsL+ZKgDeCz
X2jJCG9od8xQSgN5eJa5fBKYRsOywOX+mhf1mYj0dh1M4YULGcfZ/1ysa7AOO7q8
A9WlbBxGsbeg//YQzmLQ0otjbB9dxCGESXM2kuBCPAkdRBoRKflbGxzwrAwjosyC
aiIk+usDZqv/rzvYuSFw1aTP5y5HsBAPVfNuId2HB13jXqR0ra8RHROtArM9Evk1
kyGFDBLXbzxoyRqJJCK54HgkY3dcZkCO/lAQBf6mfJQV76qAY78=
=qg01
-----END PGP SIGNATURE-----
commit

8c5eeeaa080929e00dce35525e8b849cf3e930b7

parent

e6faf9478aab0e9958e43b5b0a2987698cdba480

2 files changed, 65 insertions(+), 8 deletions(-)

jump to
M gametable/server.gogametable/server.go

@@ -8,6 +8,9 @@ "io/ioutil"

"log" "net/http" "nhooyr.io/websocket" + "nilfm.cc/git/felt/dbengine" + "nilfm.cc/git/felt/models" + "nilfm.cc/git/quartzgun/cookie" "sync" "time" )

@@ -23,15 +26,17 @@ publishLimiter *rate.Limiter

logf func(f string, v ...interface{}) serveMux http.ServeMux subscribersLock sync.Mutex - subscribers map[*Subscriber]struct{} + subscribers map[*Subscriber]models.tableKey + dbAdapter dbengine.DbAdapter } -func New() *GameTableServer { +func New(adapter dbengine.DbAdapter) *GameTableServer { srvr := &GameTableServer{ subscribeMessageBuffer: 16, logf: log.Printf, - subscribers: make(map[*Subscriber]struct{}), + subscribers: make(map[*Subscriber]models.TableKey{}), publishLimiter: rate.NewLimiter(rate.Every(time.Millisecond*100), 8), + dbAdapter: adapter, } srvr.serveMux.Handle("/", http.FileServer(http.Dir("./static"))) srvr.serveMux.HandleFunc("/subscribe", srvr.subscribeHandler)

@@ -66,7 +71,8 @@ return

} } -func (self *GameTableServer) subscribe(ctx context.Context, c *websocket.Conn) error { +func (self *GameTableServer) subscribe(r *http.Request, c *websocket.Conn) error { + ctx := r.Context() ctx = c.CloseRead(ctx) s := &Subscriber{

@@ -75,8 +81,33 @@ closeSlow: func() {

c.Close(websocket.StatusPolicyViolation, "connection too slow to keep up with messages") }, } + + tableName, tblNameErr := cookie.GetToken("tableName", r) + tablePasscode, tblPassErr := cookie.GetToken("tablePasscode", r) + + if tblNameErr != nil { + return tblNameErr + } else if tblPassErr != nil { + return tblPassErr + } + + tableKey = models.TableKey{ + Name: tableName, + Passcode: tablePasscode, + } + + if !self.dbAdapter.CheckTable(tableKey) { + return errors.New("Table with matching key was not found on this server") + } + self.addSubscriber(s) + defer self.deleteSubscriber(s) + select { + case s.msgs <- self.getCurrentState(tableKey): + default: + go s.closeSlow() + } for { select {

@@ -125,9 +156,16 @@ }

} } -func (self *GameTableServer) addSubscriber(s *Subscriber) { +func (self *GameTableServer) getCurrentState(tableKey models.TableKey) []byte { + // get diceroll log, map, and token state + // build into a []byte message + + return make([]byte, 1) +} + +func (self *GameTableServer) addSubscriber(s *Subscriber, k models.TableKey) { self.subscribersLock.Lock() - self.subscribers[s] = struct{}{} + self.subscribers[s] = k self.subscribersLock.Unlock() }
M mongodb/adapter.gomongodb/adapter.go

@@ -20,6 +20,8 @@

CreateTable(table models.TableKey) error DestroyTable(table models.TableKey) error + CheckTable(table models.TableKey) boolean + InsertDiceRoll(table models.TableKey, diceRoll models.DiceRoll) error GetDiceRolls(table models.TableKey) ([]models.DiceRoll, error)

@@ -38,7 +40,8 @@ db mongo.Database

} func (self *DbEngine) mkCtx(timeoutSec int) context.Context { - return context.WithTimeout(context.Background(), 10*time.Second) + ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) + return ctx } func (self *DbEngine) Init(mongoUri string) error {

@@ -47,7 +50,7 @@ if err != nil {

return err } self.client = client - ctx, _ := self.mkCtx(10) + ctx := self.mkCtx(10) err = client.Connect(ctx) if err != nil {

@@ -112,6 +115,22 @@ })

return err } return errors.New(fmt.Sprintf(errNoCollection, "tables")) +} + +func (self *DbEngine) CheckTable(table models.TableKey) boolean { + tables := self.db.Collection("tables") + if tables != nil { + _, err := tables.FindOne(self.mkCtx(10), bson.D{ + {"name", table.Name}, + {"passcode", table.Passcode}, + }) + if err != nil { + return false + } else { + return true + } + } + return false } func (self *DbEngine) InsertDiceRoll(table models.TableKey, diceRoll models.DiceRoll) error {