Enforce unique usernames

This commit is contained in:
Trevor Slocum 2023-09-09 00:31:45 -07:00
parent edeb5806d9
commit 16fce188d3
2 changed files with 65 additions and 12 deletions

View file

@ -5,6 +5,7 @@ import (
"fmt"
"log"
"strconv"
"time"
"code.rocket9labs.com/tslocum/bgammon"
)
@ -19,6 +20,7 @@ type serverClient struct {
lastPing int64
commands <-chan []byte
playerNumber int
terminating bool
bgammon.Client
}
@ -133,3 +135,21 @@ func (c *serverClient) label() string {
}
return strconv.Itoa(c.id)
}
func (c *serverClient) Terminate(reason string) {
if c.Terminated() || c.terminating {
return
}
c.terminating = true
var extra string
if reason != "" {
extra = ": " + reason
}
c.sendNotice("Connection terminated" + extra)
go func() {
time.Sleep(time.Second)
c.Client.Terminate(reason)
}()
}

View file

@ -67,6 +67,16 @@ func (s *server) handleListener(listener net.Listener) {
}
}
func (s *server) nameAvailable(username []byte) bool {
lower := bytes.ToLower(username)
for _, c := range s.clients {
if bytes.Equal(bytes.ToLower(c.name), lower) {
return false
}
}
return true
}
func (s *server) addClient(c *serverClient) {
s.clientsLock.Lock()
defer s.clientsLock.Unlock()
@ -197,9 +207,14 @@ func (s *server) handleNewClientIDs() {
}
func (s *server) randomUsername() []byte {
// TODO check if username is available
i := 100 + rand.Intn(900)
return []byte(fmt.Sprintf("Guest%d", i))
for {
i := 100 + rand.Intn(900)
name := []byte(fmt.Sprintf("Guest%d", i))
if s.nameAvailable(name) {
return name
}
}
}
func (s *server) sendHello(c *serverClient) {
@ -250,18 +265,40 @@ COMMANDS:
// Require users to send login command first.
if cmd.client.account == -1 {
if keyword == bgammon.CommandLogin || keyword == bgammon.CommandLoginJSON || keyword == "l" || keyword == "lj" {
if keyword == bgammon.CommandLoginJSON || keyword == "lj" {
cmd.client.json = true
}
s.clientsLock.Lock()
var username []byte
var password []byte
readUsername := func() bool {
username = params[0]
if !s.nameAvailable(username) {
cmd.client.Terminate("Username unavailable.")
return false
}
return true
}
switch len(params) {
case 0:
username = s.randomUsername()
case 1:
username = params[0]
if !readUsername() {
s.clientsLock.Unlock()
continue
}
default:
username = params[0]
if !readUsername() {
s.clientsLock.Unlock()
continue
}
password = bytes.Join(params[1:], []byte(" "))
}
s.clientsLock.Unlock()
if len(password) > 0 {
cmd.client.account = 1
} else {
@ -269,10 +306,6 @@ COMMANDS:
}
cmd.client.name = username
if keyword == bgammon.CommandLoginJSON || keyword == "lj" {
cmd.client.json = true
}
cmd.client.sendEvent(&bgammon.EventWelcome{
PlayerName: string(cmd.client.name),
Clients: len(s.clients),
@ -281,10 +314,10 @@ COMMANDS:
log.Printf("Client %d logged in as %s", cmd.client.id, cmd.client.name)
continue
} else {
cmd.client.Terminate("You must login before using other commands.")
continue
}
cmd.client.Terminate("You must login before using other commands.")
continue
}
clientGame := s.gameByClient(cmd.client)