mirror of
https://github.com/meshcore-dev/meshcore_py.git
synced 2026-04-20 22:13:49 +00:00
implemented anon binary requests
This commit is contained in:
parent
ac82eeb905
commit
3b46986dfa
5 changed files with 137 additions and 3 deletions
|
|
@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|||
|
||||
[project]
|
||||
name = "meshcore"
|
||||
version = "2.2.5"
|
||||
version = "2.2.6"
|
||||
authors = [
|
||||
{ name="Florent de Lamotte", email="florent@frizoncorrea.fr" },
|
||||
{ name="Alex Wolden", email="awolden@gmail.com" },
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import logging
|
|||
import random
|
||||
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 ..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)
|
||||
|
||||
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 logging
|
||||
import random
|
||||
import io
|
||||
|
||||
from .base import CommandHandlerBase
|
||||
from ..events import EventType
|
||||
from ..packets import BinaryReqType
|
||||
from ..packets import AnonReqType
|
||||
|
||||
logger = logging.getLogger("meshcore")
|
||||
|
||||
|
|
@ -242,3 +244,109 @@ class BinaryCommandHandler(CommandHandlerBase):
|
|||
res["neighbours"] += next_res["neighbours"]
|
||||
|
||||
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
|
||||
|
||||
class AnonReqType(Enum):
|
||||
REGIONS = 0x01
|
||||
OWNER = 0x02
|
||||
BASIC = 0x03 # just remote clock
|
||||
|
||||
class BinaryReqType(Enum):
|
||||
STATUS = 0x01
|
||||
KEEP_ALIVE = 0x02
|
||||
|
|
|
|||
|
|
@ -597,10 +597,10 @@ class MessageReader:
|
|||
)
|
||||
|
||||
elif packet_type_value == PacketType.BINARY_RESPONSE.value:
|
||||
logger.debug(f"Received binary data: {data.hex()}")
|
||||
dbuf.read(1)
|
||||
tag = dbuf.read(4).hex()
|
||||
response_data = dbuf.read()
|
||||
logger.debug(f"Received binary data: {data.hex()}, tag {tag}, data {response_data.hex()}")
|
||||
|
||||
# Always dispatch generic BINARY_RESPONSE
|
||||
binary_res = {"tag": tag, "data": response_data.hex()}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue