piermesh/src/Packets/Message.py

230 lines
7.3 KiB
Python
Raw Normal View History

2024-08-01 01:09:11 +00:00
import Packets.Packet as p
import Packets.HeaderPacket as h
import lzma
import msgpack
import random
import math
2024-11-23 03:34:39 +00:00
import logging
2024-08-01 01:09:11 +00:00
# DO NOT CHANGE DATA SIZE UNLESS YOU KNOW WHAT YOURE DOING
2024-11-23 03:34:39 +00:00
logger = logging.getLogger("__main__." + __name__)
2024-08-01 01:09:11 +00:00
2024-08-12 10:29:58 +00:00
def dict2bytes(cdict: dict):
return lzma.compress(msgpack.dumps(cdict))
2024-08-01 01:09:11 +00:00
class Message:
"""
Full message which is composed of `Packets.Packet.Packet`s
2024-08-01 22:03:59 +00:00
`🔗 Source <https://git.utopic.work/PierMesh/piermesh/src/branch/main/Packets/Message.py>`__
2024-08-01 01:09:11 +00:00
Attributes
----------
packets: list[Packets.Packet.Packet]
List of packets making up the Message
"""
def __init__(
self,
bytesObject: bytes,
sender: int,
senderDisplayName: int,
2024-08-12 10:29:58 +00:00
sourceNode,
2024-08-01 01:09:11 +00:00
recipient: int,
recipientNode: int,
2024-08-02 12:03:52 +00:00
cryptographyInfo,
2024-08-12 10:29:58 +00:00
packetsClass,
pAction,
2024-08-01 01:09:11 +00:00
dataSize: int = 128,
wantFullResponse: bool = False,
2024-11-23 03:34:39 +00:00
target=True,
subMessage=False,
primaryMessage=None,
pskEncrypt=False
2024-08-01 01:09:11 +00:00
):
"""
Parameters
----------
bytesObject: bytes
Bytes to split into packets
sender: int
6 digit (maximum) node or peer ID
senderDisplayName: int
3 digit (maximum) ID for mapping display names to a given user
2024-11-26 17:43:02 +00:00
sourceNode: int
Source of request
2024-08-01 01:09:11 +00:00
recipient: int
6 digit (maximum) node or peer ID
recipientNode: int
6 digit (maximum) node ID to route the packet to
2024-11-26 17:43:02 +00:00
cryptographyInfo: Cryptography.WhaleSong.Transport
Cryptography instance for encrypting message
packetsClass: int
Which protocol the packets are using
pAction: int
3 digit (maximum) pAction ID for mapping precise actions within a protocol
2024-08-01 01:09:11 +00:00
dataSize: int
Size to cut the bytesObject into per packet
wantFullResponse: bool
Whether to send a response when the message has completed reception (TODO: Kill all retries for associated packets when received)
2024-11-26 17:43:02 +00:00
target
Whether the message is being sent to a target, if so, where
subMessage: bool
Whether this is a submessage
primaryMessage
Primary message this is a submessage to, if this is a submessage
pskEncrypt: bool
Whether to encrypt the message with the pre shared key
2024-08-01 01:09:11 +00:00
"""
2024-11-23 03:34:39 +00:00
self.recipientNode = recipientNode
self.target = target
self.subMessage = subMessage
if subMessage:
self.primaryMessage = primaryMessage
2024-08-01 01:09:11 +00:00
if isinstance(bytesObject, list):
packets = [h.Header(bytesObject[0])]
for packet in bytesObject:
packets.append(
p.Packet(
packet["data"],
packetsID=packet["packetsID"],
packetNumber=packet["packetNumber"],
packetsClass=packetsClass,
)
)
self.packets = packets
else:
2024-11-26 17:43:02 +00:00
# TODO: Data passed in by peers should already have been e2ee encrypted by SubtleCrypto
2024-11-23 03:34:39 +00:00
if subMessage == False:
bytesObject, nonce, tag = cryptographyInfo.encrypt(
bytesObject, str(recipientNode).zfill(6), isDict=False, pskEncrypt=pskEncrypt
)
2024-11-26 17:43:02 +00:00
# logger.debug(bytesObject)
2024-11-23 03:34:39 +00:00
self.nonce = nonce
self.tag = tag
2024-08-01 01:09:11 +00:00
packets = []
self.packetsID = random.randrange(0, 999999)
pnum = 1
2024-11-23 03:34:39 +00:00
dataSize = 80
2024-08-01 01:09:11 +00:00
blen = math.ceil(len(bytesObject) / dataSize)
tb = b""
for it in range(blen):
if it >= (blen - 1):
2024-11-26 17:43:02 +00:00
b = bytesObject[it * dataSize:]
2024-08-01 01:09:11 +00:00
else:
2024-11-26 17:43:02 +00:00
b = bytesObject[it * dataSize: (it * dataSize + dataSize)]
2024-11-23 03:34:39 +00:00
if subMessage:
packets.append(
p.Packet(
b,
self.packetsID,
pnum,
packetsClass=packetsClass,
primaryMessage=primaryMessage,
)
)
else:
packets.append(
p.Packet(b, self.packetsID, pnum, packetsClass=packetsClass)
)
2024-08-01 01:09:11 +00:00
pnum += 1
tb += b
2024-11-23 03:34:39 +00:00
if subMessage:
pass
else:
packets.insert(
0,
h.Header(
self.packetsID,
pnum,
sender,
senderDisplayName,
sourceNode,
recipient,
recipientNode,
wantFullResponse=wantFullResponse,
packetsClass=packetsClass,
pAction=pAction,
target=target,
),
)
self.fullPackets = [p for p in packets]
if subMessage:
pnum -= 1
2024-11-26 17:43:02 +00:00
2024-08-01 01:09:11 +00:00
for it in range(pnum):
packet = msgpack.loads(packets[it].dump())
packet["packetCount"] = pnum
packets[it] = msgpack.dumps(packet)
self.packets = packets
def get(self) -> list[p.Packet]:
"""
Get and return all packets
"""
return self.packets
2024-11-23 03:34:39 +00:00
def reassemble(self, completedMessage: dict, cryptographyInfo, subMessage=False, yctx=None, packetCount=None):
2024-08-01 01:09:11 +00:00
"""
2024-11-26 17:43:02 +00:00
Reassemble packets from a completed message in `Sponge.base`, meant to be used without instantiation
Arguments
---------
completedMessage: dict
All parts of the message and submessage
cryptographyInfo: Cryptography.WhaleSong.Transport
Cryptography instance for encrypting message
subMessage: bool
Whether this is a submessage
yctx
Message parsing context
packetCount
Number of packets
2024-08-01 01:09:11 +00:00
"""
data = b""
2024-11-23 03:34:39 +00:00
sourceNode = None
if subMessage:
sourceNode = yctx["sourceNode"]["val"]
for it in range(1, packetCount+1):
data += completedMessage["data"][completedMessage["dataOrder"].index(it)]
data = msgpack.loads(lzma.decompress(data))
2024-11-26 17:43:02 +00:00
# logger.debug(data)
# logger.debug(completedMessage["data"])
# logger.debug(completedMessage["dataOrder"])
2024-11-23 03:34:39 +00:00
else:
packetCount = int(completedMessage.yctx["packetCount"]["val"])
sourceNode = completedMessage.yctx["sourceNode"]["val"]
2024-11-26 17:43:02 +00:00
# logger.debug(completedMessage.data)
2024-11-23 03:34:39 +00:00
for it in range(1, packetCount):
if it in completedMessage.dataOrder:
data += completedMessage.data[completedMessage.dataOrder.index(it)]
2024-11-26 17:43:02 +00:00
# logger.debug("pre decrypt")
# logger.debug(data)
2024-11-23 03:34:39 +00:00
data = cryptographyInfo.decrypt(
data, sourceNode, completedMessage.nonce, completedMessage.tag
2024-08-12 10:29:58 +00:00
)
2024-11-23 03:34:39 +00:00
return data