Conversation
|
Sample implementation: zxzxwu/bumble#1 |
|
I like your direction 👍 I had things to do today, let me review that tomorrow |
There was a problem hiding this comment.
I was thinking about something like this:
service L2CAP {
rpc Open(OpenRequest) returns (OpenResponse);
rpc WaitOpen(OpenRequest) returns (stream OpenResponse);
rpc Close(Channel) returns (CloseResponse);
rpc WaitClose(Channel) returns (CloseResponse);
rpc Receive(Channel) returns (stream bytes);
rpc Send(SendRequest) returns (SendResponse);
}
message Channel {
google.protobuf.Any cookie = 1;
}
message OpenRequest {
Connection connection = 1;
oneof type {
// Fixed channel identifier (returns a fixed channel).
uint16 cid = 2; // provide some constants ?
// Protocol/Service Multiplexer (returns a dynamic channel).
uint16 psm = 3; // provide some constants ?
}
// Maximum transmission unit.
// Shall not be set for fixed channels.
uint16 mtu = 4;
// Maximum PDU payload size.
// Shall not be set for fixed channels.
// Required for dynamic channels over LE.
// For BR/EDR connections, if set (and supported by the host), a credits based channel is opened.
uint16 mps = 5;
}
message OpenResponse {
oneof result {
int8 error = 1; // enum ?
Channel channel = 2;
}
}
message CloseResponse {
oneof result {
int8 error = 1; // enum ?
google.protobuf.Empty success = 2;
}
}
message SendRequest {
Channel channel = 1;
bytes data = 2;
}
message SendResponse {
oneof result {
int8 error = 1; // enum ?
google.protobuf.Empty success = 2;
}
}What do you think ?
I also considered whether we should use a socket-like API set. The reason I choose callback style is that:
|
It's true for the queue (by channel), but not really a big deal I think. Also it will better align on other services like A2dp.
I was seeing the disconnect as the end of the receive stream or as an error on the send, do we really need a specific event ? |
|
Right, so it should still be better to have a synchronized model. I will propose another version tomorrow. |
uael
left a comment
There was a problem hiding this comment.
I have a couple of questions:
- I there a requirements to wait for a server at the device level instead of the connection level ? To avoid the
Transportenum. - Don't we want to provide a way to open credits based channel for BR/EDR ?
- Is there a reason to not expose error handling ?
- I there a requirements to expose dynamic PSM allocation ? There might be one, but in that case we need the SDP service in order to expose it to the remote.
Also, I prefer to keep a naming close to the other services.
I propose you to start from the bellow version instead, and then to iterate over it:
service L2CAP {
rpc Connect(ConnectRequest) returns (ConnectResponse);
rpc WaitConnection(WaitConnectionRequest) returns (stream WaitConnectionResponse);
rpc Disconnect(DisconnectRequest) returns (DisconnectResponse);
rpc WaitDisconnection(WaitDisconnectionRequest) returns (WaitDisconnectionResponse);
rpc Receive(ReceiveRequest) returns (stream ReceiveResponse);
rpc Send(SendRequest) returns (SendResponse);
}
message Channel {
google.protobuf.Any cookie = 1;
}
message ConnectRequest {
Connection connection = 1;
oneof type {
// Fixed channel identifier (returns a fixed channel).
uint16 cid = 2; // provide some constants ?
// Protocol/Service Multiplexer (returns a dynamic channel).
uint16 psm = 3; // provide some constants ?
}
// Maximum transmission unit.
// Shall not be set for fixed channels.
uint16 mtu = 4;
// Maximum PDU payload size.
// Shall not be set for fixed channels.
// Required for dynamic channels over LE.
// For BR/EDR connections, if set (and supported by the host), a credits based channel is opened.
uint16 mps = 5;
}
message ConnectResponse {
oneof result {
uint8 error = 1; // enum ?
Channel channel = 2;
}
}
message WaitConnectionRequest {
Connection connection = 1;
oneof type {
// Fixed channel identifier (returns a fixed channel).
uint16 cid = 2; // provide some constants ?
// Protocol/Service Multiplexer (returns a dynamic channel).
uint16 psm = 3; // provide some constants ?
}
// Maximum transmission unit.
// Shall not be set for fixed channels.
uint16 mtu = 4;
// Maximum PDU payload size.
// Shall not be set for fixed channels.
// Required for dynamic channels over LE.
// For BR/EDR connections, if set (and supported by the host), a credits based channel is opened.
uint16 mps = 5;
}
message WaitConnectionResponse {
oneof result {
uint8 error = 1; // enum ?
Channel channel = 2;
}
}
message DisconnectRequest {
Channel channel = 1;
}
message DisconnectResponse {
oneof result {
uint8 error = 1; // enum ?
google.protobuf.Empty success = 2;
}
}
message WaitDisconnectionRequest {
Channel channel = 1;
}
message WaitDisconnectionResponse {
oneof result {
int8 error = 1; // enum ?
google.protobuf.Empty success = 2;
}
}
message ReceiveRequest {
Channel channel = 1;
}
message ReceiveResponse {
bytes data = 1;
}
message SendRequest {
Channel channel = 1;
bytes data = 1;
}
message SendResponse {
oneof result {
uint8 error = 1; // enum ?
google.protobuf.Empty success = 2;
}
}It's the closest from the spec I came with, but I might be wrong !
The main imposed design points are:
- Naming.
- Error handling.
XxxRequestandXxxResponsefor eachXxxrpc call, if not empty.
The rest is all subject to change, according to your feedback, android APIs, testing requirements, ...
|
Sorry that was a draft sync... |
|
But for the server questions:
This is relatively impossible, especially for fixed channels which are usually established right after ACL established. If servers must be registered on connection level, there might be some cases hard to handle.
Not for my requirement(in fact I only need fixed channels for the near future), but on many platforms(like Android), dynamic channels cannot be registered without allocation(though there is a hidden API but not promised for usage).
This is not fully applicable because |
779ce00 to
de0440f
Compare
Humm maybe we could do something like this ?
Ok, I guess we can implement this in a follow-up PR, what do you think ?
Can you try changing the package name Thank you for your patience, I known it's not easy to handle such a review with our different timelines :/ .. |
|
Generally it's good enough, but one thing left is that we still need a flag to handle whether enhanced credit based connection is used in LE.
Sure
NP |
True! message ConnectRequest {
oneof type {
// ...
// Create a Enhanced credits based dynamic channel over BR/EDR or Low-Energy.
DynamicChannelRequest enhanced_credits_based = 3;
}
}
message WaitConnectionRequest {
oneof type {
// ...
// Create a Enhanced credits based dynamic channel over BR/EDR or Low-Energy.
DynamicChannelRequest enhanced_credits_based = 3;
}
}Or something like this ? |
|
Modified based on comments. |
uael
left a comment
There was a problem hiding this comment.
Perfect! Some documentation and we are good to go 😃
dfca19d to
e655519
Compare
17af3d0 to
68be861
Compare
|
@DeltaEvo Could you review this as I will be OOO ? |
e2a3dd2 to
1683369
Compare
|
Sample implementations: |
Including fixed channels. Note: This proto is not compatible with l2cap.proto on AOSP, since the API is too Android-specific.
Including fixed channels.
Note: This proto is not compatible with l2cap.proto on AOSP, since the API is not compatible with Bumble(and even most hosts).