Rename result to response, add room for alternate responses

This commit is contained in:
Jason Coene
2013-06-09 18:23:25 -05:00
parent a80589b330
commit f39ea02cc7
5 changed files with 55 additions and 43 deletions

View File

@@ -31,8 +31,8 @@ type Client struct {
inChunkSize uint32
inChunkStreams map[uint32]*InboundChunkStream
results map[uint32]*Result
resultsMutex sync.Mutex
responses map[uint32]*Response
responsesMutex sync.Mutex
lastTransactionId uint32
connectionId string
@@ -83,7 +83,7 @@ func (c *Client) Reset() {
c.inChunkSize = DEFAULT_CHUNK_SIZE
c.inWindowSize = DEFAULT_WINDOW_SIZE
c.inChunkStreams = make(map[uint32]*InboundChunkStream)
c.results = make(map[uint32]*Result)
c.responses = make(map[uint32]*Response)
c.lastTransactionId = 0
c.connectionId = ""
}
@@ -142,7 +142,7 @@ func (c *Client) NextTransactionId() uint32 {
return atomic.AddUint32(&c.lastTransactionId, 1)
}
func (c *Client) Call(msg *Message, t uint32) (result *Result, err error) {
func (c *Client) Call(msg *Message, t uint32) (response *Response, err error) {
c.outMessages <- msg
tid := msg.TransactionId
@@ -152,19 +152,19 @@ func (c *Client) Call(msg *Message, t uint32) (result *Result, err error) {
for {
select {
case <-poll:
c.resultsMutex.Lock()
result = c.results[tid]
if result != nil {
log.Trace("client call: found result for %d", tid)
delete(c.results, tid)
c.responsesMutex.Lock()
response = c.responses[tid]
if response != nil {
log.Trace("client call: found response for %d", tid)
delete(c.responses, tid)
}
c.resultsMutex.Unlock()
c.responsesMutex.Unlock()
if result != nil {
if response != nil {
return
}
case <-timeout:
return result, Error("timed out (no response after %d seconds)", t)
return response, Error("timed out (no response after %d seconds)", t)
}
}

View File

@@ -13,23 +13,23 @@ func (c *Client) connect() (id string, err error) {
return id, Error("client connect: unable to encode connect command: %s", err)
}
var result *Result
result, err = c.Call(msg, 10)
var response *Response
response, err = c.Call(msg, 10)
if err != nil {
return id, Error("client connect: unable to complete connect: %s", err)
}
if !result.IsResult() {
return id, Error("client connect: connect result unsuccessful: %#v", result)
if !response.IsResult() {
return id, Error("client connect: connect result unsuccessful: %#v", response)
}
obj, ok := result.Objects[1].(amf.Object)
obj, ok := response.Objects[1].(amf.Object)
if !ok {
return id, Error("client connect: unable to find connect response: %#v", result)
return id, Error("client connect: unable to find connect response: %#v", response)
}
if obj["code"] != "NetConnection.Connect.Success" {
return id, Error("client connect: connection was unsuccessful: %#v", result)
return id, Error("client connect: connection was unsuccessful: %#v", response)
}
id = obj["id"].(string)

View File

@@ -23,15 +23,15 @@ func (c *Client) routeLoop() {
}
func (c *Client) routeCommandMessage(msg *Message) {
result, err := msg.DecodeResult(&c.dec)
response, err := msg.DecodeResponse(&c.dec)
if err != nil {
log.Error("unable to decode message type %d on stream %d into command, discarding: %s", msg.Type, msg.ChunkStreamId, err)
return
}
tid := uint32(result.TransactionId)
tid := uint32(response.TransactionId)
c.resultsMutex.Lock()
c.results[tid] = result
c.resultsMutex.Unlock()
c.responsesMutex.Lock()
c.responses[tid] = response
c.responsesMutex.Unlock()
}

View File

@@ -24,46 +24,46 @@ func (m *Message) RemainingBytes() uint32 {
return m.Length - uint32(m.Buffer.Len())
}
func (m *Message) DecodeResult(dec *amf.Decoder) (result *Result, err error) {
result = new(Result)
func (m *Message) DecodeResponse(dec *amf.Decoder) (response *Response, err error) {
response = new(Response)
if m.ChunkStreamId != CHUNK_STREAM_ID_COMMAND {
return result, Error("message is not a command message")
return response, Error("message is not a command message")
}
switch m.Type {
case MESSAGE_TYPE_AMF3:
_, err = m.Buffer.ReadByte()
if err != nil {
return result, Error("unable to read first byte of amf3 message")
return response, Error("unable to read first byte of amf3 message")
}
fallthrough
case MESSAGE_TYPE_AMF0:
result.Name, err = dec.DecodeAmf0String(m.Buffer, true)
response.Name, err = dec.DecodeAmf0String(m.Buffer, true)
if err != nil {
return result, Error("unable to read command from amf message")
return response, Error("unable to read command from amf message")
}
result.TransactionId, err = dec.DecodeAmf0Number(m.Buffer, true)
response.TransactionId, err = dec.DecodeAmf0Number(m.Buffer, true)
if err != nil {
return result, Error("unable to read tid from amf message")
return response, Error("unable to read tid from amf message")
}
var obj interface{}
for m.Buffer.Len() > 0 {
obj, err = dec.Decode(m.Buffer, 0)
if err != nil {
return result, Error("unable to read object from amf message: %s", err)
return response, Error("unable to read object from amf message: %s", err)
}
result.Objects = append(result.Objects, obj)
response.Objects = append(response.Objects, obj)
}
default:
return result, Error("unable to decode message: %+v", m)
return response, Error("unable to decode message: %+v", m)
}
log.Debug("command decoded: %+v", result)
log.Debug("command decoded: %+v", response)
return result, err
return response, err
}

View File

@@ -4,34 +4,46 @@ import (
"github.com/elobuff/goamf"
)
type Result struct {
type Response struct {
Name string
TransactionId float64
Objects []interface{}
}
type ResultError struct {
type ResponseError struct {
Type string
ErrorCode string
Message string
Substitution string
}
func (r *Result) IsResult() bool {
func (r *Response) IsResult() bool {
return r.Name == "_result"
}
func (r *Result) IsError() bool {
func (r *Response) IsError() bool {
return r.Name == "_error"
}
func (r *Result) DecodeError() (result ResultError, err error) {
func (r *Response) DecodeBody() (result interface{}, err error) {
for _, obj := range r.Objects {
if tobj, ok := obj.(amf.TypedObject); ok == true {
if body := tobj.Object["body"]; body != nil {
return body, nil
}
}
}
return result, Error("Could not extract body")
}
func (r *Response) DecodeError() (result ResponseError, err error) {
for _, obj := range r.Objects {
if tobj, ok := obj.(amf.TypedObject); ok == true {
if tobj.Type == "flex.messaging.messages.ErrorMessage" {
if rc := tobj.Object["rootCause"]; rc != nil {
if rootCause, ok := rc.(amf.TypedObject); ok == true {
result = *new(ResultError)
result = *new(ResponseError)
result.Type = rootCause.Type
if tmp, ok := rootCause.Object["errorCode"].(string); ok {