package nex import ( "errors" "fmt" ) // RMCRequest represets a RMC request type RMCRequest struct { protocolID uint8 customID uint16 callID uint32 methodID uint32 parameters []byte } // ProtocolID sets the RMC request protocolID func (request *RMCRequest) ProtocolID() uint8 { return request.protocolID } // CustomID returns the RMC request custom ID func (request *RMCRequest) CustomID() uint16 { return request.customID } // CallID sets the RMC request callID func (request *RMCRequest) CallID() uint32 { return request.callID } // MethodID sets the RMC request methodID func (request *RMCRequest) MethodID() uint32 { return request.methodID } // Parameters sets the RMC request parameters func (request *RMCRequest) Parameters() []byte { return request.parameters } // SetCustomID sets the RMC request custom ID func (request *RMCRequest) SetCustomID(customID uint16) { request.customID = customID } // SetProtocolID sets the RMC request protocol ID func (request *RMCRequest) SetProtocolID(protocolID uint8) { request.protocolID = protocolID } // SetCallID sets the RMC request call ID func (request *RMCRequest) SetCallID(callID uint32) { request.callID = callID } // SetMethodID sets the RMC request method ID func (request *RMCRequest) SetMethodID(methodID uint32) { request.methodID = methodID } // SetParameters sets the RMC request parameters func (request *RMCRequest) SetParameters(parameters []byte) { request.parameters = parameters } // NewRMCRequest returns a new blank RMCRequest func NewRMCRequest() RMCRequest { return RMCRequest{} } // FromBytes converts a byte slice into a RMCRequest func (request *RMCRequest) FromBytes(data []byte) error { if len(data) < 13 { return errors.New("[RMC] Data size less than minimum") } stream := NewStreamIn(data, nil) size, err := stream.ReadUInt32LE() if err != nil { return fmt.Errorf("Failed to read RMC Request size. %s", err.Error()) } if int(size) != (len(data) - 4) { return errors.New("RMC Request size does not match length of buffer") } protocolID, err := stream.ReadUInt8() if err != nil { return fmt.Errorf("Failed to read RMC Request protocol ID. %s", err.Error()) } request.SetProtocolID(protocolID ^ 0x80) if request.ProtocolID() == 0x7f { customID, err := stream.ReadUInt16LE() if err != nil { return fmt.Errorf("Failed to read RMC Request custom protocol ID. %s", err.Error()) } request.SetCustomID(customID) } callID, err := stream.ReadUInt32LE() if err != nil { return fmt.Errorf("Failed to read RMC Request call ID. %s", err.Error()) } request.SetCallID(callID) methodID, err := stream.ReadUInt32LE() if err != nil { return fmt.Errorf("Failed to read RMC Request method ID. %s", err.Error()) } request.SetMethodID(methodID) request.SetParameters(data[stream.ByteOffset():]) return nil } // Bytes converts a RMCRequest struct into a usable byte array func (request *RMCRequest) Bytes() []byte { body := NewStreamOut(nil) body.WriteUInt8(request.protocolID | 0x80) if request.protocolID == 0x7f { body.WriteUInt16LE(request.customID) } body.WriteUInt32LE(request.callID) body.WriteUInt32LE(request.methodID) if request.parameters != nil && len(request.parameters) > 0 { body.Grow(int64(len(request.parameters))) body.WriteBytesNext(request.parameters) } data := NewStreamOut(nil) data.WriteBuffer(body.Bytes()) return data.Bytes() } // RMCResponse represents a RMC response type RMCResponse struct { protocolID uint8 customID uint16 success uint8 callID uint32 methodID uint32 data []byte errorCode uint32 } // CustomID returns the RMC response customID func (response *RMCResponse) CustomID() uint16 { return response.customID } // SetCustomID sets the RMC response customID func (response *RMCResponse) SetCustomID(customID uint16) { response.customID = customID } // SetSuccess sets the RMCResponse payload to an instance of RMCSuccess func (response *RMCResponse) SetSuccess(methodID uint32, data []byte) { response.success = 1 response.methodID = methodID response.data = data } // SetError sets the RMCResponse payload to an instance of RMCError func (response *RMCResponse) SetError(errorCode uint32) { if int(errorCode)&errorMask == 0 { errorCode = uint32(int(errorCode) | errorMask) } response.success = 0 response.errorCode = errorCode } // Bytes converts a RMCResponse struct into a usable byte array func (response *RMCResponse) Bytes() []byte { body := NewStreamOut(nil) if response.protocolID > 0 { body.WriteUInt8(response.protocolID) if response.protocolID == 0x7f { body.WriteUInt16LE(response.customID) } } body.WriteUInt8(response.success) if response.success == 1 { body.WriteUInt32LE(response.callID) body.WriteUInt32LE(response.methodID | 0x8000) if response.data != nil && len(response.data) > 0 { body.Grow(int64(len(response.data))) body.WriteBytesNext(response.data) } } else { body.WriteUInt32LE(response.errorCode) body.WriteUInt32LE(response.callID) } data := NewStreamOut(nil) data.WriteBuffer(body.Bytes()) return data.Bytes() } // NewRMCResponse returns a new RMCResponse func NewRMCResponse(protocolID uint8, callID uint32) RMCResponse { response := RMCResponse{ protocolID: protocolID, callID: callID, } return response }