handle SIGINT, some cleanup
parent
8a56e79f5d
commit
03e3aa866d
|
@ -7,6 +7,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -56,6 +58,25 @@ func (cs *ClientState) Messages() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cs *ClientState) HandleSIGINT(sigC chan os.Signal) {
|
||||||
|
for range sigC {
|
||||||
|
cm := &proto.Command{
|
||||||
|
SessionInfo: cs.SessionInfo,
|
||||||
|
Verb: "quit",
|
||||||
|
}
|
||||||
|
err := cs.cmdStream.Send(cm)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("failed to send quit verb to server: %s\n", err.Error())
|
||||||
|
}
|
||||||
|
_, err = cs.cmdStream.Recv()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("failed to receive an ACK from server: %s\n", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
cs.App.Stop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (cs *ClientState) HandleInput(input string) error {
|
func (cs *ClientState) HandleInput(input string) error {
|
||||||
var verb string
|
var verb string
|
||||||
rest := input
|
rest := input
|
||||||
|
@ -74,6 +95,10 @@ func (cs *ClientState) HandleInput(input string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
_, err = cs.cmdStream.Recv()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("failed to receive an ACK from server: %s\n", err.Error())
|
||||||
|
}
|
||||||
if verb == "quit" || verb == "q" {
|
if verb == "quit" || verb == "q" {
|
||||||
cs.App.Stop()
|
cs.App.Stop()
|
||||||
}
|
}
|
||||||
|
@ -158,13 +183,10 @@ func _main() error {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
pong, err := cs.Client.Ping(ctx, cs.SessionInfo)
|
if _, err = cs.Client.Ping(ctx, cs.SessionInfo); err != nil {
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("%v.Ping -> %v", cs.Client, err)
|
log.Fatalf("%v.Ping -> %v", cs.Client, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("%#v", pong)
|
|
||||||
|
|
||||||
pages := tview.NewPages()
|
pages := tview.NewPages()
|
||||||
|
|
||||||
pages.AddPage("splash",
|
pages.AddPage("splash",
|
||||||
|
@ -202,6 +224,9 @@ func _main() error {
|
||||||
|
|
||||||
pages.AddPage("main", mainPage, true, false)
|
pages.AddPage("main", mainPage, true, false)
|
||||||
|
|
||||||
|
sigC := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(sigC, os.Interrupt)
|
||||||
|
|
||||||
lunfi := tview.NewInputField().SetLabel("account name")
|
lunfi := tview.NewInputField().SetLabel("account name")
|
||||||
lpwfi := tview.NewInputField().SetLabel("password").SetMaskCharacter('~')
|
lpwfi := tview.NewInputField().SetLabel("password").SetMaskCharacter('~')
|
||||||
|
|
||||||
|
@ -225,6 +250,7 @@ func _main() error {
|
||||||
|
|
||||||
pages.SwitchToPage("game")
|
pages.SwitchToPage("game")
|
||||||
app.SetFocus(commandInput)
|
app.SetFocus(commandInput)
|
||||||
|
go cs.HandleSIGINT(sigC)
|
||||||
// TODO error handle
|
// TODO error handle
|
||||||
go cs.Messages()
|
go cs.Messages()
|
||||||
}
|
}
|
||||||
|
@ -260,6 +286,7 @@ func _main() error {
|
||||||
|
|
||||||
pages.SwitchToPage("game")
|
pages.SwitchToPage("game")
|
||||||
app.SetFocus(commandInput)
|
app.SetFocus(commandInput)
|
||||||
|
go cs.HandleSIGINT(sigC)
|
||||||
// TODO error handle
|
// TODO error handle
|
||||||
go cs.Messages()
|
go cs.Messages()
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -37,7 +36,6 @@ func _main() (err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Printf("DBG %#v\n", l)
|
|
||||||
|
|
||||||
var opts []grpc.ServerOption
|
var opts []grpc.ServerOption
|
||||||
if *tls {
|
if *tls {
|
||||||
|
@ -146,7 +144,7 @@ func (s *gameWorldServer) verbHandler(verb, rest string, sender, target db.Objec
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ok {
|
if !ok || sc == nil {
|
||||||
sc, err = witch.NewScriptContext(serverAPI)
|
sc, err = witch.NewScriptContext(serverAPI)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -173,42 +171,83 @@ func (s *gameWorldServer) HandleCmd(verb, rest string, sender *db.Object) {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *gameWorldServer) endSession(sid string) error {
|
||||||
|
log.Printf("ending session %s", sid)
|
||||||
|
|
||||||
|
errors := []string{}
|
||||||
|
err := s.db.EndSession(sid)
|
||||||
|
if err != nil {
|
||||||
|
errors = append(errors, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
s.msgRouter[sid] = nil
|
||||||
|
|
||||||
|
avatar, err := s.db.AvatarBySessionID(sid)
|
||||||
|
if err != nil {
|
||||||
|
errors = append(errors, err.Error())
|
||||||
|
} else {
|
||||||
|
s.scriptsMutex.Lock()
|
||||||
|
s.scripts[avatar.ID] = nil
|
||||||
|
s.scriptsMutex.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(errors) > 0 {
|
||||||
|
return fmt.Errorf("error(s) encountered trying to end session %s: %v", sid, errors)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *gameWorldServer) Commands(stream proto.GameWorld_CommandsServer) error {
|
func (s *gameWorldServer) Commands(stream proto.GameWorld_CommandsServer) error {
|
||||||
var sid string
|
var sid string
|
||||||
|
var cmd *proto.Command
|
||||||
|
var err error
|
||||||
|
var avatar *db.Object
|
||||||
|
var send func(*proto.ClientMessage) error
|
||||||
|
var affected []db.Object
|
||||||
|
var o db.Object
|
||||||
for {
|
for {
|
||||||
cmd, err := stream.Recv()
|
if cmd, err = stream.Recv(); err != nil {
|
||||||
if err == io.EOF {
|
log.Printf("commands stream closed with error: %s", err.Error())
|
||||||
// TODO this doesn't really do anything. if a client
|
|
||||||
// disconnects without warning there's no EOF.
|
|
||||||
return s.db.EndSession(sid)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
sid = cmd.SessionInfo.SessionID
|
if sid == "" {
|
||||||
|
sid = cmd.SessionInfo.SessionID
|
||||||
log.Printf("verb %s in session %s", cmd.Verb, sid)
|
defer s.endSession(sid)
|
||||||
|
|
||||||
if cmd.Verb == "quit" || cmd.Verb == "q" {
|
|
||||||
s.msgRouter[sid] = nil
|
|
||||||
log.Printf("ending session %s", sid)
|
|
||||||
return s.db.EndSession(sid)
|
|
||||||
}
|
}
|
||||||
send := s.msgRouter[sid]
|
|
||||||
|
|
||||||
// TODO what is the implication of returning an error from this function?
|
err = stream.Send(&proto.CommandAck{
|
||||||
|
Acked: true,
|
||||||
|
})
|
||||||
|
|
||||||
avatar, err := s.db.AvatarBySessionID(sid)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Printf("unable to ack command in session %s", sid)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if send == nil {
|
||||||
|
send = s.msgRouter[sid]
|
||||||
|
}
|
||||||
|
|
||||||
|
if avatar, err = s.db.AvatarBySessionID(sid); err != nil {
|
||||||
return s.HandleError(send, err)
|
return s.HandleError(send, err)
|
||||||
}
|
}
|
||||||
log.Printf("found avatar %#v", avatar)
|
|
||||||
|
|
||||||
affected, err := s.db.Earshot(*avatar)
|
log.Printf("verb %s from avatar %d in session %s", cmd.Verb, avatar.ID, sid)
|
||||||
|
|
||||||
for _, o := range affected {
|
if cmd.Verb == "quit" || cmd.Verb == "q" {
|
||||||
err = s.verbHandler(cmd.Verb, cmd.Rest, *avatar, o)
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if affected, err = s.db.Earshot(*avatar); err != nil {
|
||||||
|
return s.HandleError(send, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, o = range affected {
|
||||||
|
if err = s.verbHandler(cmd.Verb, cmd.Rest, *avatar, o); err != nil {
|
||||||
|
log.Printf("error handling verb %s for object %d: %s", cmd.Verb, o.ID, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//s.HandleCmd(cmd.Verb, cmd.Rest, avatar)
|
//s.HandleCmd(cmd.Verb, cmd.Rest, avatar)
|
||||||
|
@ -387,7 +426,6 @@ func (s *gameWorldServer) HandleError(send func(*proto.ClientMessage) error, err
|
||||||
// TODO other server functions
|
// TODO other server functions
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// TODO at some point during startup clear out sessions
|
|
||||||
err := _main()
|
err := _main()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err.Error())
|
log.Fatal(err.Error())
|
||||||
|
|
|
@ -297,12 +297,11 @@ func (db *pgDB) SessionIDForAvatar(obj Object) (string, error) {
|
||||||
if !obj.Avatar {
|
if !obj.Avatar {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
fmt.Printf("%#v", obj)
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
stmt := `SELECT id FROM sessions WHERE account = $1`
|
stmt := `SELECT id FROM sessions WHERE account = $1`
|
||||||
var sid *string
|
var sid *string
|
||||||
err := db.pool.QueryRow(ctx, stmt, obj.OwnerID).Scan(&sid)
|
var err error
|
||||||
if err != nil {
|
if err = db.pool.QueryRow(ctx, stmt, obj.OwnerID).Scan(&sid); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,7 +314,6 @@ func (db *pgDB) SessionIDForAvatar(obj Object) (string, error) {
|
||||||
|
|
||||||
func (db *pgDB) AvatarBySessionID(sid string) (avatar *Object, err error) {
|
func (db *pgDB) AvatarBySessionID(sid string) (avatar *Object, err error) {
|
||||||
avatar = &Object{}
|
avatar = &Object{}
|
||||||
|
|
||||||
// TODO subquery
|
// TODO subquery
|
||||||
stmt := `
|
stmt := `
|
||||||
SELECT id, avatar, data, owner, script
|
SELECT id, avatar, data, owner, script
|
||||||
|
|
|
@ -114,5 +114,6 @@ func NewScriptContext(sAPI ServerAPI) (*ScriptContext, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sc *ScriptContext) Handle(vc VerbContext) {
|
func (sc *ScriptContext) Handle(vc VerbContext) {
|
||||||
|
log.Printf("%#v", sc)
|
||||||
sc.incoming <- vc
|
sc.incoming <- vc
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue