bumble 0.0.170__py3-none-any.whl → 0.0.172__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- bumble/_version.py +6 -2
- bumble/apps/console.py +1 -1
- bumble/apps/controller_info.py +2 -1
- bumble/apps/speaker/speaker.py +2 -2
- bumble/att.py +77 -51
- bumble/device.py +5 -3
- bumble/gatt.py +22 -20
- bumble/gatt_client.py +67 -32
- bumble/gatt_server.py +75 -31
- bumble/l2cap.py +92 -125
- bumble/pandora/security.py +5 -1
- bumble/transport/android_emulator.py +7 -4
- bumble/transport/android_netsim.py +84 -50
- bumble/transport/common.py +3 -8
- bumble/transport/ws_client.py +9 -7
- {bumble-0.0.170.dist-info → bumble-0.0.172.dist-info}/METADATA +2 -1
- {bumble-0.0.170.dist-info → bumble-0.0.172.dist-info}/RECORD +21 -21
- {bumble-0.0.170.dist-info → bumble-0.0.172.dist-info}/LICENSE +0 -0
- {bumble-0.0.170.dist-info → bumble-0.0.172.dist-info}/WHEEL +0 -0
- {bumble-0.0.170.dist-info → bumble-0.0.172.dist-info}/entry_points.txt +0 -0
- {bumble-0.0.170.dist-info → bumble-0.0.172.dist-info}/top_level.txt +0 -0
bumble/l2cap.py
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
# -----------------------------------------------------------------------------
|
|
18
18
|
from __future__ import annotations
|
|
19
19
|
import asyncio
|
|
20
|
+
import enum
|
|
20
21
|
import logging
|
|
21
22
|
import struct
|
|
22
23
|
|
|
@@ -676,56 +677,35 @@ class L2CAP_LE_Flow_Control_Credit(L2CAP_Control_Frame):
|
|
|
676
677
|
|
|
677
678
|
# -----------------------------------------------------------------------------
|
|
678
679
|
class Channel(EventEmitter):
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
STATE_NAMES = {
|
|
703
|
-
CLOSED: 'CLOSED',
|
|
704
|
-
WAIT_CONNECT: 'WAIT_CONNECT',
|
|
705
|
-
WAIT_CONNECT_RSP: 'WAIT_CONNECT_RSP',
|
|
706
|
-
OPEN: 'OPEN',
|
|
707
|
-
WAIT_DISCONNECT: 'WAIT_DISCONNECT',
|
|
708
|
-
WAIT_CREATE: 'WAIT_CREATE',
|
|
709
|
-
WAIT_CREATE_RSP: 'WAIT_CREATE_RSP',
|
|
710
|
-
WAIT_MOVE: 'WAIT_MOVE',
|
|
711
|
-
WAIT_MOVE_RSP: 'WAIT_MOVE_RSP',
|
|
712
|
-
WAIT_MOVE_CONFIRM: 'WAIT_MOVE_CONFIRM',
|
|
713
|
-
WAIT_CONFIRM_RSP: 'WAIT_CONFIRM_RSP',
|
|
714
|
-
WAIT_CONFIG: 'WAIT_CONFIG',
|
|
715
|
-
WAIT_SEND_CONFIG: 'WAIT_SEND_CONFIG',
|
|
716
|
-
WAIT_CONFIG_REQ_RSP: 'WAIT_CONFIG_REQ_RSP',
|
|
717
|
-
WAIT_CONFIG_RSP: 'WAIT_CONFIG_RSP',
|
|
718
|
-
WAIT_CONFIG_REQ: 'WAIT_CONFIG_REQ',
|
|
719
|
-
WAIT_IND_FINAL_RSP: 'WAIT_IND_FINAL_RSP',
|
|
720
|
-
WAIT_FINAL_RSP: 'WAIT_FINAL_RSP',
|
|
721
|
-
WAIT_CONTROL_IND: 'WAIT_CONTROL_IND',
|
|
722
|
-
}
|
|
680
|
+
class State(enum.IntEnum):
|
|
681
|
+
# States
|
|
682
|
+
CLOSED = 0x00
|
|
683
|
+
WAIT_CONNECT = 0x01
|
|
684
|
+
WAIT_CONNECT_RSP = 0x02
|
|
685
|
+
OPEN = 0x03
|
|
686
|
+
WAIT_DISCONNECT = 0x04
|
|
687
|
+
WAIT_CREATE = 0x05
|
|
688
|
+
WAIT_CREATE_RSP = 0x06
|
|
689
|
+
WAIT_MOVE = 0x07
|
|
690
|
+
WAIT_MOVE_RSP = 0x08
|
|
691
|
+
WAIT_MOVE_CONFIRM = 0x09
|
|
692
|
+
WAIT_CONFIRM_RSP = 0x0A
|
|
693
|
+
|
|
694
|
+
# CONFIG substates
|
|
695
|
+
WAIT_CONFIG = 0x10
|
|
696
|
+
WAIT_SEND_CONFIG = 0x11
|
|
697
|
+
WAIT_CONFIG_REQ_RSP = 0x12
|
|
698
|
+
WAIT_CONFIG_RSP = 0x13
|
|
699
|
+
WAIT_CONFIG_REQ = 0x14
|
|
700
|
+
WAIT_IND_FINAL_RSP = 0x15
|
|
701
|
+
WAIT_FINAL_RSP = 0x16
|
|
702
|
+
WAIT_CONTROL_IND = 0x17
|
|
723
703
|
|
|
724
704
|
connection_result: Optional[asyncio.Future[None]]
|
|
725
705
|
disconnection_result: Optional[asyncio.Future[None]]
|
|
726
706
|
response: Optional[asyncio.Future[bytes]]
|
|
727
707
|
sink: Optional[Callable[[bytes], Any]]
|
|
728
|
-
state:
|
|
708
|
+
state: State
|
|
729
709
|
connection: Connection
|
|
730
710
|
|
|
731
711
|
def __init__(
|
|
@@ -741,7 +721,7 @@ class Channel(EventEmitter):
|
|
|
741
721
|
self.manager = manager
|
|
742
722
|
self.connection = connection
|
|
743
723
|
self.signaling_cid = signaling_cid
|
|
744
|
-
self.state =
|
|
724
|
+
self.state = self.State.CLOSED
|
|
745
725
|
self.mtu = mtu
|
|
746
726
|
self.psm = psm
|
|
747
727
|
self.source_cid = source_cid
|
|
@@ -751,10 +731,8 @@ class Channel(EventEmitter):
|
|
|
751
731
|
self.disconnection_result = None
|
|
752
732
|
self.sink = None
|
|
753
733
|
|
|
754
|
-
def
|
|
755
|
-
logger.debug(
|
|
756
|
-
f'{self} state change -> {color(Channel.STATE_NAMES[new_state], "cyan")}'
|
|
757
|
-
)
|
|
734
|
+
def _change_state(self, new_state: State) -> None:
|
|
735
|
+
logger.debug(f'{self} state change -> {color(new_state.name, "cyan")}')
|
|
758
736
|
self.state = new_state
|
|
759
737
|
|
|
760
738
|
def send_pdu(self, pdu: Union[SupportsBytes, bytes]) -> None:
|
|
@@ -767,7 +745,7 @@ class Channel(EventEmitter):
|
|
|
767
745
|
# Check that there isn't already a request pending
|
|
768
746
|
if self.response:
|
|
769
747
|
raise InvalidStateError('request already pending')
|
|
770
|
-
if self.state !=
|
|
748
|
+
if self.state != self.State.OPEN:
|
|
771
749
|
raise InvalidStateError('channel not open')
|
|
772
750
|
|
|
773
751
|
self.response = asyncio.get_running_loop().create_future()
|
|
@@ -787,14 +765,14 @@ class Channel(EventEmitter):
|
|
|
787
765
|
)
|
|
788
766
|
|
|
789
767
|
async def connect(self) -> None:
|
|
790
|
-
if self.state !=
|
|
768
|
+
if self.state != self.State.CLOSED:
|
|
791
769
|
raise InvalidStateError('invalid state')
|
|
792
770
|
|
|
793
771
|
# Check that we can start a new connection
|
|
794
772
|
if self.connection_result:
|
|
795
773
|
raise RuntimeError('connection already pending')
|
|
796
774
|
|
|
797
|
-
self.
|
|
775
|
+
self._change_state(self.State.WAIT_CONNECT_RSP)
|
|
798
776
|
self.send_control_frame(
|
|
799
777
|
L2CAP_Connection_Request(
|
|
800
778
|
identifier=self.manager.next_identifier(self.connection),
|
|
@@ -814,10 +792,10 @@ class Channel(EventEmitter):
|
|
|
814
792
|
self.connection_result = None
|
|
815
793
|
|
|
816
794
|
async def disconnect(self) -> None:
|
|
817
|
-
if self.state !=
|
|
795
|
+
if self.state != self.State.OPEN:
|
|
818
796
|
raise InvalidStateError('invalid state')
|
|
819
797
|
|
|
820
|
-
self.
|
|
798
|
+
self._change_state(self.State.WAIT_DISCONNECT)
|
|
821
799
|
self.send_control_frame(
|
|
822
800
|
L2CAP_Disconnection_Request(
|
|
823
801
|
identifier=self.manager.next_identifier(self.connection),
|
|
@@ -832,8 +810,8 @@ class Channel(EventEmitter):
|
|
|
832
810
|
return await self.disconnection_result
|
|
833
811
|
|
|
834
812
|
def abort(self) -> None:
|
|
835
|
-
if self.state == self.OPEN:
|
|
836
|
-
self.
|
|
813
|
+
if self.state == self.State.OPEN:
|
|
814
|
+
self._change_state(self.State.CLOSED)
|
|
837
815
|
self.emit('close')
|
|
838
816
|
|
|
839
817
|
def send_configure_request(self) -> None:
|
|
@@ -856,7 +834,7 @@ class Channel(EventEmitter):
|
|
|
856
834
|
|
|
857
835
|
def on_connection_request(self, request) -> None:
|
|
858
836
|
self.destination_cid = request.source_cid
|
|
859
|
-
self.
|
|
837
|
+
self._change_state(self.State.WAIT_CONNECT)
|
|
860
838
|
self.send_control_frame(
|
|
861
839
|
L2CAP_Connection_Response(
|
|
862
840
|
identifier=request.identifier,
|
|
@@ -866,24 +844,24 @@ class Channel(EventEmitter):
|
|
|
866
844
|
status=0x0000,
|
|
867
845
|
)
|
|
868
846
|
)
|
|
869
|
-
self.
|
|
847
|
+
self._change_state(self.State.WAIT_CONFIG)
|
|
870
848
|
self.send_configure_request()
|
|
871
|
-
self.
|
|
849
|
+
self._change_state(self.State.WAIT_CONFIG_REQ_RSP)
|
|
872
850
|
|
|
873
851
|
def on_connection_response(self, response):
|
|
874
|
-
if self.state !=
|
|
852
|
+
if self.state != self.State.WAIT_CONNECT_RSP:
|
|
875
853
|
logger.warning(color('invalid state', 'red'))
|
|
876
854
|
return
|
|
877
855
|
|
|
878
856
|
if response.result == L2CAP_Connection_Response.CONNECTION_SUCCESSFUL:
|
|
879
857
|
self.destination_cid = response.destination_cid
|
|
880
|
-
self.
|
|
858
|
+
self._change_state(self.State.WAIT_CONFIG)
|
|
881
859
|
self.send_configure_request()
|
|
882
|
-
self.
|
|
860
|
+
self._change_state(self.State.WAIT_CONFIG_REQ_RSP)
|
|
883
861
|
elif response.result == L2CAP_Connection_Response.CONNECTION_PENDING:
|
|
884
862
|
pass
|
|
885
863
|
else:
|
|
886
|
-
self.
|
|
864
|
+
self._change_state(self.State.CLOSED)
|
|
887
865
|
self.connection_result.set_exception(
|
|
888
866
|
ProtocolError(
|
|
889
867
|
response.result,
|
|
@@ -895,9 +873,9 @@ class Channel(EventEmitter):
|
|
|
895
873
|
|
|
896
874
|
def on_configure_request(self, request) -> None:
|
|
897
875
|
if self.state not in (
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
876
|
+
self.State.WAIT_CONFIG,
|
|
877
|
+
self.State.WAIT_CONFIG_REQ,
|
|
878
|
+
self.State.WAIT_CONFIG_REQ_RSP,
|
|
901
879
|
):
|
|
902
880
|
logger.warning(color('invalid state', 'red'))
|
|
903
881
|
return
|
|
@@ -918,25 +896,28 @@ class Channel(EventEmitter):
|
|
|
918
896
|
options=request.options, # TODO: don't accept everything blindly
|
|
919
897
|
)
|
|
920
898
|
)
|
|
921
|
-
if self.state ==
|
|
922
|
-
self.
|
|
899
|
+
if self.state == self.State.WAIT_CONFIG:
|
|
900
|
+
self._change_state(self.State.WAIT_SEND_CONFIG)
|
|
923
901
|
self.send_configure_request()
|
|
924
|
-
self.
|
|
925
|
-
elif self.state ==
|
|
926
|
-
self.
|
|
902
|
+
self._change_state(self.State.WAIT_CONFIG_RSP)
|
|
903
|
+
elif self.state == self.State.WAIT_CONFIG_REQ:
|
|
904
|
+
self._change_state(self.State.OPEN)
|
|
927
905
|
if self.connection_result:
|
|
928
906
|
self.connection_result.set_result(None)
|
|
929
907
|
self.connection_result = None
|
|
930
908
|
self.emit('open')
|
|
931
|
-
elif self.state ==
|
|
932
|
-
self.
|
|
909
|
+
elif self.state == self.State.WAIT_CONFIG_REQ_RSP:
|
|
910
|
+
self._change_state(self.State.WAIT_CONFIG_RSP)
|
|
933
911
|
|
|
934
912
|
def on_configure_response(self, response) -> None:
|
|
935
913
|
if response.result == L2CAP_Configure_Response.SUCCESS:
|
|
936
|
-
if self.state ==
|
|
937
|
-
self.
|
|
938
|
-
elif self.state in (
|
|
939
|
-
self.
|
|
914
|
+
if self.state == self.State.WAIT_CONFIG_REQ_RSP:
|
|
915
|
+
self._change_state(self.State.WAIT_CONFIG_REQ)
|
|
916
|
+
elif self.state in (
|
|
917
|
+
self.State.WAIT_CONFIG_RSP,
|
|
918
|
+
self.State.WAIT_CONTROL_IND,
|
|
919
|
+
):
|
|
920
|
+
self._change_state(self.State.OPEN)
|
|
940
921
|
if self.connection_result:
|
|
941
922
|
self.connection_result.set_result(None)
|
|
942
923
|
self.connection_result = None
|
|
@@ -966,7 +947,7 @@ class Channel(EventEmitter):
|
|
|
966
947
|
# TODO: decide how to fail gracefully
|
|
967
948
|
|
|
968
949
|
def on_disconnection_request(self, request) -> None:
|
|
969
|
-
if self.state in (
|
|
950
|
+
if self.state in (self.State.OPEN, self.State.WAIT_DISCONNECT):
|
|
970
951
|
self.send_control_frame(
|
|
971
952
|
L2CAP_Disconnection_Response(
|
|
972
953
|
identifier=request.identifier,
|
|
@@ -974,14 +955,14 @@ class Channel(EventEmitter):
|
|
|
974
955
|
source_cid=request.source_cid,
|
|
975
956
|
)
|
|
976
957
|
)
|
|
977
|
-
self.
|
|
958
|
+
self._change_state(self.State.CLOSED)
|
|
978
959
|
self.emit('close')
|
|
979
960
|
self.manager.on_channel_closed(self)
|
|
980
961
|
else:
|
|
981
962
|
logger.warning(color('invalid state', 'red'))
|
|
982
963
|
|
|
983
964
|
def on_disconnection_response(self, response) -> None:
|
|
984
|
-
if self.state !=
|
|
965
|
+
if self.state != self.State.WAIT_DISCONNECT:
|
|
985
966
|
logger.warning(color('invalid state', 'red'))
|
|
986
967
|
return
|
|
987
968
|
|
|
@@ -992,7 +973,7 @@ class Channel(EventEmitter):
|
|
|
992
973
|
logger.warning('unexpected source or destination CID')
|
|
993
974
|
return
|
|
994
975
|
|
|
995
|
-
self.
|
|
976
|
+
self._change_state(self.State.CLOSED)
|
|
996
977
|
if self.disconnection_result:
|
|
997
978
|
self.disconnection_result.set_result(None)
|
|
998
979
|
self.disconnection_result = None
|
|
@@ -1004,7 +985,7 @@ class Channel(EventEmitter):
|
|
|
1004
985
|
f'Channel({self.source_cid}->{self.destination_cid}, '
|
|
1005
986
|
f'PSM={self.psm}, '
|
|
1006
987
|
f'MTU={self.mtu}, '
|
|
1007
|
-
f'state={
|
|
988
|
+
f'state={self.state.name})'
|
|
1008
989
|
)
|
|
1009
990
|
|
|
1010
991
|
|
|
@@ -1014,33 +995,21 @@ class LeConnectionOrientedChannel(EventEmitter):
|
|
|
1014
995
|
LE Credit-based Connection Oriented Channel
|
|
1015
996
|
"""
|
|
1016
997
|
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
STATE_NAMES = {
|
|
1025
|
-
INIT: 'INIT',
|
|
1026
|
-
CONNECTED: 'CONNECTED',
|
|
1027
|
-
CONNECTING: 'CONNECTING',
|
|
1028
|
-
DISCONNECTING: 'DISCONNECTING',
|
|
1029
|
-
DISCONNECTED: 'DISCONNECTED',
|
|
1030
|
-
CONNECTION_ERROR: 'CONNECTION_ERROR',
|
|
1031
|
-
}
|
|
998
|
+
class State(enum.IntEnum):
|
|
999
|
+
INIT = 0
|
|
1000
|
+
CONNECTED = 1
|
|
1001
|
+
CONNECTING = 2
|
|
1002
|
+
DISCONNECTING = 3
|
|
1003
|
+
DISCONNECTED = 4
|
|
1004
|
+
CONNECTION_ERROR = 5
|
|
1032
1005
|
|
|
1033
1006
|
out_queue: Deque[bytes]
|
|
1034
1007
|
connection_result: Optional[asyncio.Future[LeConnectionOrientedChannel]]
|
|
1035
1008
|
disconnection_result: Optional[asyncio.Future[None]]
|
|
1036
1009
|
out_sdu: Optional[bytes]
|
|
1037
|
-
state:
|
|
1010
|
+
state: State
|
|
1038
1011
|
connection: Connection
|
|
1039
1012
|
|
|
1040
|
-
@staticmethod
|
|
1041
|
-
def state_name(state: int) -> str:
|
|
1042
|
-
return name_or_number(LeConnectionOrientedChannel.STATE_NAMES, state)
|
|
1043
|
-
|
|
1044
1013
|
def __init__(
|
|
1045
1014
|
self,
|
|
1046
1015
|
manager: ChannelManager,
|
|
@@ -1083,19 +1052,17 @@ class LeConnectionOrientedChannel(EventEmitter):
|
|
|
1083
1052
|
self.drained.set()
|
|
1084
1053
|
|
|
1085
1054
|
if connected:
|
|
1086
|
-
self.state =
|
|
1055
|
+
self.state = self.State.CONNECTED
|
|
1087
1056
|
else:
|
|
1088
|
-
self.state =
|
|
1057
|
+
self.state = self.State.INIT
|
|
1089
1058
|
|
|
1090
|
-
def
|
|
1091
|
-
logger.debug(
|
|
1092
|
-
f'{self} state change -> {color(self.state_name(new_state), "cyan")}'
|
|
1093
|
-
)
|
|
1059
|
+
def _change_state(self, new_state: State) -> None:
|
|
1060
|
+
logger.debug(f'{self} state change -> {color(new_state.name, "cyan")}')
|
|
1094
1061
|
self.state = new_state
|
|
1095
1062
|
|
|
1096
|
-
if new_state == self.CONNECTED:
|
|
1063
|
+
if new_state == self.State.CONNECTED:
|
|
1097
1064
|
self.emit('open')
|
|
1098
|
-
elif new_state == self.DISCONNECTED:
|
|
1065
|
+
elif new_state == self.State.DISCONNECTED:
|
|
1099
1066
|
self.emit('close')
|
|
1100
1067
|
|
|
1101
1068
|
def send_pdu(self, pdu: Union[SupportsBytes, bytes]) -> None:
|
|
@@ -1106,7 +1073,7 @@ class LeConnectionOrientedChannel(EventEmitter):
|
|
|
1106
1073
|
|
|
1107
1074
|
async def connect(self) -> LeConnectionOrientedChannel:
|
|
1108
1075
|
# Check that we're in the right state
|
|
1109
|
-
if self.state != self.INIT:
|
|
1076
|
+
if self.state != self.State.INIT:
|
|
1110
1077
|
raise InvalidStateError('not in a connectable state')
|
|
1111
1078
|
|
|
1112
1079
|
# Check that we can start a new connection
|
|
@@ -1114,7 +1081,7 @@ class LeConnectionOrientedChannel(EventEmitter):
|
|
|
1114
1081
|
if identifier in self.manager.le_coc_requests:
|
|
1115
1082
|
raise RuntimeError('too many concurrent connection requests')
|
|
1116
1083
|
|
|
1117
|
-
self.
|
|
1084
|
+
self._change_state(self.State.CONNECTING)
|
|
1118
1085
|
request = L2CAP_LE_Credit_Based_Connection_Request(
|
|
1119
1086
|
identifier=identifier,
|
|
1120
1087
|
le_psm=self.le_psm,
|
|
@@ -1134,10 +1101,10 @@ class LeConnectionOrientedChannel(EventEmitter):
|
|
|
1134
1101
|
|
|
1135
1102
|
async def disconnect(self) -> None:
|
|
1136
1103
|
# Check that we're connected
|
|
1137
|
-
if self.state != self.CONNECTED:
|
|
1104
|
+
if self.state != self.State.CONNECTED:
|
|
1138
1105
|
raise InvalidStateError('not connected')
|
|
1139
1106
|
|
|
1140
|
-
self.
|
|
1107
|
+
self._change_state(self.State.DISCONNECTING)
|
|
1141
1108
|
self.flush_output()
|
|
1142
1109
|
self.send_control_frame(
|
|
1143
1110
|
L2CAP_Disconnection_Request(
|
|
@@ -1153,15 +1120,15 @@ class LeConnectionOrientedChannel(EventEmitter):
|
|
|
1153
1120
|
return await self.disconnection_result
|
|
1154
1121
|
|
|
1155
1122
|
def abort(self) -> None:
|
|
1156
|
-
if self.state == self.CONNECTED:
|
|
1157
|
-
self.
|
|
1123
|
+
if self.state == self.State.CONNECTED:
|
|
1124
|
+
self._change_state(self.State.DISCONNECTED)
|
|
1158
1125
|
|
|
1159
1126
|
def on_pdu(self, pdu: bytes) -> None:
|
|
1160
1127
|
if self.sink is None:
|
|
1161
1128
|
logger.warning('received pdu without a sink')
|
|
1162
1129
|
return
|
|
1163
1130
|
|
|
1164
|
-
if self.state != self.CONNECTED:
|
|
1131
|
+
if self.state != self.State.CONNECTED:
|
|
1165
1132
|
logger.warning('received PDU while not connected, dropping')
|
|
1166
1133
|
|
|
1167
1134
|
# Manage the peer credits
|
|
@@ -1240,7 +1207,7 @@ class LeConnectionOrientedChannel(EventEmitter):
|
|
|
1240
1207
|
self.credits = response.initial_credits
|
|
1241
1208
|
self.connected = True
|
|
1242
1209
|
self.connection_result.set_result(self)
|
|
1243
|
-
self.
|
|
1210
|
+
self._change_state(self.State.CONNECTED)
|
|
1244
1211
|
else:
|
|
1245
1212
|
self.connection_result.set_exception(
|
|
1246
1213
|
ProtocolError(
|
|
@@ -1251,7 +1218,7 @@ class LeConnectionOrientedChannel(EventEmitter):
|
|
|
1251
1218
|
),
|
|
1252
1219
|
)
|
|
1253
1220
|
)
|
|
1254
|
-
self.
|
|
1221
|
+
self._change_state(self.State.CONNECTION_ERROR)
|
|
1255
1222
|
|
|
1256
1223
|
# Cleanup
|
|
1257
1224
|
self.connection_result = None
|
|
@@ -1271,11 +1238,11 @@ class LeConnectionOrientedChannel(EventEmitter):
|
|
|
1271
1238
|
source_cid=request.source_cid,
|
|
1272
1239
|
)
|
|
1273
1240
|
)
|
|
1274
|
-
self.
|
|
1241
|
+
self._change_state(self.State.DISCONNECTED)
|
|
1275
1242
|
self.flush_output()
|
|
1276
1243
|
|
|
1277
1244
|
def on_disconnection_response(self, response) -> None:
|
|
1278
|
-
if self.state != self.DISCONNECTING:
|
|
1245
|
+
if self.state != self.State.DISCONNECTING:
|
|
1279
1246
|
logger.warning(color('invalid state', 'red'))
|
|
1280
1247
|
return
|
|
1281
1248
|
|
|
@@ -1286,7 +1253,7 @@ class LeConnectionOrientedChannel(EventEmitter):
|
|
|
1286
1253
|
logger.warning('unexpected source or destination CID')
|
|
1287
1254
|
return
|
|
1288
1255
|
|
|
1289
|
-
self.
|
|
1256
|
+
self._change_state(self.State.DISCONNECTED)
|
|
1290
1257
|
if self.disconnection_result:
|
|
1291
1258
|
self.disconnection_result.set_result(None)
|
|
1292
1259
|
self.disconnection_result = None
|
|
@@ -1339,7 +1306,7 @@ class LeConnectionOrientedChannel(EventEmitter):
|
|
|
1339
1306
|
return
|
|
1340
1307
|
|
|
1341
1308
|
def write(self, data: bytes) -> None:
|
|
1342
|
-
if self.state != self.CONNECTED:
|
|
1309
|
+
if self.state != self.State.CONNECTED:
|
|
1343
1310
|
logger.warning('not connected, dropping data')
|
|
1344
1311
|
return
|
|
1345
1312
|
|
|
@@ -1367,7 +1334,7 @@ class LeConnectionOrientedChannel(EventEmitter):
|
|
|
1367
1334
|
def __str__(self) -> str:
|
|
1368
1335
|
return (
|
|
1369
1336
|
f'CoC({self.source_cid}->{self.destination_cid}, '
|
|
1370
|
-
f'State={self.
|
|
1337
|
+
f'State={self.state.name}, '
|
|
1371
1338
|
f'PSM={self.le_psm}, '
|
|
1372
1339
|
f'MTU={self.mtu}/{self.peer_mtu}, '
|
|
1373
1340
|
f'MPS={self.mps}/{self.peer_mps}, '
|
bumble/pandora/security.py
CHANGED
|
@@ -233,7 +233,11 @@ class SecurityService(SecurityServicer):
|
|
|
233
233
|
sc=config.pairing_sc_enable,
|
|
234
234
|
mitm=config.pairing_mitm_enable,
|
|
235
235
|
bonding=config.pairing_bonding_enable,
|
|
236
|
-
identity_address_type=
|
|
236
|
+
identity_address_type=(
|
|
237
|
+
PairingConfig.AddressType.PUBLIC
|
|
238
|
+
if connection.self_address.is_public
|
|
239
|
+
else config.identity_address_type
|
|
240
|
+
),
|
|
237
241
|
delegate=PairingDelegate(
|
|
238
242
|
connection,
|
|
239
243
|
self,
|
|
@@ -97,10 +97,13 @@ async def open_android_emulator_transport(spec: Optional[str]) -> Transport:
|
|
|
97
97
|
raise ValueError('invalid mode')
|
|
98
98
|
|
|
99
99
|
# Create the transport object
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
100
|
+
class EmulatorTransport(PumpedTransport):
|
|
101
|
+
async def close(self):
|
|
102
|
+
await super().close()
|
|
103
|
+
await channel.close()
|
|
104
|
+
|
|
105
|
+
transport = EmulatorTransport(
|
|
106
|
+
PumpedPacketSource(hci_device.read), PumpedPacketSink(hci_device.write)
|
|
104
107
|
)
|
|
105
108
|
transport.start()
|
|
106
109
|
|