Module: ZeroConf::Utils

Included in:
Client, Service
Defined in:
lib/zeroconf/utils.rb

Overview

:startdoc:

Constant Summary collapse

DISCOVERY_NAME =
"_services._dns-sd._udp.local."
BROADCAST_V4 =
Addrinfo.new Socket.sockaddr_in(Resolv::MDNS::Port, Resolv::MDNS::AddressV4)
BROADCAST_V6 =
Addrinfo.new Socket.sockaddr_in(Resolv::MDNS::Port, Resolv::MDNS::AddressV6)

Instance Method Summary collapse

Instance Method Details

#broadcast_v4Object



85
86
87
# File 'lib/zeroconf/utils.rb', line 85

def broadcast_v4
  BROADCAST_V4
end

#broadcast_v6Object



89
90
91
# File 'lib/zeroconf/utils.rb', line 89

def broadcast_v6
  BROADCAST_V6
end

#multicast_send(sock, query) ⇒ Object



75
76
77
78
79
80
81
82
83
# File 'lib/zeroconf/utils.rb', line 75

def multicast_send sock, query
  dest = if sock.local_address.ipv4?
    broadcast_v4
  else
    broadcast_v6
  end

  sock.send(query, 0, dest)
end

#open_ipv4(saddr, port) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/zeroconf/utils.rb', line 57

def open_ipv4 saddr, port
  sock = UDPSocket.new Socket::AF_INET
  sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true)
  sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEPORT, true)
  sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_MULTICAST_TTL, true)
  sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_MULTICAST_LOOP, true)
  sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP,
                  IPAddr.new(Resolv::MDNS::AddressV4).hton + IPAddr.new(saddr.ip_address).hton)
  sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_MULTICAST_IF, IPAddr.new(saddr.ip_address).hton)
  sock.bind saddr.ip_address, port
  flags = sock.fcntl(Fcntl::F_GETFL, 0)
  sock.fcntl(Fcntl::F_SETFL, Fcntl::O_NONBLOCK | flags)
  sock
end

#open_ipv6(saddr, port) ⇒ Object



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/zeroconf/utils.rb', line 97

def open_ipv6 saddr, port
  sock = UDPSocket.new Socket::AF_INET6
  sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true)
  sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEPORT, true)
  sock.setsockopt(Socket::IPPROTO_IPV6, Socket::IPV6_MULTICAST_HOPS, true)
  sock.setsockopt(Socket::IPPROTO_IPV6, Socket::IPV6_MULTICAST_LOOP, true)

  # This address isn't correct, but giving it to IPAddr seems to result
  # in the right bytes back from hton.
  # See: https://github.com/ruby/ipaddr/issues/63
  s = IPAddr.new("ff02:0000:0000:0000:0000:00fb:0000:0000").hton
  sock.setsockopt(Socket::IPPROTO_IPV6, Socket::IPV6_JOIN_GROUP, s)
  sock.setsockopt(Socket::IPPROTO_IPV6, Socket::IPV6_MULTICAST_IF, IPAddr.new(saddr.ip_address).hton)
  sock.bind saddr.ip_address, port
  flags = sock.fcntl(Fcntl::F_GETFL, 0)
  sock.fcntl(Fcntl::F_SETFL, Fcntl::O_NONBLOCK | flags)

  sock
rescue SystemCallError
end

#unicast_send(sock, data, to) ⇒ Object



93
94
95
# File 'lib/zeroconf/utils.rb', line 93

def unicast_send sock, data, to
  sock.send(data, 0, Addrinfo.new(to))
end