agent/wsclient/decode.go
func DecodeData(data []byte, dec TypeDecoder) (interface{}, string, error) {
	raw := &ReceivedMessage{}
	// Delay unmarshal until we know the type
	err := json.Unmarshal(data, raw)
	if err != nil || raw.Type == "" {
		// Unframed messages can be of the {"Type":"Message"} form as well, try
		// that.
		connErr, connErrType, decodeErr := DecodeConnectionError(data, dec)
		if decodeErr == nil && connErrType != "" {
			return connErr, connErrType, nil
		}
		return nil, "", decodeErr
	}

	reqMessage, ok := dec.NewOfType(raw.Type)
	if !ok {
		return nil, raw.Type, &UnrecognizedWSRequestType{raw.Type}
	}
	err = jsonutil.UnmarshalJSON(reqMessage, bytes.NewReader(raw.Message))
	return reqMessage, raw.Type, err
}
func DecodeData(data []byte, dec TypeDecoder) (interface{}, string, error) {
	raw := &ReceivedMessage{}
	// Delay unmarshal until we know the type
	err := json.Unmarshal(data, raw)
	if err != nil || raw.Type == "" {
		// Unframed messages can be of the {"Type":"Message"} form as well, try
		// that.
		connErr, connErrType, decodeErr := DecodeConnectionError(data, dec)
		if decodeErr == nil && connErrType != "" {
			return connErr, connErrType, nil
		}
		return nil, "", decodeErr
	}

	reqMessage, ok := dec.NewOfType(raw.Type)
	if !ok {
		return nil, raw.Type, &UnrecognizedWSRequestType{raw.Type}
	}
	err = jsonutil.UnmarshalJSON(reqMessage, bytes.NewReader(raw.Message))
	return reqMessage, raw.Type, err
}
// DecodeData decodes a raw message into its type. E.g. An ACS message of the
// form {"type":"FooMessage","message":{"foo":1}} will be decoded into the
// corresponding *ecsacs.FooMessage type. The type string, "FooMessage", will
// also be returned as a convenience.