Commit f9817fae authored by Kevin Seidel's avatar Kevin Seidel
Browse files

Merge branch 'att-server-prepare-then-execute-write-request' of https://github.com/chenkaie/ble

parents 34e0308d 04bd0327
......@@ -15,8 +15,8 @@ This package implement Attribute Protocol (ATT) [Vol 3, Part F]
- [x] Write Request [3.4.5.1 & 3.4.5.2]
- [x] Write Command [3.4.5.3]
- [ ] Signed Write Command [3.4.5.4]
- [ ] Prepare Write Request [3.4.6.1 & 3.4.6.2]
- [ ] Execute Write Request [3.4.6.3]
- [x] Prepare Write Request [3.4.6.1 & 3.4.6.2]
- [x] Execute Write Request [3.4.6.3]
- [x] Handle Value Notification [3.4.7.1]
- [x] Handle Value Indication [3.4.7.2 & 3.4.7.3]
......
......@@ -32,6 +32,10 @@ type Server struct {
chConfirm chan bool
dummyRspWriter ble.ResponseWriter
// Store a write handler for defer execute once receving ExecuteWriteRequest
prepareWriteRequestAttr *attr
prepareWriteRequestData bytes.Buffer
}
// NewServer returns an ATT (Attribute Protocol) server.
......@@ -191,9 +195,11 @@ func (s *Server) handleRequest(b []byte) []byte {
resp = s.handleWriteRequest(b)
case WriteCommandCode:
s.handleWriteCommand(b)
case PrepareWriteRequestCode:
resp = s.handlePrepareWriteRequest(b)
case ExecuteWriteRequestCode:
resp = s.handleExecuteWriteRequest(b)
case ReadMultipleRequestCode,
PrepareWriteRequestCode,
ExecuteWriteRequestCode,
SignedWriteCommandCode:
fallthrough
default:
......@@ -304,7 +310,7 @@ func (s *Server) handleFindByTypeValueRequest(r FindByTypeValueRequest) []byte {
// Since ResponseWriter caps the value at the capacity,
// we allocate one extra byte, and the written length.
buf2 := bytes.NewBuffer(make([]byte, 0, len(s.txBuf)-7+1))
e := handleATT(a, s.conn, r, ble.NewResponseWriter(buf2))
e := handleATT(a, s, r, ble.NewResponseWriter(buf2))
if e != ble.ErrSuccess || buf2.Len() > len(s.txBuf)-7 {
return newErrorResponse(r.AttributeOpcode(), r.StartingHandle(), ble.ErrInvalidHandle)
}
......@@ -352,7 +358,7 @@ func (s *Server) handleReadByTypeRequest(r ReadByTypeRequest) []byte {
v := a.v
if v == nil {
buf2 := bytes.NewBuffer(make([]byte, 0, len(s.txBuf)-2))
if e := handleATT(a, s.conn, r, ble.NewResponseWriter(buf2)); e != ble.ErrSuccess {
if e := handleATT(a, s, r, ble.NewResponseWriter(buf2)); e != ble.ErrSuccess {
// Return if the first value read cause an error.
if dlen == 0 {
return newErrorResponse(r.AttributeOpcode(), r.StartingHandle(), e)
......@@ -414,7 +420,7 @@ func (s *Server) handleReadRequest(r ReadRequest) []byte {
// Pass the request to upper layer with the ResponseWriter, which caps
// the buffer to a valid length of payload.
if e := handleATT(a, s.conn, r, ble.NewResponseWriter(buf)); e != ble.ErrSuccess {
if e := handleATT(a, s, r, ble.NewResponseWriter(buf)); e != ble.ErrSuccess {
return newErrorResponse(r.AttributeOpcode(), r.AttributeHandle(), e)
}
return rsp[:1+buf.Len()]
......@@ -446,7 +452,7 @@ func (s *Server) handleReadBlobRequest(r ReadBlobRequest) []byte {
// Pass the request to upper layer with the ResponseWriter, which caps
// the buffer to a valid length of payload.
if e := handleATT(a, s.conn, r, ble.NewResponseWriter(buf)); e != ble.ErrSuccess {
if e := handleATT(a, s, r, ble.NewResponseWriter(buf)); e != ble.ErrSuccess {
return newErrorResponse(r.AttributeOpcode(), r.AttributeHandle(), e)
}
return rsp[:1+buf.Len()]
......@@ -472,7 +478,7 @@ func (s *Server) handleReadByGroupRequest(r ReadByGroupTypeRequest) []byte {
v := a.v
if v == nil {
buf2 := bytes.NewBuffer(make([]byte, buf.Cap()-buf.Len()-4))
if e := handleATT(a, s.conn, r, ble.NewResponseWriter(buf2)); e != ble.ErrSuccess {
if e := handleATT(a, s, r, ble.NewResponseWriter(buf2)); e != ble.ErrSuccess {
return newErrorResponse(r.AttributeOpcode(), r.StartingHandle(), e)
}
v = buf2.Bytes()
......@@ -520,12 +526,62 @@ func (s *Server) handleWriteRequest(r WriteRequest) []byte {
if a == nil {
return newErrorResponse(r.AttributeOpcode(), r.AttributeHandle(), ble.ErrWriteNotPerm)
}
if e := handleATT(a, s.conn, r, ble.NewResponseWriter(nil)); e != ble.ErrSuccess {
if e := handleATT(a, s, r, ble.NewResponseWriter(nil)); e != ble.ErrSuccess {
return newErrorResponse(r.AttributeOpcode(), r.AttributeHandle(), e)
}
return []byte{WriteResponseCode}
}
func (s *Server) handlePrepareWriteRequest(r PrepareWriteRequest) []byte {
logger.Debug("handlePrepareWriteRequest ->", "r.AttributeHandle", r.AttributeHandle())
// Validate the request.
switch {
case len(r) < 3:
return newErrorResponse(r.AttributeOpcode(), 0x0000, ble.ErrInvalidPDU)
}
a, ok := s.db.at(r.AttributeHandle())
if !ok {
return newErrorResponse(r.AttributeOpcode(), r.AttributeHandle(), ble.ErrInvalidHandle)
}
// We don't support write to static value. Pass the request to upper layer.
if a == nil {
return newErrorResponse(r.AttributeOpcode(), r.AttributeHandle(), ble.ErrWriteNotPerm)
}
if e := handleATT(a, s, r, ble.NewResponseWriter(nil)); e != ble.ErrSuccess {
return newErrorResponse(r.AttributeOpcode(), r.AttributeHandle(), e)
}
// Convert and validate the response.
rsp := PrepareWriteResponse(r)
rsp.SetAttributeOpcode()
return rsp
}
func (s *Server) handleExecuteWriteRequest(r ExecuteWriteRequest) []byte {
// Validate the request.
switch {
case len(r) < 2:
return newErrorResponse(r.AttributeOpcode(), 0x0000, ble.ErrInvalidPDU)
}
switch r.Flags() {
case 0:
// 0x00 – Cancel all prepared writes
s.prepareWriteRequestAttr = nil
case 1:
// 0x01 – Immediately write all pending prepared values
a := s.prepareWriteRequestAttr
if e := handleATT(a, s, r, ble.NewResponseWriter(nil)); e != ble.ErrSuccess {
return newErrorResponse(r.AttributeOpcode(), 0, e)
}
}
return []byte{ExecuteWriteResponseCode}
}
// handle Write command. [Vol 3, Part F, 3.4.5.3]
func (s *Server) handleWriteCommand(r WriteCommand) []byte {
// Validate the request.
......@@ -543,7 +599,7 @@ func (s *Server) handleWriteCommand(r WriteCommand) []byte {
if a == nil {
return nil
}
if e := handleATT(a, s.conn, r, s.dummyRspWriter); e != ble.ErrSuccess {
if e := handleATT(a, s, r, s.dummyRspWriter); e != ble.ErrSuccess {
return nil
}
return nil
......@@ -558,10 +614,11 @@ func newErrorResponse(op byte, h uint16, s ble.ATTError) []byte {
return r
}
func handleATT(a *attr, conn ble.Conn, req []byte, rsp ble.ResponseWriter) ble.ATTError {
func handleATT(a *attr, s *Server, req []byte, rsp ble.ResponseWriter) ble.ATTError {
rsp.SetStatus(ble.ErrSuccess)
var offset int
var data []byte
conn := s.conn
switch req[0] {
case ReadByTypeRequestCode:
fallthrough
......@@ -576,6 +633,27 @@ func handleATT(a *attr, conn ble.Conn, req []byte, rsp ble.ResponseWriter) ble.A
}
offset = int(ReadBlobRequest(req).ValueOffset())
a.rh.ServeRead(ble.NewRequest(conn, data, offset), rsp)
case PrepareWriteRequestCode:
if a.wh == nil {
return ble.ErrWriteNotPerm
}
data = PrepareWriteRequest(req).PartAttributeValue()
logger.Debug("handleATT", "PartAttributeValue",
fmt.Sprintf("data: %x, offset: %d, %p\n", data, int(PrepareWriteRequest(req).ValueOffset()), s.prepareWriteRequestAttr))
if s.prepareWriteRequestAttr == nil {
s.prepareWriteRequestAttr = a
s.prepareWriteRequestData.Reset()
}
s.prepareWriteRequestData.Write(data)
case ExecuteWriteRequestCode:
if a.wh == nil {
return ble.ErrWriteNotPerm
}
data = s.prepareWriteRequestData.Bytes()
a.wh.ServeWrite(ble.NewRequest(conn, data, offset), rsp)
s.prepareWriteRequestAttr = nil
case WriteRequestCode:
fallthrough
case WriteCommandCode:
......@@ -584,8 +662,6 @@ func handleATT(a *attr, conn ble.Conn, req []byte, rsp ble.ResponseWriter) ble.A
}
data = WriteRequest(req).AttributeValue()
a.wh.ServeWrite(ble.NewRequest(conn, data, offset), rsp)
// case PrepareWriteRequestCode:
// case ExecuteWriteRequestCode:
// case SignedWriteCommandCode:
// case ReadByGroupTypeRequestCode:
// case ReadMultipleRequestCode:
......
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