diff --git a/client.go b/client.go index 32cf500..10d3b03 100644 --- a/client.go +++ b/client.go @@ -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) } } diff --git a/client_connect.go b/client_connect.go index 2f22be4..813494e 100644 --- a/client_connect.go +++ b/client_connect.go @@ -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) diff --git a/client_route.go b/client_route.go index 10b6d77..031a7e6 100644 --- a/client_route.go +++ b/client_route.go @@ -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() } diff --git a/message.go b/message.go index 31bb870..f23efa0 100644 --- a/message.go +++ b/message.go @@ -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 } diff --git a/result.go b/response.go similarity index 68% rename from result.go rename to response.go index c0ba861..32b6f5d 100644 --- a/result.go +++ b/response.go @@ -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 {