Permalink
Browse files

Basic session support and ship API

  • Loading branch information...
1 parent 866d87d commit 2df54c66d2c0064ec632877a330822e5fdc82388 @brendonh committed Aug 11, 2012
@@ -17,24 +17,43 @@ function startSocket(url) {
socket.onopen = function() {
console.log("Connected!");
+ var ping = {
+ 'service': 'accounts',
+ 'method': 'ping',
+ 'data': {}
+ }
+
var login = {
'service': 'accounts',
'method': 'login',
'data': {
- 'name': 'brendonh',
+ 'name': 'other',
'password': 'test'
}
}
- var ping = {
- 'service': 'accounts',
- 'method': 'ping',
+ var ships = {
+ 'service': 'ships',
+ 'method': 'list',
'data': {}
}
- sendAPICall(ping, socket)
sendAPICall(login, socket)
- sendAPICall(ping, socket)
+
+ // Temp until we have callbacks
+ setTimeout(
+ function() {
+ // sendAPICall({"service": "ships",
+ // "method": "create",
+ // "data": { "name": "Sparky" }},
+ // socket)
+ //sendAPICall(ships, socket)
+ sendAPICall(
+ {"service": "ships",
+ "method": "control",
+ "data": { "id": "d4e15abf-bf62-4bae-bf88-ce63026ded41"}},
+ socket)
+ }, 500)
}
@@ -11,10 +11,30 @@ type Account struct {
Admin bool
}
+// Storage API
func (account *Account) StorageKey() string {
return account.Name
}
+// User API
+func (account *Account) DisplayName() string {
+ return account.Name
+}
+
+// User API
+func (account *Account) ID() string {
+ return account.Name
+}
+
+
+
+func (account *Account) CheckPassword(given string) bool {
+ var err = bcrypt.CompareHashAndPassword(
+ account.PasswordHash,
+ []byte(given))
+ return err == nil
+}
+
func NewAccount(name string, password string) *Account {
hash, _ := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
@@ -38,11 +58,5 @@ func CreateAccount(name string, password string, context ServerContext) (*Accoun
}
-func (account *Account) CheckPassword(given string) bool {
- var err = bcrypt.CompareHashAndPassword(
- account.PasswordHash,
- []byte(given))
- return err == nil
-}
@@ -5,7 +5,6 @@ import (
"drift/services"
"fmt"
- "time"
)
// ------------------------------------------
@@ -39,7 +38,7 @@ func GetService() *services.Service {
}
-func method_register(args APIData, context ServerContext) (bool, APIData) {
+func method_register(args APIData, session Session, context ServerContext) (bool, APIData) {
var response = make(APIData)
account, ok := CreateAccount(
@@ -60,25 +59,33 @@ func method_register(args APIData, context ServerContext) (bool, APIData) {
}
-func method_login(args APIData, context ServerContext) (bool, APIData) {
+func method_login(args APIData, session Session, context ServerContext) (bool, APIData) {
var response = make(APIData)
+ session.Lock()
+ defer session.Unlock()
+
+ if session.User() != nil {
+ response["message"] = "Already logged in"
+ return false, response
+ }
+
var client = context.Storage()
- var account = Account{Name: args["name"].(string)}
+ var account = &Account{Name: args["name"].(string)}
- if !client.Get(&account) || !account.CheckPassword(args["password"].(string)) {
+ if !client.Get(account) || !account.CheckPassword(args["password"].(string)) {
response["message"] = "Invalid credentials"
return false, response
}
- time.Sleep(2 * time.Second)
+ session.SetUser(account)
return true, response
}
-func method_ping(args APIData, context ServerContext) (bool, APIData) {
+func method_ping(args APIData, session Session, context ServerContext) (bool, APIData) {
var response = make(APIData)
response["message"] = "Pong"
return true, response
@@ -16,6 +16,35 @@ type Endpoint interface {
}
+// ------------------------------------------
+// Users and sessions
+// ------------------------------------------
+
+type User interface {
+ ID() string
+ DisplayName() string
+}
+
+type Session interface {
+ ID() string
+ User() User
+ Avatar() Entity
+
+ Lock()
+ Unlock()
+
+ SetUser(User)
+ SetAvatar(Entity)
+}
+
+
+// ------------------------------------------
+// Entities
+// ------------------------------------------
+
+type Entity interface {
+}
+
// ------------------------------------------
// API
@@ -45,7 +74,7 @@ type APIMethod struct {
type APIData map[string]interface{}
-type APIHandler func(APIData, ServerContext) (bool, APIData)
+type APIHandler func(APIData, Session, ServerContext) (bool, APIData)
@@ -61,8 +90,8 @@ type APIService interface {
type API interface {
AddService(APIService)
- HandleRequest(APIData, ServerContext) APIData
- HandleCall(string, string, APIData, ServerContext) (bool, []string, APIData)
+ HandleRequest(APIData, Session, ServerContext) APIData
+ HandleCall(string, string, APIData, Session, ServerContext) (bool, []string, APIData)
}
@@ -78,8 +78,11 @@ func (endpoint *HttpRpcEndpoint) ServeHTTP(response http.ResponseWriter, req *ht
form[k] = v[0]
}
+ // XXX TODO: Session tracking
+ var session = NewEndpointSession()
+
ok, errors, resp := endpoint.context.API().HandleCall(
- bits[0], bits[1], form, endpoint.context)
+ bits[0], bits[1], form, session, endpoint.context)
if errors != nil {
response.WriteHeader(400)
@@ -0,0 +1,54 @@
+package endpoints
+
+import (
+ . "drift/common"
+
+ "sync"
+ "fmt"
+
+ "code.google.com/p/go-uuid/uuid"
+)
+
+
+type EndpointSession struct {
+ id string
+ user User
+ avatar Entity
+ *sync.Mutex
+}
+
+func NewEndpointSession() *EndpointSession {
+ return &EndpointSession {
+ id: uuid.New(),
+ user: nil,
+ avatar: nil,
+ Mutex: new(sync.Mutex),
+ }
+}
+
+
+// ------------------------------------------
+// Session API
+// ------------------------------------------
+
+func (session *EndpointSession) ID() string {
+ return session.id;
+}
+
+func (session *EndpointSession) User() User {
+ return session.user;
+}
+
+func (session *EndpointSession) Avatar() Entity {
+ return session.avatar;
+}
+
+func (session *EndpointSession) SetUser(user User) {
+ fmt.Printf("Session login: %s (%s)\n", user.DisplayName(), session.id)
+ session.user = user
+}
+
+func (session *EndpointSession) SetAvatar(entity Entity) {
+ fmt.Printf("Session set entity: %v (%s)\n", entity, session.id)
+ session.avatar = entity
+}
@@ -81,6 +81,9 @@ func (endpoint *WebsocketEndpoint) Handle(ws *websocket.Conn) {
ws.PayloadType = websocket.BinaryFrame
var buf = make([]byte, 1024 * 64)
+ var session Session = NewEndpointSession()
+
+ fmt.Printf("New session: %s\n", session.ID())
for {
@@ -102,7 +105,7 @@ func (endpoint *WebsocketEndpoint) Handle(ws *websocket.Conn) {
switch buf[0] {
case APIFrame:
- go endpoint.HandleAPI(msgBuf, ws)
+ go endpoint.HandleAPI(msgBuf, session, ws)
case PositionFrame:
fmt.Printf("Position frame: %v\n", msgBuf)
default:
@@ -112,7 +115,7 @@ func (endpoint *WebsocketEndpoint) Handle(ws *websocket.Conn) {
}
-func (endpoint *WebsocketEndpoint) HandleAPI(buf []byte, ws *websocket.Conn) {
+func (endpoint *WebsocketEndpoint) HandleAPI(buf []byte, session Session, ws *websocket.Conn) {
var data APIData
var resolver = msgpack.DefaultDecoderContainerResolver
resolver.MapType = reflect.TypeOf(make(APIData))
@@ -126,7 +129,7 @@ func (endpoint *WebsocketEndpoint) HandleAPI(buf []byte, ws *websocket.Conn) {
return
}
- var response = endpoint.context.API().HandleRequest(data, endpoint.context)
+ var response = endpoint.context.API().HandleRequest(data, session, endpoint.context)
if id, ok := data["id"]; ok {
response["id"] = id
@@ -67,7 +67,7 @@ var requestArgSpec = []APIArg {
APIArg{Name: "data", ArgType: RawArg},
}
-func (collection ServiceCollection) HandleRequest(request APIData, context ServerContext) APIData {
+func (collection ServiceCollection) HandleRequest(request APIData, session Session, context ServerContext) APIData {
ok, resolutionErrors, args := Parse(requestArgSpec, request)
if !ok {
@@ -78,14 +78,15 @@ func (collection ServiceCollection) HandleRequest(request APIData, context Serve
args["service"].(string),
args["method"].(string),
args["data"].(APIData),
- context))
+ session, context))
}
func (collection ServiceCollection) HandleCall(
serviceName string,
methodName string,
data APIData,
+ session Session,
context ServerContext) (bool, []string, APIData) {
@@ -104,7 +105,7 @@ func (collection ServiceCollection) HandleCall(
return false, ListToStringSlice(errors), nil
}
- ok, response := method.Handler(args, context)
+ ok, response := method.Handler(args, session, context)
if !ok {
return false, nil, response
}
Oops, something went wrong.

0 comments on commit 2df54c6

Please sign in to comment.