litenetlib-0952 1.0.0__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.
- litenetlib/__init__.py +66 -0
- litenetlib/channels/__init__.py +16 -0
- litenetlib/channels/base_channel.py +115 -0
- litenetlib/channels/reliable_channel.py +451 -0
- litenetlib/channels/sequenced_channel.py +239 -0
- litenetlib/core/__init__.py +53 -0
- litenetlib/core/connection_request.py +240 -0
- litenetlib/core/constants.py +186 -0
- litenetlib/core/events.py +336 -0
- litenetlib/core/internal_packets.py +358 -0
- litenetlib/core/manager.py +355 -0
- litenetlib/core/packet.py +457 -0
- litenetlib/core/peer.py +334 -0
- litenetlib/utils/__init__.py +21 -0
- litenetlib/utils/data_reader.py +447 -0
- litenetlib/utils/data_writer.py +402 -0
- litenetlib/utils/fast_bit_converter.py +199 -0
- litenetlib/utils/net_utils.py +165 -0
- litenetlib_0952-1.0.0.dist-info/METADATA +448 -0
- litenetlib_0952-1.0.0.dist-info/RECORD +23 -0
- litenetlib_0952-1.0.0.dist-info/WHEEL +5 -0
- litenetlib_0952-1.0.0.dist-info/licenses/LICENSE +21 -0
- litenetlib_0952-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Sequenced channel implementation (asyncio-compatible).
|
|
3
|
+
|
|
4
|
+
Implements sequenced and reliable sequenced delivery where only
|
|
5
|
+
the newest packet matters (older packets are dropped).
|
|
6
|
+
|
|
7
|
+
This version uses asyncio for Python compatibility while maintaining
|
|
8
|
+
exact C# protocol logic for interoperability.
|
|
9
|
+
|
|
10
|
+
Ported from: LiteNetLib/SequencedChannel.cs
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import asyncio
|
|
14
|
+
import time
|
|
15
|
+
from typing import Optional
|
|
16
|
+
from litenetlib.channels.base_channel import BaseChannel
|
|
17
|
+
from litenetlib.core.packet import NetPacket
|
|
18
|
+
from litenetlib.core.constants import PacketProperty, DeliveryMethod, NetConstants
|
|
19
|
+
from litenetlib.utils.net_utils import NetUtils
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class SequencedChannel(BaseChannel):
|
|
23
|
+
"""
|
|
24
|
+
Sequenced channel with optional reliability (asyncio-compatible).
|
|
25
|
+
|
|
26
|
+
Sequenced: Can drop packets, no duplicates, arrives in order.
|
|
27
|
+
ReliableSequenced: Only the last packet is reliable, cannot be fragmented.
|
|
28
|
+
|
|
29
|
+
Uses asyncio for Python compatibility while maintaining
|
|
30
|
+
exact C# protocol logic for C# interoperability.
|
|
31
|
+
|
|
32
|
+
C# Reference: internal sealed class SequencedChannel : BaseChannel
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
__slots__ = (
|
|
36
|
+
'_local_sequence',
|
|
37
|
+
'_remote_sequence',
|
|
38
|
+
'_reliable',
|
|
39
|
+
'_last_packet',
|
|
40
|
+
'_ack_packet',
|
|
41
|
+
'_must_send_ack',
|
|
42
|
+
'_id',
|
|
43
|
+
'_last_packet_send_time',
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
def __init__(self, peer, reliable: bool, channel_id: int):
|
|
47
|
+
"""
|
|
48
|
+
Initialize sequenced channel.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
peer: Associated peer
|
|
52
|
+
reliable: True for ReliableSequenced, False for Sequenced
|
|
53
|
+
channel_id: Channel ID (1 or 3)
|
|
54
|
+
|
|
55
|
+
C# Equivalent: public SequencedChannel(LiteNetPeer peer, bool reliable, byte id)
|
|
56
|
+
"""
|
|
57
|
+
super().__init__(peer)
|
|
58
|
+
|
|
59
|
+
self._id = channel_id
|
|
60
|
+
self._reliable = reliable
|
|
61
|
+
|
|
62
|
+
# C#: _ackPacket = new NetPacket(PacketProperty.Ack, 0) {ChannelId = id};
|
|
63
|
+
if self._reliable:
|
|
64
|
+
self._ack_packet = NetPacket(PacketProperty.ACK, 0)
|
|
65
|
+
self._ack_packet.channel_id = channel_id
|
|
66
|
+
else:
|
|
67
|
+
self._ack_packet = None
|
|
68
|
+
|
|
69
|
+
# Initialize sequences
|
|
70
|
+
# C#: _localSequence = 0; _remoteSequence = 0;
|
|
71
|
+
self._local_sequence = 0
|
|
72
|
+
self._remote_sequence = 0
|
|
73
|
+
|
|
74
|
+
# Last packet (for reliable sequenced)
|
|
75
|
+
self._last_packet: Optional[NetPacket] = None
|
|
76
|
+
self._last_packet_send_time: float = 0.0
|
|
77
|
+
|
|
78
|
+
# ACK flag
|
|
79
|
+
self._must_send_ack = False
|
|
80
|
+
|
|
81
|
+
def send_next_packets(self) -> bool:
|
|
82
|
+
"""
|
|
83
|
+
Send next packets from queue.
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
True if more packets to send, False otherwise
|
|
87
|
+
|
|
88
|
+
C# Equivalent: public override bool SendNextPackets()
|
|
89
|
+
"""
|
|
90
|
+
# C#: if (_reliable && OutgoingQueue.Count == 0)
|
|
91
|
+
if self._reliable and self._outgoing_queue.empty():
|
|
92
|
+
# Resend last packet if needed (reliable sequenced)
|
|
93
|
+
# C#: long packetHoldTime = currentTime - _lastPacketSendTime;
|
|
94
|
+
# if (packetHoldTime >= Peer.ResendDelay * TimeSpan.TicksPerMillisecond)
|
|
95
|
+
current_time = time.time()
|
|
96
|
+
packet_hold_time = current_time - self._last_packet_send_time
|
|
97
|
+
resend_delay = self._peer.resend_delay / 1000.0 # Convert to seconds
|
|
98
|
+
|
|
99
|
+
if packet_hold_time >= resend_delay:
|
|
100
|
+
packet = self._last_packet
|
|
101
|
+
if packet is not None:
|
|
102
|
+
# C#: _lastPacketSendTime = currentTime; Peer.SendUserData(packet);
|
|
103
|
+
self._last_packet_send_time = current_time
|
|
104
|
+
if hasattr(self._peer, 'send_user_data'):
|
|
105
|
+
self._peer.send_user_data(packet)
|
|
106
|
+
else:
|
|
107
|
+
# Send new packets
|
|
108
|
+
# C#: while (OutgoingQueue.Count > 0)
|
|
109
|
+
while not self._outgoing_queue.empty():
|
|
110
|
+
try:
|
|
111
|
+
# C#: NetPacket packet = OutgoingQueue.Dequeue();
|
|
112
|
+
packet = self._outgoing_queue.get_nowait()
|
|
113
|
+
except asyncio.QueueEmpty:
|
|
114
|
+
break
|
|
115
|
+
|
|
116
|
+
# Advance sequence and set packet properties
|
|
117
|
+
# C#: _localSequence = (_localSequence + 1) % NetConstants.MaxSequence;
|
|
118
|
+
# packet.Sequence = (ushort)_localSequence;
|
|
119
|
+
# packet.ChannelId = _id;
|
|
120
|
+
self._local_sequence = (self._local_sequence + 1) % NetConstants.MAX_SEQUENCE
|
|
121
|
+
packet.sequence = self._local_sequence & 0xFFFF
|
|
122
|
+
packet.channel_id = self._id
|
|
123
|
+
|
|
124
|
+
# Send packet
|
|
125
|
+
# C#: Peer.SendUserData(packet);
|
|
126
|
+
if hasattr(self._peer, 'send_user_data'):
|
|
127
|
+
self._peer.send_user_data(packet)
|
|
128
|
+
|
|
129
|
+
# Handle reliable sequenced (keep last packet)
|
|
130
|
+
# C#: if (_reliable && OutgoingQueue.Count == 0)
|
|
131
|
+
# {
|
|
132
|
+
# _lastPacketSendTime = DateTime.UtcNow.Ticks;
|
|
133
|
+
# _lastPacket = packet;
|
|
134
|
+
# }
|
|
135
|
+
# else
|
|
136
|
+
# {
|
|
137
|
+
# Peer.NetManager.PoolRecycle(packet);
|
|
138
|
+
# }
|
|
139
|
+
if self._reliable and self._outgoing_queue.empty():
|
|
140
|
+
self._last_packet_send_time = time.time()
|
|
141
|
+
self._last_packet = packet
|
|
142
|
+
else:
|
|
143
|
+
# Packet sent, will be recycled by peer
|
|
144
|
+
pass
|
|
145
|
+
|
|
146
|
+
# Send ACK if needed
|
|
147
|
+
# C#: if (_reliable && _mustSendAck)
|
|
148
|
+
# {
|
|
149
|
+
# _mustSendAck = false;
|
|
150
|
+
# _ackPacket.Sequence = _remoteSequence;
|
|
151
|
+
# Peer.SendUserData(_ackPacket);
|
|
152
|
+
# }
|
|
153
|
+
if self._reliable and self._must_send_ack:
|
|
154
|
+
self._must_send_ack = False
|
|
155
|
+
self._ack_packet.sequence = self._remote_sequence & 0xFFFF
|
|
156
|
+
if hasattr(self._peer, 'send_user_data'):
|
|
157
|
+
# Send ACK packet (copy it since it's reused)
|
|
158
|
+
ack_copy = NetPacket.from_bytes(self._ack_packet.get_bytes())
|
|
159
|
+
self._peer.send_user_data(ack_copy)
|
|
160
|
+
|
|
161
|
+
# C#: return _lastPacket != null;
|
|
162
|
+
return self._last_packet is not None
|
|
163
|
+
|
|
164
|
+
def process_packet(self, packet: NetPacket) -> bool:
|
|
165
|
+
"""
|
|
166
|
+
Process incoming packet.
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
packet: Received packet
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
True if packet was processed successfully
|
|
173
|
+
|
|
174
|
+
C# Equivalent: public override bool ProcessPacket(NetPacket packet)
|
|
175
|
+
"""
|
|
176
|
+
# C#: if (packet.IsFragmented) return false;
|
|
177
|
+
if packet.is_fragmented:
|
|
178
|
+
return False
|
|
179
|
+
|
|
180
|
+
# Handle ACK packet
|
|
181
|
+
# C#: if (packet.Property == PacketProperty.Ack)
|
|
182
|
+
# {
|
|
183
|
+
# if (_reliable && _lastPacket != null && packet.Sequence == _lastPacket.Sequence)
|
|
184
|
+
# _lastPacket = null;
|
|
185
|
+
# return false;
|
|
186
|
+
# }
|
|
187
|
+
if packet.packet_property == PacketProperty.ACK:
|
|
188
|
+
if self._reliable and self._last_packet is not None and packet.sequence == self._last_packet.sequence:
|
|
189
|
+
self._last_packet = None
|
|
190
|
+
return False
|
|
191
|
+
|
|
192
|
+
# Calculate relative sequence
|
|
193
|
+
# C#: int relative = NetUtils.RelativeSequenceNumber(packet.Sequence, _remoteSequence);
|
|
194
|
+
relative = NetUtils.relative_sequence_number(packet.sequence, self._remote_sequence)
|
|
195
|
+
packet_processed = False
|
|
196
|
+
|
|
197
|
+
# C#: if (packet.Sequence < NetConstants.MaxSequence && relative > 0)
|
|
198
|
+
if packet.sequence < NetConstants.MAX_SEQUENCE and relative > 0:
|
|
199
|
+
# Newer packet received - drop older packets
|
|
200
|
+
# C#: if (Peer.NetManager.EnableStatistics)
|
|
201
|
+
# {
|
|
202
|
+
# Peer.Statistics.AddPacketLoss(relative - 1);
|
|
203
|
+
# Peer.NetManager.Statistics.AddPacketLoss(relative - 1);
|
|
204
|
+
# }
|
|
205
|
+
# _remoteSequence = packet.Sequence;
|
|
206
|
+
|
|
207
|
+
# Note: Statistics not implemented in Python yet
|
|
208
|
+
self._remote_sequence = packet.sequence
|
|
209
|
+
|
|
210
|
+
# Deliver packet to peer
|
|
211
|
+
# C#: Peer.NetManager.CreateReceiveEvent(
|
|
212
|
+
# packet,
|
|
213
|
+
# _reliable ? DeliveryMethod.ReliableSequenced : DeliveryMethod.Sequenced,
|
|
214
|
+
# (byte)(packet.ChannelId / NetConstants.ChannelTypeCount),
|
|
215
|
+
# NetConstants.ChanneledHeaderSize,
|
|
216
|
+
# Peer);
|
|
217
|
+
|
|
218
|
+
if hasattr(self._peer, 'add_reliable_packet'):
|
|
219
|
+
delivery_method = DeliveryMethod.RELIABLE_SEQUENCED if self._reliable else DeliveryMethod.SEQUENCED
|
|
220
|
+
self._peer.add_reliable_packet(delivery_method, packet)
|
|
221
|
+
|
|
222
|
+
packet_processed = True
|
|
223
|
+
|
|
224
|
+
# Send ACK if reliable
|
|
225
|
+
# C#: if (_reliable)
|
|
226
|
+
# {
|
|
227
|
+
# _mustSendAck = true;
|
|
228
|
+
# AddToPeerChannelSendQueue();
|
|
229
|
+
# }
|
|
230
|
+
if self._reliable:
|
|
231
|
+
self._must_send_ack = True
|
|
232
|
+
self._add_to_peer_channel_send_queue()
|
|
233
|
+
|
|
234
|
+
return packet_processed
|
|
235
|
+
|
|
236
|
+
def __repr__(self) -> str:
|
|
237
|
+
reliable_str = "reliable" if self._reliable else "unreliable"
|
|
238
|
+
return (f"SequencedChannel(id={self._id}, {reliable_str}, "
|
|
239
|
+
f"local_seq={self._local_sequence}, remote_seq={self._remote_sequence})")
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Core modules for LiteNetLib v0.9.5.2 / LiteNetLib v0.9.5.2 核心模块
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from .constants import (
|
|
6
|
+
PacketProperty,
|
|
7
|
+
DeliveryMethod,
|
|
8
|
+
DisconnectReason,
|
|
9
|
+
NetConstants,
|
|
10
|
+
get_header_size
|
|
11
|
+
)
|
|
12
|
+
from .manager import LiteNetManager
|
|
13
|
+
from .peer import NetPeer, ConnectionState
|
|
14
|
+
from .events import EventBasedNetListener, INetEventListener
|
|
15
|
+
from .packet import NetPacket, NetPacketPool
|
|
16
|
+
from .connection_request import ConnectionRequest
|
|
17
|
+
from .internal_packets import (
|
|
18
|
+
NetConnectRequestPacket,
|
|
19
|
+
NetConnectAcceptPacket,
|
|
20
|
+
serialize_address,
|
|
21
|
+
deserialize_address
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
__all__ = [
|
|
25
|
+
# Constants / 常量
|
|
26
|
+
"PacketProperty",
|
|
27
|
+
"DeliveryMethod",
|
|
28
|
+
"DisconnectReason",
|
|
29
|
+
"NetConstants",
|
|
30
|
+
"get_header_size",
|
|
31
|
+
|
|
32
|
+
# Manager / 管理器
|
|
33
|
+
"LiteNetManager",
|
|
34
|
+
|
|
35
|
+
# Peer / 对等端
|
|
36
|
+
"NetPeer",
|
|
37
|
+
"ConnectionState",
|
|
38
|
+
|
|
39
|
+
# Events / 事件
|
|
40
|
+
"EventBasedNetListener",
|
|
41
|
+
"INetEventListener",
|
|
42
|
+
|
|
43
|
+
# Packets / 数据包
|
|
44
|
+
"NetPacket",
|
|
45
|
+
"NetPacketPool",
|
|
46
|
+
"ConnectionRequest",
|
|
47
|
+
|
|
48
|
+
# Internal packets / 内部数据包
|
|
49
|
+
"NetConnectRequestPacket",
|
|
50
|
+
"NetConnectAcceptPacket",
|
|
51
|
+
"serialize_address",
|
|
52
|
+
"deserialize_address",
|
|
53
|
+
]
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Connection request handling for LiteNetLib.
|
|
3
|
+
|
|
4
|
+
This module manages incoming connection requests from remote peers,
|
|
5
|
+
providing methods to accept or reject connections.
|
|
6
|
+
|
|
7
|
+
Ported from: LiteNetLib/ConnectionRequest.cs
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import threading
|
|
11
|
+
from typing import Optional, Tuple
|
|
12
|
+
from litenetlib.core.internal_packets import NetConnectRequestPacket
|
|
13
|
+
from litenetlib.utils.data_reader import NetDataReader
|
|
14
|
+
from litenetlib.utils.data_writer import NetDataWriter
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ConnectionRequestResult:
|
|
18
|
+
"""Result of connection request processing."""
|
|
19
|
+
NONE = 0
|
|
20
|
+
ACCEPT = 1
|
|
21
|
+
REJECT = 2
|
|
22
|
+
REJECT_FORCE = 3
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ConnectionRequest:
|
|
26
|
+
"""
|
|
27
|
+
Represents an incoming connection request.
|
|
28
|
+
|
|
29
|
+
Provides methods to accept or reject the connection, with optional
|
|
30
|
+
additional data for rejection reason.
|
|
31
|
+
|
|
32
|
+
Thread-safe: Each request can only be processed once (accept or reject).
|
|
33
|
+
|
|
34
|
+
C# Reference: ConnectionRequest class
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
__slots__ = (
|
|
38
|
+
'_manager',
|
|
39
|
+
'_used',
|
|
40
|
+
'_result',
|
|
41
|
+
'_internal_packet',
|
|
42
|
+
'_remote_address'
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
def __init__(
|
|
46
|
+
self,
|
|
47
|
+
remote_address: Tuple[str, int],
|
|
48
|
+
request_packet: NetConnectRequestPacket,
|
|
49
|
+
manager
|
|
50
|
+
):
|
|
51
|
+
"""
|
|
52
|
+
Create connection request.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
remote_address: Remote endpoint (host, port)
|
|
56
|
+
request_packet: Connection request packet
|
|
57
|
+
manager: Network manager instance (for callback)
|
|
58
|
+
"""
|
|
59
|
+
self._manager = manager
|
|
60
|
+
self._used = 0 # Atomic-like flag for thread safety
|
|
61
|
+
self._result = ConnectionRequestResult.NONE
|
|
62
|
+
self._internal_packet = request_packet
|
|
63
|
+
self._remote_address = remote_address
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def data(self) -> NetDataReader:
|
|
67
|
+
"""Get additional data from connection request."""
|
|
68
|
+
return self._internal_packet.data
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
def remote_address(self) -> Tuple[str, int]:
|
|
72
|
+
"""Get remote endpoint address."""
|
|
73
|
+
return self._remote_address
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def connection_time(self) -> int:
|
|
77
|
+
"""Get connection timestamp from request."""
|
|
78
|
+
return self._internal_packet.connection_time
|
|
79
|
+
|
|
80
|
+
@property
|
|
81
|
+
def connection_number(self) -> int:
|
|
82
|
+
"""Get connection number from request."""
|
|
83
|
+
return self._internal_packet.connection_number
|
|
84
|
+
|
|
85
|
+
@property
|
|
86
|
+
def peer_id(self) -> int:
|
|
87
|
+
"""Get peer ID from request."""
|
|
88
|
+
return self._internal_packet.peer_id
|
|
89
|
+
|
|
90
|
+
@property
|
|
91
|
+
def result(self) -> int:
|
|
92
|
+
"""Get request result (after accept/reject)."""
|
|
93
|
+
return self._result
|
|
94
|
+
|
|
95
|
+
def update_request(self, connect_request: NetConnectRequestPacket) -> None:
|
|
96
|
+
"""
|
|
97
|
+
Update request with newer connection attempt.
|
|
98
|
+
|
|
99
|
+
Only updates if the new request is newer (based on timestamp and connection number).
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
connect_request: New connection request packet
|
|
103
|
+
|
|
104
|
+
C# Equivalent: UpdateRequest(NetConnectRequestPacket)
|
|
105
|
+
"""
|
|
106
|
+
# Old request - ignore
|
|
107
|
+
if connect_request.connection_time < self._internal_packet.connection_time:
|
|
108
|
+
return
|
|
109
|
+
|
|
110
|
+
# Same request - ignore
|
|
111
|
+
if (connect_request.connection_time == self._internal_packet.connection_time and
|
|
112
|
+
connect_request.connection_number == self._internal_packet.connection_number):
|
|
113
|
+
return
|
|
114
|
+
|
|
115
|
+
# Newer request - update
|
|
116
|
+
self._internal_packet = connect_request
|
|
117
|
+
|
|
118
|
+
def _try_activate(self) -> bool:
|
|
119
|
+
"""
|
|
120
|
+
Try to activate request for processing (thread-safe).
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
True if successfully activated (first time), False if already used
|
|
124
|
+
|
|
125
|
+
C# Equivalent: TryActivate()
|
|
126
|
+
Uses Interlocked.CompareExchange for thread safety
|
|
127
|
+
"""
|
|
128
|
+
# Python doesn't have true atomic operations, but threading.Lock is sufficient
|
|
129
|
+
with threading.Lock():
|
|
130
|
+
if self._used == 0:
|
|
131
|
+
self._used = 1
|
|
132
|
+
return True
|
|
133
|
+
return False
|
|
134
|
+
|
|
135
|
+
def accept_if_key(self, key: str) -> Optional:
|
|
136
|
+
"""
|
|
137
|
+
Accept connection only if data matches key.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
key: Expected key string in connection data
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
Connected peer if key matches, None otherwise
|
|
144
|
+
|
|
145
|
+
C# Equivalent: AcceptIfKey(string key)
|
|
146
|
+
"""
|
|
147
|
+
if not self._try_activate():
|
|
148
|
+
return None
|
|
149
|
+
|
|
150
|
+
try:
|
|
151
|
+
reader = NetDataReader(self._internal_packet.data)
|
|
152
|
+
received_key = reader.get_string()
|
|
153
|
+
if received_key == key:
|
|
154
|
+
self._result = ConnectionRequestResult.ACCEPT
|
|
155
|
+
except Exception:
|
|
156
|
+
# NetDebug.WriteError("[AC] Invalid incoming data")
|
|
157
|
+
pass
|
|
158
|
+
|
|
159
|
+
if self._result == ConnectionRequestResult.ACCEPT:
|
|
160
|
+
return self._manager.on_connection_solved(self, None, 0, 0)
|
|
161
|
+
|
|
162
|
+
self._result = ConnectionRequestResult.REJECT
|
|
163
|
+
self._manager.on_connection_solved(self, None, 0, 0)
|
|
164
|
+
return None
|
|
165
|
+
|
|
166
|
+
def accept(self) -> Optional:
|
|
167
|
+
"""
|
|
168
|
+
Accept connection and get connected peer.
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
Connected peer, or None if request already processed
|
|
172
|
+
|
|
173
|
+
C# Equivalent: Accept()
|
|
174
|
+
"""
|
|
175
|
+
if not self._try_activate():
|
|
176
|
+
return None
|
|
177
|
+
|
|
178
|
+
self._result = ConnectionRequestResult.ACCEPT
|
|
179
|
+
return self._manager.on_connection_solved(self, None, 0, 0)
|
|
180
|
+
|
|
181
|
+
def reject(
|
|
182
|
+
self,
|
|
183
|
+
reject_data: Optional[bytes] = None,
|
|
184
|
+
start: int = 0,
|
|
185
|
+
length: Optional[int] = None,
|
|
186
|
+
force: bool = False
|
|
187
|
+
) -> None:
|
|
188
|
+
"""
|
|
189
|
+
Reject connection with optional data.
|
|
190
|
+
|
|
191
|
+
Args:
|
|
192
|
+
reject_data: Optional rejection data bytes
|
|
193
|
+
start: Starting offset in reject_data
|
|
194
|
+
length: Number of bytes from reject_data to send
|
|
195
|
+
force: Whether to force rejection
|
|
196
|
+
|
|
197
|
+
C# Equivalent: Reject(byte[], int, int, bool)
|
|
198
|
+
"""
|
|
199
|
+
if not self._try_activate():
|
|
200
|
+
return
|
|
201
|
+
|
|
202
|
+
if length is None and reject_data is not None:
|
|
203
|
+
length = len(reject_data)
|
|
204
|
+
|
|
205
|
+
self._result = ConnectionRequestResult.REJECT_FORCE if force else ConnectionRequestResult.REJECT
|
|
206
|
+
self._manager.on_connection_solved(self, reject_data, start, length if length else 0)
|
|
207
|
+
|
|
208
|
+
def reject_force(
|
|
209
|
+
self,
|
|
210
|
+
reject_data: Optional[bytes] = None,
|
|
211
|
+
start: int = 0,
|
|
212
|
+
length: Optional[int] = None
|
|
213
|
+
) -> None:
|
|
214
|
+
"""
|
|
215
|
+
Force reject connection.
|
|
216
|
+
|
|
217
|
+
Args:
|
|
218
|
+
reject_data: Optional rejection data bytes
|
|
219
|
+
start: Starting offset in reject_data
|
|
220
|
+
length: Number of bytes from reject_data to send
|
|
221
|
+
|
|
222
|
+
C# Equivalent: RejectForce(byte[], int, int)
|
|
223
|
+
"""
|
|
224
|
+
self.reject(reject_data, start, length, force=True)
|
|
225
|
+
|
|
226
|
+
def reject_with_writer(self, reject_data: NetDataWriter, force: bool = False) -> None:
|
|
227
|
+
"""
|
|
228
|
+
Reject connection with NetDataWriter.
|
|
229
|
+
|
|
230
|
+
Args:
|
|
231
|
+
reject_data: Data writer with rejection information
|
|
232
|
+
force: Whether to force rejection
|
|
233
|
+
|
|
234
|
+
C# Equivalent: Reject(NetDataWriter) or RejectForce(NetDataWriter)
|
|
235
|
+
"""
|
|
236
|
+
self.reject(reject_data.data, 0, reject_data.length, force)
|
|
237
|
+
|
|
238
|
+
def __repr__(self) -> str:
|
|
239
|
+
return (f"ConnectionRequest(remote={self._remote_address}, "
|
|
240
|
+
f"time={self.connection_time}, peer_id={self.peer_id})")
|