diff --git a/main.go b/main.go index e9c93d6..f372457 100644 --- a/main.go +++ b/main.go @@ -1,7 +1,6 @@ package main import ( - "bitbucket.org/hackerbots/botserv/protocol" "code.google.com/p/go.net/websocket" "flag" "fmt" @@ -49,61 +48,14 @@ func main() { } func addPlayer(ws *websocket.Conn) { - var err error - id := fmt.Sprintf("robot%d", <-g.id) - log.Printf("sending robot id: %s", id) - err = websocket.JSON.Send(ws, protocol.NewIdRequest(id)) + conf, err := Negociate(ws, id, *width, *height) if err != nil { - log.Printf("%s: problem sending initial identification", id) - websocket.JSON.Send(ws, protocol.NewFailure("generic server error")) - return + websocket.JSON.Send(ws, NewFailure(err.Error())) } - var clientid protocol.ClientID - err = websocket.JSON.Receive(ws, &clientid) - if err != nil { - log.Printf("%s: problem parsing clientID", id) - websocket.JSON.Send(ws, protocol.NewFailure("could not parse id")) - return - } - if v, msg := clientid.Valid(); !v { - log.Printf("%s: invalid clientid: %+v", id, clientid) - websocket.JSON.Send( - ws, - protocol.NewFailure(msg), - ) - return - } - - gameParam := protocol.NewGameParam(*width, *height) - err = websocket.JSON.Send(ws, gameParam) - if err != nil { - log.Println("%s: problem sending game info: %+v", id, gameParam) - websocket.JSON.Send(ws, protocol.NewFailure("generic server error")) - return - } - - switch clientid.Type { - case "robot": - var conf Config - for { - err = websocket.JSON.Receive(ws, &conf) - if err != nil { - log.Print(err) - return - } - if conf.Stats.valid() { - _ = websocket.JSON.Send(ws, protocol.NewHandshake(id, true)) - break - } else { - _ = websocket.JSON.Send(ws, protocol.NewHandshake(id, false)) - log.Printf("%s invalid config", id) - } - } - log.Printf("%s eventually sent valid config: %+v", id, conf) - + if conf != nil { p := &player{ Robot: robot{ Stats: conf.Stats, @@ -121,7 +73,7 @@ func addPlayer(ws *websocket.Conn) { go p.sender() p.recv() log.Printf("%v has been disconnect from this game\n", p.Robot.Id) - case "spectator": + } else { s := &Spectator{ send: make(chan *boardstate), ws: ws, diff --git a/protocol.go b/protocol.go new file mode 100644 index 0000000..62d8166 --- /dev/null +++ b/protocol.go @@ -0,0 +1,140 @@ +package main + +import ( + "code.google.com/p/go.net/websocket" + "errors" + "log" +) + +// > identify +type IdRequest struct { + Type string `json:"type"` + AssignedID string `json:"id"` +} + +func NewIdRequest(id string) *IdRequest { + return &IdRequest{ + Type: "idreq", + AssignedID: id, + } +} + +// < [robot | spectator], name, client-type, game ID +type ClientID struct { + Type string `json:"type"` + Name string `json:"name"` + Useragent string `json:"useragent"` +} + +func (c *ClientID) Valid() (bool, string) { + switch c.Type { + case "robot", "spectator": + return true, "" + } + return false, "usergent must be 'robot' or 'spectator'" +} + +type BoardSize struct { + Width float64 `json:"width"` + Height float64 `json:"height"` +} + +type GameParam struct { + BoardSize BoardSize `json:"boardsize"` + Type string `json:"type"` +} + +// > [OK | FULL | NOT AUTH], board size, game params +func NewGameParam(w, h float64) *GameParam { + return &GameParam{ + BoardSize: BoardSize{ + Width: w, + Height: h, + }, + Type: "gameparam", + } +} + +type Handshake struct { + ID string `json:"id"` + Success bool `json:"success"` + Type string `json:"type"` +} + +func NewHandshake(id string, success bool) *Handshake { + return &Handshake{ + ID: id, + Success: success, + Type: "handshake", + } +} + +type Failure struct { + Reason string `json:"reason"` + Type string `json:"type"` +} + +func NewFailure(reason string) *Failure { + return &Failure{ + Reason: reason, + Type: "failure", + } +} + +func Negociate(ws *websocket.Conn, id string, width, height float64) (*Config, error) { + var err error + + log.Printf("sending robot id: %s", id) + + err = websocket.JSON.Send(ws, NewIdRequest(id)) + if err != nil { + log.Printf("%s: problem sending initial identification", id) + return nil, errors.New("generic servr error") + } + + var clientid ClientID + err = websocket.JSON.Receive(ws, &clientid) + if err != nil { + log.Printf("%s: problem parsing clientID", id) + return nil, errors.New("could not parse id") + } + if v, msg := clientid.Valid(); !v { + log.Printf("%s: invalid clientid: %+v", id, clientid) + websocket.JSON.Send( + ws, + NewFailure(msg), + ) + return nil, errors.New(msg) + } + + gameParam := NewGameParam(width, height) + err = websocket.JSON.Send(ws, gameParam) + if err != nil { + log.Println("%s: problem sending game info: %+v", id, gameParam) + websocket.JSON.Send(ws, NewFailure("generic server error")) + return nil, err + } + switch clientid.Type { + case "robot": + var conf Config + for { + err = websocket.JSON.Receive(ws, &conf) + if err != nil { + log.Print(err) + return nil, err + } + if conf.Stats.valid() { + _ = websocket.JSON.Send(ws, NewHandshake(id, true)) + break + } else { + _ = websocket.JSON.Send(ws, NewHandshake(id, false)) + log.Printf("%s invalid config", id) + } + } + log.Printf("%s eventually sent valid config: %+v", id, conf) + return &conf, nil + case "spectator": + return nil, nil + } + return nil, nil +} diff --git a/protocol/protocol.go b/protocol/protocol.go deleted file mode 100644 index a182fe3..0000000 --- a/protocol/protocol.go +++ /dev/null @@ -1,76 +0,0 @@ -package protocol - -// > identify -type IdRequest struct { - Type string `json:"type"` - AssignedID string `json:"id"` -} - -func NewIdRequest(id string) *IdRequest { - return &IdRequest{ - Type: "idreq", - AssignedID: id, - } -} - -// < [robot | spectator], name, client-type, game ID -type ClientID struct { - Type string `json:"type"` - Name string `json:"name"` - Useragent string `json:"useragent"` -} - -func (c *ClientID) Valid() (bool, string) { - switch c.Type { - case "robot", "spectator": - return true, "" - } - return false, "usergent must be 'robot' or 'spectator'" -} - -type BoardSize struct { - Width float64 `json:"width"` - Height float64 `json:"height"` -} - -type GameParam struct { - BoardSize BoardSize `json:"boardsize"` - Type string `json:"type"` -} - -// > [OK | FULL | NOT AUTH], board size, game params -func NewGameParam(w, h float64) *GameParam { - return &GameParam{ - BoardSize: BoardSize{ - Width: w, - Height: h, - }, - Type: "gameparam", - } -} - -type Handshake struct { - ID string `json:"id"` - Success bool `json:"success"` - Type string `json:"type"` -} - -func NewHandshake(id string, success bool) *Handshake { - return &Handshake{ - ID: id, - Success: success, - Type: "handshake", - } -} - -type Failure struct { - Reason string `json:"reason"` - Type string `json:"type"` -} - -func NewFailure(reason string) *Failure { - return &Failure{ - Reason: reason, - Type: "failure", - } -} diff --git a/protocol/protocol_test.go b/protocol_test.go similarity index 98% rename from protocol/protocol_test.go rename to protocol_test.go index da25620..a1001e8 100644 --- a/protocol/protocol_test.go +++ b/protocol_test.go @@ -1,4 +1,4 @@ -package protocol +package main import ( "encoding/json"