Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions examples/simple_send_and_receive/send_psn.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@

try:
tracker_num = int(sys.argv[1])
ip_addr = sys.argv[2]
mcast_ip = None
iface_ip = sys.argv[2]
mcast_grp = None

if sys.argv[3]:
mcast_ip = sys.argv[3]
mcast_grp = sys.argv[3]

except Exception as e:
print("Args: tracker_num ip_addr mcast_ip (opt).")
print("Args: tracker_num iface_ip mcast_grp (opt).")
print(e)

start_time_us = time.time_ns() // 1000
Expand Down Expand Up @@ -161,9 +161,9 @@

pypsn.send_psn_packet(
psn_packet=psn_info_packet_bytes,
mcast_ip=mcast_ip,
ip_addr=ip_addr,
iface_ip=iface_ip,
port=56565,
mcast_grp=mcast_grp,
)

psn_data.info.timestamp = elapsed_time_us
Expand All @@ -185,7 +185,7 @@

pypsn.send_psn_packet(
psn_packet=psn_data_packet_bytes,
mcast_ip=mcast_ip,
ip_addr=ip_addr,
iface_ip=iface_ip,
port=56565,
mcast_grp=mcast_grp,
)
1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ classifiers = [
"Programming Language :: Python"
]
dependencies = [
"multicast_expert>=1.4.0",
]

[tool.setuptools]
Expand Down
81 changes: 66 additions & 15 deletions pypsn/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
Pure python PSN interface.
"""

import os
import sys
import socket
from struct import pack, unpack
from enum import IntEnum
from typing import List
import os
from threading import Thread
import multicast_expert

__version__ = "0.2.4"

Expand Down Expand Up @@ -655,23 +655,74 @@ def prepare_psn_data_packet_bytes(data_packet: PsnDataPacket):


def send_psn_packet(
psn_packet, mcast_ip="236.10.10.10", ip_addr="127.0.0.1", port=56565
psn_packet,
iface_name="",
iface_ip="127.0.0.1",
port=56565,
mcast_grp="236.10.10.10",
transmit_block_size=9216,
time_to_live=31,
):
"""Send psn packet.
If mcast_ip is specified, it does via multicast with the help
of multicast_expert. If not, it does via simple unicast.
If mcast_ip is specified, it does via multicast.
If not, it does via simple unicast.
!IPV4 ONLY!
Thanks to https://gist.github.com/ifundef/09d3ec98459a856052bd935bd91683ed


Args:
psn_packet (_type_): as bytes
mcast_ip (str, optional): multicastip. Default: "236.10.10.10"
ip_addr (str, optional): local ip. Default: 127.0.0.1
psn_packet (bytes): Use binary/bytes, not text/strings for data
iface_name (str, optional): local interface name
iface_ip (str, optional): local interface ip. Default: 127.0.0.1
port (int, optional): udp port. Default: 56565
mcast_ip (str, optional): multicastip. Default: "236.10.10.10"
transmit_block_size (int, optional): max udp packet (65535) -
udp header (8) - ip header (20) = 65507. Defaults to 65507.
time_to_live (int, optional): time to live (TTL) of sent
packets. Defaults to 31 (maximum recommended for local network).

Raises:
AttributeError
"""
if mcast_ip:
with multicast_expert.McastTxSocket(
socket.AF_INET, mcast_ips=[mcast_ip], iface_ip=ip_addr
) as mcast_tx_sock:
mcast_tx_sock.sendto(psn_packet, (mcast_ip, port))

if not iface_name:
iface_name = socket.inet_ntoa(pack("i", socket.INADDR_ANY))

output_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
output_socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, time_to_live)

if mcast_grp:
ip_addr = mcast_grp

if sys.platform == "win32":
mreq = struct.pack(
"4s4s", socket.inet_aton(mcast_grp), socket.inet_aton(iface_ip)
)
output_socket.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)

# disable Path MTU Discovery (PMTUD) as it doesn't address multicast
# and silently drops any IP packets > a remote network's MTU
if sys.platform == "linux" or sys.platform == "darwin":
try:
output_socket.setsockopt(
socket.IPPROTO_IP, socket.IP_MTU_DISCOVER, socket.IP_PMTUDISC_DONT
)
except AttributeError as err:
# use numeric values instead of symbolic names
# see /usr/include/linux/in.h
if "IP_MTU_DISCOVER" in str(err) or "IP_PMTUDISC_DONT" in str(err):
output_socket.setsockopt(socket.IPPROTO_IP, 10, 0)
else:
raise err

# sent multicast packets should be looped back to local sockets
# by default, but set IP_MULTICAST_LOOP to true to insure such
output_socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, True)
output_socket.setsockopt(
socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton(iface_ip)
)
else:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(psn_packet, (ip_addr, port))
ip_addr = iface_ip

output_socket.sendto(psn_packet, (ip_addr, port))
output_socket.close()
Loading