-
Notifications
You must be signed in to change notification settings - Fork 39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Expose indications and notifications in the att layer #267
Conversation
6e925ba
to
530434b
Compare
Hmm, yeah. Maybe merging AttReq and AttRsp into Att is the way? Requires changing the variant names to something more in line with the name of the constant then perhaps.
The AttRsp was kind of a bolt-on for supporting gatt clients. I agree they should probably use the same. I think perhaps it's easier to fix now.
I haven't really thought through the consequences of exposing it, but I guess it's ok with the caveat that maybe we will need to refactor/break this in the future. I'd be interested to know you have to use a 'hybrid' of the attribute server and the 'raw' request handling, is there something we can fix in the attribute server perhaps so that you wouldn't need the low level access? |
Sounds like a good idea! Let me quickly prototype this.
Shall I also do this?
I think if we get to refactor the |
I would really appreciate if it was documented before we made it public, which is the reason I've not made it public yet. I'm happy to do that, but you might have to wait a little with merging this until that is done as it's not a high priority task for me right now.
No objections here, just as a warning if you're going to rely on it :) |
Unifying But. There is one single place I'm not sure how to handle, here: Line 404 in 0950a9c
Any suggestions? If that's not clear, the question is a bit, shall we just trigger a |
Here's how it would look after the unification, except for that one pesky problem from above ^^^: |
I think that would break devices that operate as both gatt client and gatt server on the same connection, so I think for now it's probably best to add some method on the Att type to check if it's a request or response (I think you can just check for request code being an odd/even number) and dispatch to either channel based on that. GattClient is probably due for a refactoring but it's better to do that later I think. |
@lulf Sorry for the delay. I have updated the "single Att" branch (main...ivmarkov:trouble:single-att) with comments and with your suggested method that differentiates between client->server PDUs and server->client PDUs. However, and after reading this (Section 3.3 to be precise), I think another option is to keep the current "Att Req/Rsp" dichotomy but maybe extend it a bit. First of all, the
So this opens the door for two additional models (besides the "lets lump everything into a single Att enum" as I did in the above branch):
"Option 2" would allow us to have a correct type for the new So, which one should it be?
|
I have now updated this PR to actually implement "Option 2" as I felt this is the most correct path we should take. |
0531f13
to
ac60c09
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, just a few comments around the error handling. I agree with going for option 2. Thanks for documenting as well!
host/src/gatt.rs
Outdated
let Att::Client(client) = att else { | ||
unreachable!(); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Somehow feels better to do a panic!() with a descriptive message here, or change signature to Result<AttClient<'_>, Error> and appropriate error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- I don't think we should change the API to be fallible, because at this place, it is impossible to get anything but
Att::Client
. This is enforced by this code inhost.rs
which posts into the connection event queue:
#[cfg(feature = "gatt")]
match a {
/// !!! This branch specifically !!!
Ok(att::Att::Client(_)) => {
let event = ConnectionEventData::Gatt {
data: Pdu::new(packet, header.length as usize),
};
self.connections.post_handle_event(acl.handle(), event)?;
}
Ok(att::Att::Server(_)) => {
if let Err(e) = self
.att_client
.try_send((acl.handle(), Pdu::new(packet, header.length as usize)))
{
return Err(Error::OutOfMemory);
}
}
Err(e) => {
warn!("Error decoding attribute payload: {:?}", e);
}
}
Also, your comment // We know it has been checked, therefore this cannot fail
in fact asserts exactly that (and the fact that the PDU has a valid format and can be decoded). It is just that in the past AttReq
also had a public decode
method, so the match
+unreachable!()
was not necessary. After my changes, only Att
has a decode
method (and I somehow believe this is cleaner), hence the additional unreachable.
- As for replacing
panic!
withunreachable!
, an informal definition ofunreachable!
is given here. So I think it should beunreachable!
rather than apanic!
. Putting a message insideunreachable!
is no prob though, I'll do that shortly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lulf I've now documented the unreachable!
statements more heavily, and I've put an error message inside unreachable!
, if you can look again.
host/src/gatt.rs
Outdated
let Att::Client(att) = att else { | ||
unreachable!(); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as earlier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See above - I'll put something in the unreachable!()
5edf097
to
5933e19
Compare
5933e19
to
35316a3
Compare
@lulf Anything else to do here or would you say it is ready? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks for explaining the unreachable thing, I think it's ok.
/test |
Is this a flaky test or did I manage to regress something? |
/test |
Looks like some interference causing a disconnect. Retry seems to pass. Adjusting supervision timeouts etc. might improve stability, but this is the first time I've seen this one so can be fixed later. |
It just boils down to extending
AttReq
andAttRsp
with some additional variants. NOTE: The attribute server is not (yet) updated to handle these - this should be a separate future PR, but this extension allows folks working with theatt
layer directly (or directly and then in a combination with the attribute server - quite possible!) to use these.Possible topics of contention:
Notify
andIndicate
should be part ofAttRsp
(whileConfirmIndication
is also weirdly part ofAttReq
), as they are - strictly speaking - not a "response" to anything. The problem is this line of code which pretty much forces us to model these as "responses". On the other hand, we can still claim they are responses, yet - unsolicited (SeeGattData::reply_unsolicited
.)GattData::reply_unsolicited
. By the way the Gatt server is not really using theAttRsp
enum and is doing its own encoding; we should probably fix this in future#[allow(missing_docs)] // Temporary
on top of the now-publicatt module
. I'm also OK with commenting the module with a subsequent commit in this PR, but did not want the (small amount of) changes to be lost in the docu noisecccd_handle
to be public for my hybrid use of lower level att and higher level attribute server utilization and I made it so. Nothing wrong with that I hope?