Unverified Commit 7370f1c5 authored by Kevin's avatar Kevin Committed by GitHub
Browse files

Refinement (#19)

* Simplify uuid.Reverse method

* Add uuid test

* Fix linting issues
parent 721d2405
......@@ -25,7 +25,7 @@ func (r *DB) idx(h int) int {
if h < int(r.base) {
return tooSmall
}
if int(h) >= int(r.base)+len(r.attrs) {
if h >= int(r.base)+len(r.attrs) {
return tooLarge
}
return h - int(r.base)
......
......@@ -302,7 +302,7 @@ func (s *Server) handleFindByTypeValueRequest(r FindByTypeValueRequest) []byte {
for _, a := range s.db.subrange(r.StartingHandle(), r.EndingHandle()) {
v, starth, endh := a.v, a.h, a.endh
if !(ble.UUID(a.typ).Equal(ble.UUID16(r.AttributeType()))) {
if !a.typ.Equal(ble.UUID16(r.AttributeType())) {
continue
}
if v == nil {
......
......@@ -33,9 +33,6 @@ type Conn struct {
txMTU int
rxMPS int
// leFrame is set to be true when the LE Credit based flow control is used.
leFrame bool
// Signaling MTUs are The maximum size of command information that the
// L2CAP layer entity is capable of accepting.
// A L2CAP implementations supporting LE-U should support at least 23 bytes.
......@@ -47,23 +44,25 @@ type Conn struct {
sigRxMTU int
sigTxMTU int
// sigID is used to match responses with signaling requests.
// The requesting device sets this field and the responding device uses the
// same value in its response. Within each signalling channel a different
// Identifier shall be used for each successive command. [Vol 3, Part A, 4]
sigID uint8
sigSent chan []byte
smpSent chan []byte
// smpSent chan []byte
chInPkt chan packet
chInPDU chan pdu
chDone chan struct{}
// Host to Controller Data Flow Control pkt-based Data flow control for LE-U [Vol 2, Part E, 4.1.1]
// chSentBufs tracks the HCI buffer occupied by this connection.
txBuffer *Client
chDone chan struct{}
// sigID is used to match responses with signaling requests.
// The requesting device sets this field and the responding device uses the
// same value in its response. Within each signalling channel a different
// Identifier shall be used for each successive command. [Vol 3, Part A, 4]
sigID uint8
// leFrame is set to be true when the LE Credit based flow control is used.
leFrame bool
}
func newConn(h *HCI, param evt.LEConnectionComplete) *Conn {
......@@ -94,7 +93,7 @@ func newConn(h *HCI, param evt.LEConnectionComplete) *Conn {
if err != io.EOF {
// TODO: wrap and pass the error up.
// err := errors.Wrap(err, "recombine failed")
logger.Error("recombine failed: ", "err", err)
_ = logger.Error("recombine failed: ", "err", err)
}
close(c.chInPDU)
return
......@@ -140,7 +139,7 @@ func (c *Conn) Read(sdu []byte) (n int, err error) {
buf.Write(data)
for buf.Len() < slen {
p := <-c.chInPDU
buf.Write(pdu(p).payload())
buf.Write(p.payload())
}
return slen, nil
}
......@@ -205,10 +204,23 @@ func (c *Conn) writePDU(pdu []byte) (int, error) {
}
// Prepare the Headers
binary.Write(pkt, binary.LittleEndian, uint8(pktTypeACLData)) // HCI Header: pkt Type
binary.Write(pkt, binary.LittleEndian, uint16(c.param.ConnectionHandle()|(flags<<8))) // ACL Header: handle and flags
binary.Write(pkt, binary.LittleEndian, uint16(flen)) // ACL Header: data len
binary.Write(pkt, binary.LittleEndian, pdu[:flen]) // Append payload
// HCI Header: pkt Type
if err := binary.Write(pkt, binary.LittleEndian, pktTypeACLData); err != nil {
return 0, err
}
// ACL Header: handle and flags
if err := binary.Write(pkt, binary.LittleEndian, c.param.ConnectionHandle()|(flags<<8)); err != nil {
return 0, err
}
// ACL Header: data len
if err := binary.Write(pkt, binary.LittleEndian, uint16(flen)); err != nil {
return 0, err
}
// Append payload
if err := binary.Write(pkt, binary.LittleEndian, pdu[:flen]); err != nil {
return 0, err
}
// Flush the pkt to HCI
select {
......
......@@ -278,7 +278,7 @@ func (h *HCI) sktLoop() {
// Some bluetooth devices may append vendor specific packets at the last,
// in this case, simply ignore them.
if strings.HasPrefix(err.Error(), "unsupported vendor packet:") {
logger.Error("skt: %v", err)
_ = logger.Error("skt: %v", err)
} else {
h.err = fmt.Errorf("skt: %v", err)
return
......@@ -317,7 +317,7 @@ func (h *HCI) handleACL(b []byte) error {
c, ok := h.conns[handle]
h.muConns.Unlock()
if !ok {
logger.Warn("invalid connection handle on ACL packet", "handle", handle)
_ = logger.Warn("invalid connection handle on ACL packet", "handle", handle)
return nil
}
c.chInPkt <- b
......
......@@ -13,7 +13,7 @@ import (
// Signal ...
type Signal interface {
Code() int
Marshal() []byte
Marshal() ([]byte, error)
Unmarshal([]byte) error
}
......@@ -26,15 +26,30 @@ func (s sigCmd) data() []byte { return s[4 : 4+s.len()] }
// Signal ...
func (c *Conn) Signal(req Signal, rsp Signal) error {
data := req.Marshal()
data, err := req.Marshal()
if err != nil {
return err
}
buf := bytes.NewBuffer(make([]byte, 0))
binary.Write(buf, binary.LittleEndian, uint16(4+len(data)))
binary.Write(buf, binary.LittleEndian, uint16(cidLESignal))
if err := binary.Write(buf, binary.LittleEndian, uint16(4+len(data))); err != nil {
return err
}
if err := binary.Write(buf, binary.LittleEndian, cidLESignal); err != nil {
return err
}
binary.Write(buf, binary.LittleEndian, uint8(req.Code()))
binary.Write(buf, binary.LittleEndian, uint8(c.sigID))
binary.Write(buf, binary.LittleEndian, uint16(len(data)))
binary.Write(buf, binary.LittleEndian, data)
if err := binary.Write(buf, binary.LittleEndian, uint8(req.Code())); err != nil {
return err
}
if err := binary.Write(buf, binary.LittleEndian, uint8(c.sigID)); err != nil {
return err
}
if err := binary.Write(buf, binary.LittleEndian, uint16(len(data))); err != nil {
return err
}
if err := binary.Write(buf, binary.LittleEndian, data); err != nil {
return err
}
c.sigSent = make(chan []byte)
defer close(c.sigSent)
......@@ -63,13 +78,26 @@ func (c *Conn) Signal(req Signal, rsp Signal) error {
}
func (c *Conn) sendResponse(code uint8, id uint8, r Signal) (int, error) {
data := r.Marshal()
data, err := r.Marshal()
if err != nil {
return 0, err
}
buf := bytes.NewBuffer(make([]byte, 0))
binary.Write(buf, binary.LittleEndian, uint16(4+len(data)))
binary.Write(buf, binary.LittleEndian, uint16(cidLESignal))
binary.Write(buf, binary.LittleEndian, uint8(code))
binary.Write(buf, binary.LittleEndian, uint8(id))
binary.Write(buf, binary.LittleEndian, uint16(len(data)))
if err := binary.Write(buf, binary.LittleEndian, uint16(4+len(data))); err != nil {
return 0, err
}
if err := binary.Write(buf, binary.LittleEndian, cidLESignal); err != nil {
return 0, err
}
if err := binary.Write(buf, binary.LittleEndian, code); err != nil {
return 0, err
}
if err := binary.Write(buf, binary.LittleEndian, id); err != nil {
return 0, err
}
if err := binary.Write(buf, binary.LittleEndian, uint16(len(data))); err != nil {
return 0, err
}
if err := binary.Write(buf, binary.LittleEndian, data); err != nil {
return 0, err
}
......@@ -85,13 +113,16 @@ func (c *Conn) handleSignal(p pdu) error {
// command in the L2CAP packet. If only Responses are recognized, the packet
// shall be silently discarded. [Vol3, Part A, 4.1]
if p.dlen() > c.sigRxMTU {
c.sendResponse(
_, err := c.sendResponse(
SignalCommandReject,
sigCmd(p.payload()).id(),
&CommandReject{
Reason: 0x0001, // Signaling MTU exceeded.
Data: []byte{uint8(c.sigRxMTU), uint8(c.sigRxMTU >> 8)}, // Actual MTUsig.
})
if err != nil {
_ = logger.Error("send repsonse", fmt.Sprintf("%v", err))
}
return nil
}
......
......@@ -18,10 +18,12 @@ type CommandReject struct {
func (s CommandReject) Code() int { return 0x01 }
// Marshal serializes the command parameters into binary form.
func (s *CommandReject) Marshal() []byte {
func (s *CommandReject) Marshal() ([]byte, error) {
buf := bytes.NewBuffer(make([]byte, 0))
binary.Write(buf, binary.LittleEndian, s)
return buf.Bytes()
if err := binary.Write(buf, binary.LittleEndian, s); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// Unmarshal de-serializes the binary data and stores the result in the receiver.
......@@ -42,10 +44,12 @@ type DisconnectRequest struct {
func (s DisconnectRequest) Code() int { return 0x06 }
// Marshal serializes the command parameters into binary form.
func (s *DisconnectRequest) Marshal() []byte {
func (s *DisconnectRequest) Marshal() ([]byte, error) {
buf := bytes.NewBuffer(make([]byte, 0))
binary.Write(buf, binary.LittleEndian, s)
return buf.Bytes()
if err := binary.Write(buf, binary.LittleEndian, s); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// Unmarshal de-serializes the binary data and stores the result in the receiver.
......@@ -66,10 +70,12 @@ type DisconnectResponse struct {
func (s DisconnectResponse) Code() int { return 0x07 }
// Marshal serializes the command parameters into binary form.
func (s *DisconnectResponse) Marshal() []byte {
func (s *DisconnectResponse) Marshal() ([]byte, error) {
buf := bytes.NewBuffer(make([]byte, 0))
binary.Write(buf, binary.LittleEndian, s)
return buf.Bytes()
if err := binary.Write(buf, binary.LittleEndian, s); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// Unmarshal de-serializes the binary data and stores the result in the receiver.
......@@ -92,10 +98,12 @@ type ConnectionParameterUpdateRequest struct {
func (s ConnectionParameterUpdateRequest) Code() int { return 0x12 }
// Marshal serializes the command parameters into binary form.
func (s *ConnectionParameterUpdateRequest) Marshal() []byte {
func (s *ConnectionParameterUpdateRequest) Marshal() ([]byte, error) {
buf := bytes.NewBuffer(make([]byte, 0))
binary.Write(buf, binary.LittleEndian, s)
return buf.Bytes()
if err := binary.Write(buf, binary.LittleEndian, s); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// Unmarshal de-serializes the binary data and stores the result in the receiver.
......@@ -115,10 +123,12 @@ type ConnectionParameterUpdateResponse struct {
func (s ConnectionParameterUpdateResponse) Code() int { return 0x13 }
// Marshal serializes the command parameters into binary form.
func (s *ConnectionParameterUpdateResponse) Marshal() []byte {
func (s *ConnectionParameterUpdateResponse) Marshal() ([]byte, error) {
buf := bytes.NewBuffer(make([]byte, 0))
binary.Write(buf, binary.LittleEndian, s)
return buf.Bytes()
if err := binary.Write(buf, binary.LittleEndian, s); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// Unmarshal de-serializes the binary data and stores the result in the receiver.
......@@ -142,10 +152,12 @@ type LECreditBasedConnectionRequest struct {
func (s LECreditBasedConnectionRequest) Code() int { return 0x14 }
// Marshal serializes the command parameters into binary form.
func (s *LECreditBasedConnectionRequest) Marshal() []byte {
func (s *LECreditBasedConnectionRequest) Marshal() ([]byte, error) {
buf := bytes.NewBuffer(make([]byte, 0))
binary.Write(buf, binary.LittleEndian, s)
return buf.Bytes()
if err := binary.Write(buf, binary.LittleEndian, s); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// Unmarshal de-serializes the binary data and stores the result in the receiver.
......@@ -169,10 +181,12 @@ type LECreditBasedConnectionResponse struct {
func (s LECreditBasedConnectionResponse) Code() int { return 0x15 }
// Marshal serializes the command parameters into binary form.
func (s *LECreditBasedConnectionResponse) Marshal() []byte {
func (s *LECreditBasedConnectionResponse) Marshal() ([]byte, error) {
buf := bytes.NewBuffer(make([]byte, 0))
binary.Write(buf, binary.LittleEndian, s)
return buf.Bytes()
if err := binary.Write(buf, binary.LittleEndian, s); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// Unmarshal de-serializes the binary data and stores the result in the receiver.
......@@ -193,10 +207,12 @@ type LEFlowControlCredit struct {
func (s LEFlowControlCredit) Code() int { return 0x16 }
// Marshal serializes the command parameters into binary form.
func (s *LEFlowControlCredit) Marshal() []byte {
func (s *LEFlowControlCredit) Marshal() ([]byte, error) {
buf := bytes.NewBuffer(make([]byte, 0))
binary.Write(buf, binary.LittleEndian, s)
return buf.Bytes()
if err := binary.Write(buf, binary.LittleEndian, s); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// Unmarshal de-serializes the binary data and stores the result in the receiver.
......
......@@ -25,9 +25,15 @@ const (
func (c *Conn) sendSMP(p pdu) error {
buf := bytes.NewBuffer(make([]byte, 0))
binary.Write(buf, binary.LittleEndian, uint16(4+len(p)))
binary.Write(buf, binary.LittleEndian, cidSMP)
binary.Write(buf, binary.LittleEndian, p)
if err := binary.Write(buf, binary.LittleEndian, uint16(4+len(p))); err != nil {
return err
}
if err := binary.Write(buf, binary.LittleEndian, cidSMP); err != nil {
return err
}
if err := binary.Write(buf, binary.LittleEndian, p); err != nil {
return err
}
_, err := c.writePDU(buf.Bytes())
logger.Debug("smp", "send", fmt.Sprintf("[%X]", buf.Bytes()))
return err
......
......@@ -84,15 +84,13 @@ func Contains(s []UUID, u UUID) bool {
// Reverse returns a reversed copy of u.
func Reverse(u []byte) []byte {
// Special-case 16 bit UUIDS for speed.
l := len(u)
if l == 2 {
return []byte{u[1], u[0]}
}
b := make([]byte, l)
for i := 0; i < l/2+1; i++ {
b[i], b[l-i-1] = u[l-i-1], u[i]
for i := 0; i < l; i++ {
b[l-i-1] = u[i]
}
return b
}
......
package ble
import (
"bytes"
"testing"
)
var forward = [][]byte{
[]byte{1, 2, 3, 4, 5, 6},
[]byte{12, 143, 231, 123, 87, 124, 209},
[]byte{3, 43, 223, 12, 54},
}
var reverse = [][]byte{
[]byte{6, 5, 4, 3, 2, 1},
[]byte{209, 124, 87, 123, 231, 143, 12},
[]byte{54, 12, 223, 43, 3},
}
func TestReverse(t *testing.T) {
for i := 0; i < len(forward); i++ {
r := Reverse(forward[i])
if !bytes.Equal(r, reverse[i]) {
t.Errorf("Error: %v in reverse should be %v, but is: %v", forward[i], reverse[i], r)
}
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment