]> git.michaelhowe.org Git - packages/p/paho-mqtt.git/commitdiff
Add support for DNS SRV records
authorJan-Piet Mens <jpmens@gmail.com>
Wed, 13 Nov 2013 10:59:06 +0000 (11:59 +0100)
committerRoger Light <roger@atchoo.org>
Mon, 3 Feb 2014 21:20:21 +0000 (21:20 +0000)
adds preliminary support for DNS SRV records in a new
function connect_srv(domain=None). If domain is None
a lookup on the domain of the host is attempted. Otherwise
domain is a DNS domain name to query for the SRV records.
change service to IANA-assigned

Signed-off-by: Jan-Piet Mens <jpmens@gmail.com>
examples/sub-srv.py [new file with mode: 0755]
src/paho/mqtt/client.py

diff --git a/examples/sub-srv.py b/examples/sub-srv.py
new file mode 100755 (executable)
index 0000000..b5103a0
--- /dev/null
@@ -0,0 +1,68 @@
+#!/usr/bin/python
+
+# Copyright (c) 2010-2013 Roger Light <roger@atchoo.org>
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Distribution License v1.0
+# which accompanies this distribution. 
+#
+# The Eclipse Distribution License is available at 
+#   http://www.eclipse.org/org/documents/edl-v10.php.
+#
+# Contributors:
+#    Roger Light - initial implementation
+# Copyright (c) 2010,2011 Roger Light <roger@atchoo.org>
+# All rights reserved.
+
+# This shows a simple example of an MQTT subscriber.
+
+import sys
+try:
+    import paho.mqtt.client as mqtt
+except ImportError:
+    # This part is only required to run the example from within the examples
+    # directory when the module itself is not installed.
+    #
+    # If you have the module installed, just use "import paho.mqtt.client"
+    import os
+    import inspect
+    cmd_subfolder = os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],"../src")))
+    if cmd_subfolder not in sys.path:
+        sys.path.insert(0, cmd_subfolder)
+    import paho.mqtt.client as mqtt
+
+def on_connect(mqttc, obj, rc):
+    print "Connected to %s:%s" % (mqttc._host, mqttc._port)
+
+def on_message(mqttc, obj, msg):
+    print(msg.topic+" "+str(msg.qos)+" "+str(msg.payload))
+
+def on_publish(mqttc, obj, mid):
+    print("mid: "+str(mid))
+
+def on_subscribe(mqttc, obj, mid, granted_qos):
+    print("Subscribed: "+str(mid)+" "+str(granted_qos))
+
+def on_log(mqttc, obj, level, string):
+    print(string)
+
+# If you want to use a specific client id, use
+# mqttc = mqtt.Client("client-id")
+# but note that the client id must be unique on the broker. Leaving the client
+# id parameter empty will generate a random id for you.
+mqttc = mqtt.Client()
+mqttc.on_message = on_message
+mqttc.on_connect = on_connect
+mqttc.on_publish = on_publish
+mqttc.on_subscribe = on_subscribe
+# Uncomment to enable debug messages
+#mqttc.on_log = on_log
+mqttc.connect_srv("mosquitto.org", 60)
+mqttc.subscribe("$SYS/broker/version", 0)
+
+
+rc = 0
+while rc == 0:
+    rc = mqttc.loop()
+
+print("rc: "+str(rc))
index 1ba6f9b9659aec3c2db43617361e10c1a9775ffd..13365b1dfb12c2af6f309e17c0519db01436e6f3 100755 (executable)
@@ -25,6 +25,11 @@ import struct
 import sys
 import threading
 import time
+HAVE_DNS = True
+try:
+    import dns.resolver
+except ImportError:
+    HAVE_DNS = False
 
 if sys.version_info[0] < 3:
     PROTOCOL_NAME = "MQIsdp"
@@ -540,6 +545,44 @@ class Client:
         self.connect_async(host, port, keepalive, bind_address)
         return self.reconnect()
 
+    def connect_srv(self, domain=None, keepalive=60, bind_address=""):
+        """Connect to a remote broker.
+
+        domain is the DNS domain to search for SRV records; if None,
+        try to determine local domain name.
+        keepalive and bind_address are as for connect()
+        """
+
+        if HAVE_DNS == False:
+            raise ValueError('No DNS resolver library found.')
+
+        if domain is None:
+            domain = socket.getfqdn()
+            domain = domain[domain.find('.') + 1:]
+
+        try:
+            rr = '_mqtt._tcp.%s' % domain
+            if self._ssl is not None:
+                # IANA specifies secure-mqtt (not mqtts) for port 8883
+                rr = '_secure-mqtt._tcp.%s' % domain
+            answers = []
+            for answer in dns.resolver.query(rr, dns.rdatatype.SRV):
+                addr = answer.target.to_text()[:-1]
+                answers.append((addr, answer.port, answer.priority, answer.weight))
+        except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer, dns.resolver.NoNameservers):
+            raise ValueError("No answer/NXDOMAIN for SRV in %s" % (domain))
+
+        # FIXME: doesn't account for weight
+        for answer in answers:
+            host, port, prio, weight = answer
+
+            try:
+                return self.connect(host, port, keepalive, bind_address)
+            except:
+                pass
+
+        raise ValueError("No SRV hosts responded")
+
     def connect_async(self, host, port=1883, keepalive=60, bind_address=""):
         """Connect to a remote broker asynchronously. This is a non-blocking
         connect call that can be used with loop_start() to provide very quick