-
Notifications
You must be signed in to change notification settings - Fork 6
Q&A for developer
Every packet is strait defined by handler.
So it is very important to predefine your handler's behavior first.
Then you can make a unicast or broadcast like below:
# Unicast
p.handler_unicast_packet(host=(target_addr[0], target_addr[1]),
pkt_type=CustomHandler.pkt_type)
# Broadcast
# "all" will broadcast to each peer
# You can specified a role like "core" or something else.
role = "all"
p.handler_broadcast_packet(host=(None, role),
pkt_type=CustomHandler.pkt_type)Currently we don't provide any way to operate on registered handler.
You can not list all handler that the peer has registered.
But you do can test a handler is registered or not like below:
handler = p.select_handler(pkt_type=TestExistsHandler.pkt_type)
if handler is None:
# handler not registered.
pass
else:
# handler is registered.
passTechnically, no, you can't do it while that packet's handler not registered.
Both handler_unicast_packet and handler_broadcast_packet checks register relation while trying to pend the packet into sending queue.
But you do can archive with a very tricky way which is directly operate sending queue inside peer class.
AND HERE IS A VERY BIG BUT: We don't recommend that way to force peer to send the packet. Because we are trying to make every packet has properly handle by handler. Once an improper packet has been pend in sending queue, the remote peer may not function normally.
The idea of this structure is that we highly encapsulated the relation b/w Packet and Handler.
It seems that any additional operation of packet from outer class is impossible.
But actually, through your customize handler class, you do can decide what kind of arguments you want to give, when a handler is going to be initialize.
And the solution is to give a callback argument would be very good and gentle.
from atomic_p2p.utils.communication import Handler
class CustomHandler(Handler):
pkt_type = "custom_pkt"
def __init__(self, peer, callback):
super(CustomHandler, self).__init__(
peer=peer, pkt_type=type(self).pkt_type)
self.callback = callback
... statements ...
def on_recv_pkt(self, src, pkt, conn):
# Here is some operations when you recv a packet from remote peer.
# ... statements ...
self.peer.logger.info("src: {}, pkt: {}".format(src, pkt))
# This gives the data to callback.
self.callback(pkt.data)But unfortunately, this solution will make the peer initialization been a little bit complex.
The handler would take one more argument while registering the handler.
And here comes two approach.
This will make arguments of class be very very hard to read.
from atomic_p2p.peer import Peer
from custom_handler import CustomHandler
class CustomPeer(Peer):
def __init__(self, host, name, role, cert, _hash, handler_callback):
super(CustomPeer, self).__init__(
host=host, name=name, role=role, cert=cert, _hash=_hash)
# If you have a lot of handler needs callback, this may annoy you.
self.handler_callback = handler_callback
def _register_handler(self):
super(CustomPeer, self)._register_handler()
installing_handlers = [
# Here puts the poor handler_callback
CustomHandler(self, callback=self.handler_callback)
]
for each in installing_handlers:
self.pkt_handlers[type(each).pkt_type] = eachAt the definition of _handler_register inside Peer class.
def _register_handler(self) -> None:
installing_handlers = [ ... handlers ... ]
for each in installing_handlers:
self.pkt_handlers[type(each).pkt_type] = eachYou can manually register a handler outside custom peer class just like _handler_register method do.
For example:
def handler_callback(data):
pass
p = CustomPeer(...)
handler = CustomHandler(peer=p, callback=handler_callback)
p.pkt_handlers[type(handler).pkt_type] = handler
p.start()I know this approach is very tricky, and I will provide a handler register method asap.