diff --git a/extmod/modussl_axtls.c b/extmod/modussl_axtls.c
index 2dab6ff49146c3ce63e116a5dfa6bc9549dcc29a..b559b1358002e7417f22e55ffcb30eb32be3c51d 100644
--- a/extmod/modussl_axtls.c
+++ b/extmod/modussl_axtls.c
@@ -3,7 +3,7 @@
  *
  * The MIT License (MIT)
  *
- * Copyright (c) 2015-2017 Paul Sokolovsky
+ * Copyright (c) 2015-2019 Paul Sokolovsky
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -41,6 +41,7 @@ typedef struct _mp_obj_ssl_socket_t {
     SSL *ssl_sock;
     byte *buf;
     uint32_t bytes_left;
+    bool blocking;
 } mp_obj_ssl_socket_t;
 
 struct ssl_args {
@@ -48,6 +49,7 @@ struct ssl_args {
     mp_arg_val_t cert;
     mp_arg_val_t server_side;
     mp_arg_val_t server_hostname;
+    mp_arg_val_t do_handshake;
 };
 
 STATIC const mp_obj_type_t ussl_socket_type;
@@ -62,8 +64,12 @@ STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) {
     o->buf = NULL;
     o->bytes_left = 0;
     o->sock = sock;
+    o->blocking = true;
 
     uint32_t options = SSL_SERVER_VERIFY_LATER;
+    if (!args->do_handshake.u_bool) {
+        options |= SSL_CONNECT_IN_PARTS;
+    }
     if (args->key.u_obj != mp_const_none) {
         options |= SSL_NO_DEFAULT_KEY;
     }
@@ -97,17 +103,14 @@ STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) {
 
         o->ssl_sock = ssl_client_new(o->ssl_ctx, (long)sock, NULL, 0, ext);
 
-        int res = ssl_handshake_status(o->ssl_sock);
-        // Pointer to SSL_EXTENSIONS as being passed to ssl_client_new()
-        // is saved in ssl_sock->extensions.
-        // As of axTLS 2.1.3, extensions aren't used beyond the initial
-        // handshake, and that's pretty much how it's expected to be. So
-        // we allocate them on stack and reset the pointer after handshake.
+        if (args->do_handshake.u_bool) {
+            int res = ssl_handshake_status(o->ssl_sock);
 
-        if (res != SSL_OK) {
-            printf("ssl_handshake_status: %d\n", res);
-            ssl_display_error(res);
-            mp_raise_OSError(MP_EIO);
+            if (res != SSL_OK) {
+                printf("ssl_handshake_status: %d\n", res);
+                ssl_display_error(res);
+                mp_raise_OSError(MP_EIO);
+            }
         }
 
     }
@@ -133,8 +136,18 @@ STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errc
         mp_int_t r = ssl_read(o->ssl_sock, &o->buf);
         if (r == SSL_OK) {
             // SSL_OK from ssl_read() means "everything is ok, but there's
-            // no user data yet". So, we just keep reading.
-            continue;
+            // no user data yet". It may happen e.g. if handshake is not
+            // finished yet. The best way we can treat it is by returning
+            // EAGAIN. This may be a bit unexpected in blocking mode, but
+            // default is to perform complete handshake in constructor, so
+            // this should not happen in blocking mode. On the other hand,
+            // in nonblocking mode EAGAIN (comparing to the alternative of
+            // looping) is really preferrable.
+            if (o->blocking) {
+                continue;
+            } else {
+                goto eagain;
+            }
         }
         if (r < 0) {
             if (r == SSL_CLOSE_NOTIFY || r == SSL_ERROR_CONN_LOST) {
@@ -142,6 +155,7 @@ STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errc
                 return 0;
             }
             if (r == SSL_EAGAIN) {
+eagain:
                 r = MP_EAGAIN;
             }
             *errcode = r;
@@ -187,12 +201,14 @@ STATIC mp_uint_t socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, i
 }
 
 STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) {
-    // Currently supports only blocking mode
-    (void)self_in;
-    if (!mp_obj_is_true(flag_in)) {
-        mp_raise_NotImplementedError(NULL);
-    }
-    return mp_const_none;
+    mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(self_in);
+    mp_obj_t sock = o->sock;
+    mp_obj_t dest[3];
+    mp_load_method(sock, MP_QSTR_setblocking, dest);
+    dest[2] = flag_in;
+    mp_obj_t res = mp_call_method_n_kw(1, 0, dest);
+    o->blocking = mp_obj_is_true(flag_in);
+    return res;
 }
 STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking);
 
@@ -234,6 +250,7 @@ STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_
         { MP_QSTR_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} },
         { MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
         { MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} },
+        { MP_QSTR_do_handshake, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
     };
 
     // TODO: Check that sock implements stream protocol
diff --git a/tests/extmod/ussl_basic.py.exp b/tests/extmod/ussl_basic.py.exp
index cb9c51f7a12633d6c0c12adbdee27bef7bf27b7a..57eed8c57f4d9a48061b86a9b20f006742822cf2 100644
--- a/tests/extmod/ussl_basic.py.exp
+++ b/tests/extmod/ussl_basic.py.exp
@@ -4,6 +4,5 @@ wrap_socket: OSError(5,)
 setblocking: NotImplementedError
 4
 b''
-read: OSError(-261,)
 read: OSError(9,)
 write: OSError(9,)