89 lines
2.9 KiB
Python
Raw Permalink Normal View History

import sys
import time
import threading
from scapy.all import Ether, IP, UDP, send, sendp, Raw, sniff
global initial_timestamp
initial_timestamp = int(time.time() * 1000)
# Simulated ACK sending function
def send_ack(destination_IP, my_port, sender_port):
ack_data = ""
###################
# With localhost:
ack_packet = (
IP(dst=destination_IP)
/ UDP(dport=sender_port, sport=my_port)
/ Raw(load=str(ack_data))
)
send(ack_packet, verbose=False)
###################
# With netns:
# ack_packet = Ether(dst="00:00:00:00:00:04", src="00:00:00:00:00:01") / IP(dst="127.0.0.1") / UDP(dport=5551) / Raw(load=str(ack_data))
# sendp(ack_packet, verbose=False)
###################
print(f"Sent ACK: {ack_data}")
# Process incoming packets
def process_packet(pkt):
################### Save timestamps ###################
if Raw in pkt:
with open(save_file, "a") as f: # open as "a" for append
global initial_timestamp
receival_time = str(
int(time.time() * 1000) - initial_timestamp
) # time of arrival at receiver
send_time = pkt[Raw].load # time it was sent from the sender
################### Conversion & error handling ###################
try:
send_time = int(
send_time.decode("utf-8").split("X")[0]
) # decode the payload and stop at "X"
except (
ValueError
): # For the last packet without a timestamp but "END" as payload
print(f"END for {my_port}")
send_ack(destination_IP, my_port, sender_port)
return
except Exception as e:
print(f"Decoding error at {my_port}")
send_ack(destination_IP, my_port, sender_port)
return
################### Write data ###################
aoi = int(receival_time) - send_time
f.write(f"{send_time},{receival_time},{aoi}\n")
send_ack(destination_IP, my_port, sender_port)
# Main loop
def main(destination_IP, my_port, sender_port):
###################
# With localhost:
sniff(
iface="lo",
filter=f"udp and dst port {my_port}",
prn=process_packet,
store=False,
)
###################
# With netns:
# sniff(iface="ns-g", filter=f"udp and dst port {my_port}", prn=process_packet, store=False)
###################
if __name__ == "__main__":
if len(sys.argv) != 4:
print(
"Usage: python receive_and_ack.py <destination_IP> <my_port> <sender_port>"
)
sys.exit(1)
destination_IP = sys.argv[1] # Clear
my_port = int(sys.argv[2]) # Port to listen on
sender_port = int(sys.argv[3]) # Port to send acks to
save_file = f"timestamps_{my_port}"
main(destination_IP, my_port, sender_port)