Skip to content

Commit c124e22

Browse files
committed
Add basic SSL support
This is a partial support as the CA certificate is not validated. This is so as this functionality is not implemented in all micropython ports. For example, it isn't currently supported in the esp32 port although a draft of the feature has been published: micropython/micropython#5998 As the CA functionality is not there, we cannot use this parameter do decide when to switch to SSL mode as done in the CPython version. Instead we enable SSL when connecting to port 443 or 8443 which are well known ports used for TLS communications. One more thing is that this library relies on short reads to get data from the socket as it always ask for the max buffer length when reading. In micropython, the interface provided for SSL socket is only the one of a stream which doesn't allow short reads. To go around this we change the socket to non blocking which which has the side-effect of allowing short reads. However we then need to do manual polling and timeout on the socket which we do here.
1 parent 6a8a62a commit c124e22

File tree

1 file changed

+24
-2
lines changed

1 file changed

+24
-2
lines changed

blynklib_mp.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
__version__ = '0.2.6'
66

77
import usocket as socket
8+
import ussl as ssl
89
import utime as time
910
import ustruct as struct
1011
import uselect as select
@@ -125,6 +126,7 @@ def internal_msg(self, *args):
125126
class Connection(Protocol):
126127
SOCK_MAX_TIMEOUT = const(5)
127128
SOCK_TIMEOUT = 0.05
129+
SOCK_SSL_TIMEOUT = const(1)
128130
EAGAIN = const(11)
129131
ETIMEDOUT = const(60)
130132
RETRIES_TX_DELAY = const(2)
@@ -164,15 +166,28 @@ def send(self, data):
164166
try:
165167
retries -= 1
166168
self._last_send_time = ticks_ms()
167-
return self._socket.send(data)
169+
try:
170+
bytes_written = self._socket.send(data)
171+
except AttributeError:
172+
bytes_written = self._socket.write(data)
173+
return bytes_written
168174
except (IOError, OSError):
169175
sleep_ms(self.RETRIES_TX_DELAY)
170176

171177
def receive(self, length, timeout):
172178
d_buff = b''
173179
try:
174180
self._set_socket_timeout(timeout)
175-
d_buff += self._socket.recv(length)
181+
try:
182+
d_buff += self._socket.recv(length)
183+
except AttributeError:
184+
timeout = self.SOCK_SSL_TIMEOUT
185+
while not d_buff and timeout > 0:
186+
ret = self._socket.read(length)
187+
if ret:
188+
d_buff += ret
189+
timeout -= self.SOCK_TIMEOUT
190+
time.sleep(self.SOCK_TIMEOUT)
176191
if len(d_buff) >= length:
177192
d_buff = d_buff[:length]
178193
return d_buff
@@ -203,6 +218,13 @@ def _get_socket(self):
203218
self._socket = socket.socket()
204219
self._socket.connect(socket.getaddrinfo(self.server, self.port)[0][-1])
205220
self._set_socket_timeout(self.SOCK_TIMEOUT)
221+
if self.port == 443 or self.port == 8443:
222+
self.log('Using SSL socket...')
223+
self._socket = ssl.wrap_socket(self._socket)
224+
# Short reads are not supported in ssl mode. We work around
225+
# this by setting the socket non blocking and doing manual
226+
# polling/timeout.
227+
self._socket.setblocking(False)
206228
self.log('Connected to server')
207229
except Exception as g_exc:
208230
raise BlynkError('Server connection failed: {}'.format(g_exc))

0 commit comments

Comments
 (0)