90 lines
3.0 KiB
Python
Raw Normal View History

2024-07-03 23:29:26 +09:00
import math
2024-07-08 16:46:17 +09:00
from collections import Counter
from typing import Awaitable
2024-07-03 23:29:26 +09:00
import pandas
from mixnet.connection import SimplexConnection
from mixnet.framework.framework import Framework, Queue
2024-07-05 17:29:20 +09:00
from mixnet.sim.config import NetworkConfig
2024-07-05 22:57:46 +09:00
from mixnet.sim.state import NodeState
2024-07-03 23:29:26 +09:00
class MeteredRemoteSimplexConnection(SimplexConnection):
framework: Framework
2024-07-05 17:29:20 +09:00
latency: float
send_queue: Queue
mid_queue: Queue
recv_queue: Queue
send_task: Awaitable
send_meters: list[int]
recv_task: Awaitable
recv_meters: list[int]
send_node_states: list[NodeState]
recv_node_states: list[NodeState]
2024-07-08 16:46:17 +09:00
msg_sizes: Counter[int]
2024-07-05 22:57:46 +09:00
def __init__(
self,
config: NetworkConfig,
framework: Framework,
send_node_states: list[NodeState],
recv_node_states: list[NodeState],
2024-07-05 22:57:46 +09:00
):
self.framework = framework
2024-07-05 22:57:46 +09:00
self.latency = config.random_latency()
self.send_queue = framework.queue()
self.mid_queue = framework.queue()
self.recv_queue = framework.queue()
self.send_meters = []
self.send_task = framework.spawn(self.__run_send_task())
self.recv_meters = []
self.recv_task = framework.spawn(self.__run_recv_task())
self.send_node_states = send_node_states
self.recv_node_states = recv_node_states
2024-07-08 16:46:17 +09:00
self.msg_sizes = Counter()
2024-07-03 23:29:26 +09:00
async def send(self, data: bytes) -> None:
await self.send_queue.put(data)
2024-07-08 16:46:17 +09:00
self.msg_sizes.update([len(data)])
2024-07-05 22:57:46 +09:00
ms = math.floor(self.framework.now() * 1000)
self.send_node_states[ms] = NodeState.SENDING
2024-07-03 23:29:26 +09:00
async def recv(self) -> bytes:
data = await self.recv_queue.get()
2024-07-05 22:57:46 +09:00
ms = math.floor(self.framework.now() * 1000)
self.send_node_states[ms] = NodeState.RECEIVING
2024-07-05 22:57:46 +09:00
return data
2024-07-03 23:29:26 +09:00
async def __run_send_task(self):
start_time = self.framework.now()
2024-07-03 23:29:26 +09:00
while True:
data = await self.send_queue.get()
self.__update_meter(self.send_meters, len(data), start_time)
await self.mid_queue.put(data)
2024-07-03 23:29:26 +09:00
async def __run_recv_task(self):
start_time = self.framework.now()
2024-07-03 23:29:26 +09:00
while True:
data = await self.mid_queue.get()
if data is None:
break
2024-07-05 17:29:20 +09:00
await self.framework.sleep(self.latency)
self.__update_meter(self.recv_meters, len(data), start_time)
await self.recv_queue.put(data)
2024-07-03 23:29:26 +09:00
def __update_meter(self, meters: list[int], size: int, start_time: float):
slot = math.floor(self.framework.now() - start_time)
2024-07-03 23:29:26 +09:00
assert slot >= len(meters) - 1
meters.extend([0] * (slot - len(meters) + 1))
meters[-1] += size
def sending_bandwidths(self) -> pandas.Series:
return self.__bandwidths(self.send_meters)
2024-07-03 23:29:26 +09:00
def receiving_bandwidths(self) -> pandas.Series:
return self.__bandwidths(self.recv_meters)
2024-07-03 23:29:26 +09:00
def __bandwidths(self, meters: list[int]) -> pandas.Series:
return pandas.Series(meters, name="bandwidth")