Skip to content

username/password support #6

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
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
58 changes: 47 additions & 11 deletions MQTT.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ def connectionLost(self, reason):
pass

def connectReceived(self, clientID, keepalive, willTopic,
willMessage, willQoS, willRetain, cleanStart):
willMessage, willQos, willRetain, cleanStart):
pass

def connackReceived(self, status):
Expand Down Expand Up @@ -276,21 +276,34 @@ def disconnectReceived(self):
pass

def connect(self, clientID, keepalive=3000, willTopic=None,
willMessage=None, willQoS=0, willRetain=False,
cleanStart=True):
willMessage=None, willQos=0, willRetain=0,
cleanStart=0, username=None, password=None):
header = bytearray()
varHeader = bytearray()
payload = bytearray()

varHeader.extend(self._encodeString("MQIsdp"))
varHeader.append(3)

if willMessage is None or willTopic is None:
# Clean start, no will message
varHeader.append(0 << 2 | cleanStart << 1)
if username and password:
username_flag = 1
password_flag = 1
else:
varHeader.append(willRetain << 5 | willQoS << 3
| 1 << 2 | cleanStart << 1)
username_flag = 0
password_flag = 0

if willQos and willRetain and willTopic and willMessage:
will_flag = 1
else:
will_flag = 0

varHeader.append(username_flag << 7 |
password_flag << 6 |
willRetain << 5 |
willQos << 4 |
will_flag << 2 |
cleanStart << 1 |
0)

varHeader.extend(self._encodeValue(keepalive/1000))

Expand All @@ -299,6 +312,10 @@ def connect(self, clientID, keepalive=3000, willTopic=None,
payload.extend(self._encodeString(willTopic))
payload.extend(self._encodeString(willMessage))

if username_flag and password_flag:
payload.extend(self._encodeString(username))
payload.extend(self._encodeString(password))

header.append(0x01 << 4)
header.extend(self._encodeLength(len(varHeader) + len(payload)))

Expand Down Expand Up @@ -546,7 +563,18 @@ def _decodeValue(self, valueArray):
class MQTTClient(MQTTProtocol):

def __init__(self, clientId=None, keepalive=None, willQos=0,
willTopic=None, willMessage=None, willRetain=False):
willTopic=None, willMessage=None, willRetain=False,
username=None, password=None):

self.username = username
self.password = password

if username and password:
self.username_flag = 1
self.password_flag = 1
else:
self.username_flag = 0
self.password_flag = 0

if clientId is not None:
self.clientId = clientId
Expand All @@ -564,8 +592,16 @@ def __init__(self, clientId=None, keepalive=None, willQos=0,
self.willRetain = willRetain

def connectionMade(self):
self.connect(self.clientId, self.keepalive, self.willTopic,
self.willMessage, self.willQos, self.willRetain, True)
self.connect(clientID=self.clientId,
keepalive=self.keepalive,
willTopic=self.willTopic,
willMessage=self.willMessage,
willQos=self.willQos,
willRetain=self.willRetain,
cleanStart=True,
username=self.username,
password=self.password)


def connackReceived(self, status):
if status == 0:
Expand Down
89 changes: 89 additions & 0 deletions tests/test_commands.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
from StringIO import StringIO
from twisted.trial import unittest
from twisted.test import proto_helpers
from twisted.internet.protocol import ClientFactory
from MQTT import MQTTClient


class MQTTClientFactory(ClientFactory):
username = "testuser"
password = "testpwd"

def buildProtocol(self, addr):
return MQTTClient(username=self.username, password=self.password)

class CommandsTestCase(unittest.TestCase):
def setUp(self):
factory = MQTTClientFactory()
self.proto = factory.buildProtocol(('127.0.0.1', 0))
self.tr = proto_helpers.StringTransport()
self.proto.makeConnection(self.tr)

def _make_fixed_header(self, command, dup, qos, retain, remainning_length):
header = bytearray()
header.append(command << 4 | dup << 3 | qos << 1 | retain)
header.extend(remainning_length)
return header

def _make_variable_header_connect(self,
protocol_name,
version,
user_name_flag,
password_flag,
will_retain,
will_qos,
will_flag,
clean_session,
keep_alive_timer):
header = bytearray()
header.extend(self.proto._encodeString(protocol_name))
header.append(version)

header.append(user_name_flag << 7 |
password_flag << 6 |
will_retain << 5 |
will_qos << 4 |
will_flag << 2 |
clean_session << 1 |
0)
header.extend(self.proto._encodeValue(keep_alive_timer / 1000))
return header

def _make_payload_connect(self,
client_id,
will_topic,
will_message,
user_name,
password):
payload = bytearray()

if client_id:
payload.extend(self.proto._encodeString(client_id))

if will_message and will_topic:
payload.extend(self.proto._encodeString(will_topic))
payload.extend(self.proto._encodeString(will_message))

if user_name and password:
payload.extend(self.proto._encodeString(user_name))
payload.extend(self.proto._encodeString(password))

return payload

def test_connect(self):
"""
test connect command
"""

""" when default parameters """

variable_header = self._make_variable_header_connect("MQIsdp", 3, 1, 1, 0, 0, 0, 1, 3000)
payload = self._make_payload_connect(self.proto.clientId, None, None, "testuser", "testpwd")
fixed_header = self._make_fixed_header(0x01, 0, 0, 0, self.proto._encodeLength(len(variable_header) + len(payload)))

st = StringIO()
st.write(fixed_header)
st.write(variable_header)
st.write(payload)
self.assertEqual(self.proto.transport.value(), "".join(
map(lambda x: str(x), [fixed_header, variable_header, payload])))