mirror of
https://github.com/meshcore-dev/meshcore_py.git
synced 2026-06-11 11:56:18 +00:00
implemented anon binary requests
This commit is contained in:
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "meshcore"
|
name = "meshcore"
|
||||||
version = "2.2.5"
|
version = "2.2.6"
|
||||||
authors = [
|
authors = [
|
||||||
{ name="Florent de Lamotte", email="florent@frizoncorrea.fr" },
|
{ name="Florent de Lamotte", email="florent@frizoncorrea.fr" },
|
||||||
{ name="Alex Wolden", email="awolden@gmail.com" },
|
{ name="Alex Wolden", email="awolden@gmail.com" },
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import logging
|
|||||||
import random
|
import random
|
||||||
from typing import Any, Callable, Coroutine, Dict, List, Optional, Union
|
from typing import Any, Callable, Coroutine, Dict, List, Optional, Union
|
||||||
|
|
||||||
from meshcore.packets import BinaryReqType
|
from meshcore.packets import BinaryReqType, AnonReqType
|
||||||
|
|
||||||
from ..events import Event, EventDispatcher, EventType
|
from ..events import Event, EventDispatcher, EventType
|
||||||
from ..reader import MessageReader
|
from ..reader import MessageReader
|
||||||
@@ -187,3 +187,24 @@ class CommandHandlerBase:
|
|||||||
self._reader.register_binary_request(pubkey_prefix.hex(), exp_tag, request_type, actual_timeout, context=context)
|
self._reader.register_binary_request(pubkey_prefix.hex(), exp_tag, request_type, actual_timeout, context=context)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
async def send_anon_req(self, dst: DestinationType, request_type: AnonReqType, data: Optional[bytes] = None, context={}, timeout=None, min_timeout=0) -> Event:
|
||||||
|
dst_bytes = _validate_destination(dst, prefix_length=32)
|
||||||
|
pubkey_prefix = _validate_destination(dst, prefix_length=6)
|
||||||
|
logger.debug(f"Anon Binary request to {dst_bytes.hex()}")
|
||||||
|
data = b"\x39" + dst_bytes + request_type.value.to_bytes(1, "little", signed=False) + (data if data else b"")
|
||||||
|
|
||||||
|
result = await self.send(data, [EventType.MSG_SENT, EventType.ERROR])
|
||||||
|
|
||||||
|
# Register the request with the reader if we have both reader and request_type
|
||||||
|
if (result.type == EventType.MSG_SENT and
|
||||||
|
self._reader is not None and
|
||||||
|
request_type is not None):
|
||||||
|
|
||||||
|
exp_tag = result.payload["expected_ack"].hex()
|
||||||
|
# Use provided timeout or fallback to suggested timeout (with 5s default)
|
||||||
|
actual_timeout = timeout if timeout is not None and timeout > 0 else result.payload.get("suggested_timeout", 4000) / 800.0
|
||||||
|
actual_timeout = min_timeout if actual_timeout < min_timeout else actual_timeout
|
||||||
|
self._reader.register_binary_request(pubkey_prefix.hex(), exp_tag, request_type, actual_timeout, context=context)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
import random
|
import random
|
||||||
|
import io
|
||||||
|
|
||||||
from .base import CommandHandlerBase
|
from .base import CommandHandlerBase
|
||||||
from ..events import EventType
|
from ..events import EventType
|
||||||
from ..packets import BinaryReqType
|
from ..packets import BinaryReqType
|
||||||
|
from ..packets import AnonReqType
|
||||||
|
|
||||||
logger = logging.getLogger("meshcore")
|
logger = logging.getLogger("meshcore")
|
||||||
|
|
||||||
@@ -242,3 +244,109 @@ class BinaryCommandHandler(CommandHandlerBase):
|
|||||||
res["neighbours"] += next_res["neighbours"]
|
res["neighbours"] += next_res["neighbours"]
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
async def req_regions_async(self, contact, timeout=0, min_timeout=0):
|
||||||
|
req = b"\0" # The return path, I currently do nothing with, so direct only
|
||||||
|
return await self.send_anon_req(
|
||||||
|
contact,
|
||||||
|
AnonReqType.REGIONS,
|
||||||
|
data=req,
|
||||||
|
timeout=timeout
|
||||||
|
)
|
||||||
|
|
||||||
|
async def req_regions_sync(self, contact, timeout=0, min_timeout=0):
|
||||||
|
res = await self.req_regions_async(contact, timeout, min_timeout)
|
||||||
|
|
||||||
|
if res.type == EventType.ERROR:
|
||||||
|
return None
|
||||||
|
|
||||||
|
timeout = res.payload["suggested_timeout"] / 800 if timeout == 0 else timeout
|
||||||
|
timeout = timeout if timeout > min_timeout else min_timeout
|
||||||
|
|
||||||
|
if self.dispatcher is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
region_event = await self.dispatcher.wait_for_event(
|
||||||
|
EventType.BINARY_RESPONSE,
|
||||||
|
attribute_filters={"tag": res.payload["expected_ack"].hex()},
|
||||||
|
timeout=timeout,
|
||||||
|
)
|
||||||
|
|
||||||
|
if region_event is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
pkt = bytes().fromhex(region_event.payload["data"])
|
||||||
|
pbuf = io.BytesIO(pkt)
|
||||||
|
tag_again = pbuf.read(4)
|
||||||
|
return pbuf.read().decode("utf-8", "ignore").strip("\x00")
|
||||||
|
|
||||||
|
async def req_owner_async(self, contact, timeout=0, min_timeout=0):
|
||||||
|
req = b"\0"
|
||||||
|
return await self.send_anon_req(
|
||||||
|
contact,
|
||||||
|
AnonReqType.OWNER,
|
||||||
|
data=req,
|
||||||
|
timeout=timeout
|
||||||
|
)
|
||||||
|
|
||||||
|
async def req_owner_sync(self, contact, timeout=0, min_timeout=0):
|
||||||
|
|
||||||
|
res = await self.req_owner_async(contact, timeout, min_timeout)
|
||||||
|
|
||||||
|
if res.type == EventType.ERROR:
|
||||||
|
return None
|
||||||
|
|
||||||
|
timeout = res.payload["suggested_timeout"] / 800 if timeout == 0 else timeout
|
||||||
|
timeout = timeout if timeout > min_timeout else min_timeout
|
||||||
|
|
||||||
|
if self.dispatcher is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
owner_event = await self.dispatcher.wait_for_event(
|
||||||
|
EventType.BINARY_RESPONSE,
|
||||||
|
attribute_filters={"tag": res.payload["expected_ack"].hex()},
|
||||||
|
timeout=timeout,
|
||||||
|
)
|
||||||
|
|
||||||
|
if owner_event is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
pkt = bytes().fromhex(owner_event.payload["data"])
|
||||||
|
pbuf = io.BytesIO(pkt)
|
||||||
|
tag_again = pbuf.read(4)
|
||||||
|
strings = pbuf.read().decode("utf-8", "ignore").split("\n", 1)
|
||||||
|
|
||||||
|
return dict(name=strings[0], owner=strings[1].strip("\x00"))
|
||||||
|
|
||||||
|
async def req_basic_async(self, contact, timeout=0, min_timeout=0):
|
||||||
|
req = b"\0"
|
||||||
|
return await self.send_anon_req(
|
||||||
|
contact,
|
||||||
|
AnonReqType.BASIC,
|
||||||
|
data=req,
|
||||||
|
timeout=timeout
|
||||||
|
)
|
||||||
|
|
||||||
|
async def req_basic_sync(self, contact, timeout=0, min_timeout=0):
|
||||||
|
|
||||||
|
res = await self.req_basic_async(contact, timeout, min_timeout)
|
||||||
|
|
||||||
|
if res.type == EventType.ERROR:
|
||||||
|
return None
|
||||||
|
|
||||||
|
timeout = res.payload["suggested_timeout"] / 800 if timeout == 0 else timeout
|
||||||
|
timeout = timeout if timeout > min_timeout else min_timeout
|
||||||
|
|
||||||
|
if self.dispatcher is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
basic_event = await self.dispatcher.wait_for_event(
|
||||||
|
EventType.BINARY_RESPONSE,
|
||||||
|
attribute_filters={"tag": res.payload["expected_ack"].hex()},
|
||||||
|
timeout=timeout,
|
||||||
|
)
|
||||||
|
|
||||||
|
if basic_event is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return basic_event.payload
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
|
||||||
|
class AnonReqType(Enum):
|
||||||
|
REGIONS = 0x01
|
||||||
|
OWNER = 0x02
|
||||||
|
BASIC = 0x03 # just remote clock
|
||||||
|
|
||||||
class BinaryReqType(Enum):
|
class BinaryReqType(Enum):
|
||||||
STATUS = 0x01
|
STATUS = 0x01
|
||||||
KEEP_ALIVE = 0x02
|
KEEP_ALIVE = 0x02
|
||||||
|
|||||||
@@ -597,10 +597,10 @@ class MessageReader:
|
|||||||
)
|
)
|
||||||
|
|
||||||
elif packet_type_value == PacketType.BINARY_RESPONSE.value:
|
elif packet_type_value == PacketType.BINARY_RESPONSE.value:
|
||||||
logger.debug(f"Received binary data: {data.hex()}")
|
|
||||||
dbuf.read(1)
|
dbuf.read(1)
|
||||||
tag = dbuf.read(4).hex()
|
tag = dbuf.read(4).hex()
|
||||||
response_data = dbuf.read()
|
response_data = dbuf.read()
|
||||||
|
logger.debug(f"Received binary data: {data.hex()}, tag {tag}, data {response_data.hex()}")
|
||||||
|
|
||||||
# Always dispatch generic BINARY_RESPONSE
|
# Always dispatch generic BINARY_RESPONSE
|
||||||
binary_res = {"tag": tag, "data": response_data.hex()}
|
binary_res = {"tag": tag, "data": response_data.hex()}
|
||||||
|
|||||||
Reference in New Issue
Block a user