format, add comments
This commit is contained in:
@@ -3,4 +3,8 @@ mDNS server
|
|||||||
|
|
||||||
Minimalist mDNS server implementation with only core service annoucement and no conflict resolution.
|
Minimalist mDNS server implementation with only core service annoucement and no conflict resolution.
|
||||||
|
|
||||||
|
Listen for `http` service questiond and answer with `toto` service.
|
||||||
|
|
||||||
To test our implementation we’re using zeroconf as a trusted client.
|
To test our implementation we’re using zeroconf as a trusted client.
|
||||||
|
|
||||||
|
See the [blog post](https://alexrio.fr/blog/mdns-server) for references and details.
|
||||||
|
|||||||
58
main.py
58
main.py
@@ -1,3 +1,9 @@
|
|||||||
|
"""
|
||||||
|
Simple and navie mDNS implementation.
|
||||||
|
|
||||||
|
Low level socket management to listen to mDNS queries and respond to _http._tcp.local service queries with constant name.
|
||||||
|
"""
|
||||||
|
|
||||||
import socket
|
import socket
|
||||||
from dnslib import DNSRecord, DNSHeader, QTYPE, A, SRV, TXT, RR, PTR
|
from dnslib import DNSRecord, DNSHeader, QTYPE, A, SRV, TXT, RR, PTR
|
||||||
import dns.message
|
import dns.message
|
||||||
@@ -6,21 +12,30 @@ multicast_group = "224.0.0.251"
|
|||||||
multicast_port = 5353
|
multicast_port = 5353
|
||||||
interface_ip = "0.0.0.0"
|
interface_ip = "0.0.0.0"
|
||||||
|
|
||||||
|
SERVICE_TO_ANNOUNCE = "toto"
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
|
||||||
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 32)
|
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 32)
|
||||||
# See man socket(7)
|
# See man socket(7)
|
||||||
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
#sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
|
# sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
|
||||||
|
|
||||||
sock.bind(("", multicast_port))
|
sock.bind(("", multicast_port))
|
||||||
# sock.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(multicast_group) + socket.inet_aton(interface_ip))
|
# sock.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(multicast_group) + socket.inet_aton(interface_ip))
|
||||||
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton(interface_ip))
|
sock.setsockopt(
|
||||||
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(multicast_group) + socket.inet_aton(interface_ip))
|
socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton(interface_ip)
|
||||||
|
)
|
||||||
|
sock.setsockopt(
|
||||||
|
socket.IPPROTO_IP,
|
||||||
|
socket.IP_ADD_MEMBERSHIP,
|
||||||
|
socket.inet_aton(multicast_group) + socket.inet_aton(interface_ip),
|
||||||
|
)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
received, sender = sock.recvfrom(1500)
|
received, sender = sock.recvfrom(1500)
|
||||||
print(f'Received packet of {len(received)} bytes from {sender}')
|
print(f"Received packet of {len(received)} bytes from {sender}")
|
||||||
try:
|
try:
|
||||||
msg = dns.message.from_wire(received)
|
msg = dns.message.from_wire(received)
|
||||||
except dns.exception.FormError:
|
except dns.exception.FormError:
|
||||||
@@ -29,18 +44,36 @@ def main():
|
|||||||
|
|
||||||
if msg.opcode() == dns.opcode.QUERY:
|
if msg.opcode() == dns.opcode.QUERY:
|
||||||
for question in msg.question:
|
for question in msg.question:
|
||||||
if str(question.name) == '_http._tcp.local.':
|
if str(question.name) == "_http._tcp.local.":
|
||||||
print(f"question name {type(msg)}")
|
print(f"question name {type(msg)}")
|
||||||
unicast_response = question.rdclass == 0x8001
|
unicast_response = question.rdclass == 0x8001
|
||||||
response = DNSRecord(DNSHeader(id = 0, bitmap=0x8400))
|
response = DNSRecord(DNSHeader(id=0, bitmap=0x8400))
|
||||||
ptr = PTR("toto._http._tcp.local")
|
ptr = PTR(SERVICE_TO_ANNOUNCE + "._http._tcp.local")
|
||||||
srv = SRV(target="toto.local", priority=10, port=80, weight=100)
|
srv = SRV(target="toto.local", priority=10, port=80, weight=100)
|
||||||
txt = TXT("path=/")
|
txt = TXT("path=/")
|
||||||
a = A("192.168.1.21")
|
a = A("192.168.1.21")
|
||||||
response.add_answer(RR('_http._tcp.local', QTYPE.PTR, rdata = ptr, ttl=120))
|
response.add_answer(
|
||||||
response.add_ar(RR('toto._http._tcp.local', QTYPE.SRV, rdata = srv, ttl=120))
|
RR("_http._tcp.local", QTYPE.PTR, rdata=ptr, ttl=120)
|
||||||
response.add_ar(RR('toto._http._tcp.local', QTYPE.TXT, rdata = txt, ttl=120))
|
)
|
||||||
response.add_ar(RR('toto.local', QTYPE.A, rdata = a, ttl=120))
|
response.add_ar(
|
||||||
|
RR(
|
||||||
|
SERVICE_TO_ANNOUNCE + "._http._tcp.local",
|
||||||
|
QTYPE.SRV,
|
||||||
|
rdata=srv,
|
||||||
|
ttl=120,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
response.add_ar(
|
||||||
|
RR(
|
||||||
|
SERVICE_TO_ANNOUNCE + "._http._tcp.local",
|
||||||
|
QTYPE.TXT,
|
||||||
|
rdata=txt,
|
||||||
|
ttl=120,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
response.add_ar(
|
||||||
|
RR(SERVICE_TO_ANNOUNCE + ".local", QTYPE.A, rdata=a, ttl=120)
|
||||||
|
)
|
||||||
print(str(response))
|
print(str(response))
|
||||||
if unicast_response:
|
if unicast_response:
|
||||||
print("Unicast response")
|
print("Unicast response")
|
||||||
@@ -48,7 +81,8 @@ def main():
|
|||||||
else:
|
else:
|
||||||
print("Multicast response")
|
print("Multicast response")
|
||||||
sock.sendto(response.pack(), (multicast_group, multicast_port))
|
sock.sendto(response.pack(), (multicast_group, multicast_port))
|
||||||
print(f'Send response to {sender}')
|
print(f"Send response to {sender}")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "mdns"
|
name = "mdns"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
description = "Minimalist mdns server"
|
description = "Very minimalist mdns server"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
|||||||
Reference in New Issue
Block a user