From 04db848dc7c7356a38f809b5efdd4699a41aa54f Mon Sep 17 00:00:00 2001 From: danicampora Date: Tue, 20 Oct 2015 15:04:55 +0200 Subject: [PATCH] docs: Add usocket and ussl modules' documentation. --- cc3200/mods/modusocket.c | 17 +++- cc3200/mods/modussl.c | 4 +- docs/library/index.rst | 1 + docs/library/network.rst | 10 +-- docs/library/usocket.rst | 186 +++++++++++++++++++++++++++++++++++++-- docs/library/ussl.rst | 56 ++++++++++++ docs/library/wipy.rst | 6 +- 7 files changed, 265 insertions(+), 15 deletions(-) create mode 100644 docs/library/ussl.rst diff --git a/cc3200/mods/modusocket.c b/cc3200/mods/modusocket.c index ad59493ea..42163b68b 100644 --- a/cc3200/mods/modusocket.c +++ b/cc3200/mods/modusocket.c @@ -397,6 +397,21 @@ STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t blocking) { } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking); +STATIC mp_obj_t socket_makefile(mp_uint_t n_args, const mp_obj_t *args) { + // TODO: CPython explicitly says that closing the returned object doesn't + // close the original socket (Python2 at all says that fd is dup()ed). But + // we save on the bloat. + mod_network_socket_obj_t *self = args[0]; + if (n_args > 1) { + const char *mode = mp_obj_str_get_str(args[1]); + if (strcmp(mode, "rb") && strcmp(mode, "wb")) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + } + } + return self; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_makefile_obj, 1, 6, socket_makefile); + STATIC const mp_map_elem_t socket_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___del__), (mp_obj_t)&socket_close_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&socket_close_obj }, @@ -412,7 +427,7 @@ STATIC const mp_map_elem_t socket_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_setsockopt), (mp_obj_t)&socket_setsockopt_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_settimeout), (mp_obj_t)&socket_settimeout_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_setblocking), (mp_obj_t)&socket_setblocking_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_makefile), (mp_obj_t)&mp_identity_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_makefile), (mp_obj_t)&socket_makefile_obj }, // stream methods { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj }, diff --git a/cc3200/mods/modussl.c b/cc3200/mods/modussl.c index a11d2b2ef..ce3067d96 100644 --- a/cc3200/mods/modussl.c +++ b/cc3200/mods/modussl.c @@ -61,7 +61,7 @@ STATIC const mp_obj_type_t ssl_socket_type; /******************************************************************************/ // Micro Python bindings; SSL class -// ssl socket inherits from normal socket, so we take its +// ssl sockets inherit from normal socket, so we take its // locals and stream methods STATIC const mp_obj_type_t ssl_socket_type = { { &mp_type_type }, @@ -116,7 +116,7 @@ STATIC mp_obj_t mod_ssl_wrap_socket(mp_uint_t n_args, const mp_obj_t *pos_args, // create the ssl socket mp_obj_ssl_socket_t *ssl_sock = m_new_obj(mp_obj_ssl_socket_t); - // ssl socket inherits all properties from the original socket + // ssl sockets inherit all properties from the original socket memcpy (&ssl_sock->sock_base, &((mod_network_socket_obj_t *)args[0].u_obj)->sock_base, sizeof(mod_network_socket_base_t)); ssl_sock->base.type = &ssl_socket_type; ssl_sock->sock_base.cert_req = (args[4].u_int == SSL_CERT_REQUIRED) ? true : false; diff --git a/docs/library/index.rst b/docs/library/index.rst index 81a9824ef..60882598e 100644 --- a/docs/library/index.rst +++ b/docs/library/index.rst @@ -92,6 +92,7 @@ it will fallback to loading the built-in ``ujson`` module. ujson.rst ure.rst usocket.rst + ussl.rst .. only:: port_wipy diff --git a/docs/library/network.rst b/docs/library/network.rst index c0115864d..0b9acf642 100644 --- a/docs/library/network.rst +++ b/docs/library/network.rst @@ -378,16 +378,16 @@ For example:: .. method:: wlan.isconnected() In case of STA mode, returns ``True`` if connected to a wifi access point and has a valid IP address. - In AP mode returns ``True`` when a station is connected. Returns ``False`` otherwise. + In AP mode returns ``True`` when a station is connected, ``False`` otherwise. .. method:: wlan.ifconfig(if_id=0, config=['dhcp' or configtuple]) With no parameters given eturns a 4-tuple of ``(ip, subnet_mask, gateway, DNS_server)``. - + if ``'dhcp'`` is passed as a parameter then the DHCP client is enabled and the IP params are negotiated with the AP. - - if the 4-tuple config is given then a static IP is configured. For example:: + + If the 4-tuple config is given then a static IP is configured. For instance:: wlan.ifconfig(config=('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8')) @@ -423,7 +423,7 @@ For example:: - ``handler`` is the function that gets called when the irq is triggered. - ``wake`` must be ``machine.SLEEP``. - Returns a irq object. + Returns an irq object. Constants --------- diff --git a/docs/library/usocket.rst b/docs/library/usocket.rst index cf79973f1..a83a87d2e 100644 --- a/docs/library/usocket.rst +++ b/docs/library/usocket.rst @@ -1,17 +1,193 @@ +******************************* :mod:`usocket` -- socket module -=============================== +******************************* .. module:: usocket :synopsis: socket module -Socket functionality. +This module provides access to the BSD socket interface. Functions --------- -.. function:: getaddrinfo(host, port) +.. function:: socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP) + Create a new socket using the given address family, socket type and protocol number. -.. function:: socket(family=AF_INET, type=SOCK_STREAM, fileno=-1) + .. only:: port_wipy - Create a socket. + .. note:: + + SSL sockets need to be created the following way before wrapping them with + ``ssl.wrap_socket``:: + + import socket + import ssl + s = socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC) + ss = ssl.wrap_socket(s) + +.. function:: socket.getaddrinfo(host, port) + + Translate the host/port argument into a sequence of 5-tuples that contain all the + necessary arguments for creating a socket connected to that service. The list of + 5-tuples has following structure:: + + (family, type, proto, canonname, sockaddr) + + The following example shows how to connect to a given url:: + + s = socket.socket() + s.connect(socket.getaddrinfo('www.micropython.org', 80)[0][4]) + +Exceptions +---------- + +.. data:: socket.error +.. data:: socket.timeout + +Constants +--------- + +.. data:: socket.AF_INET + + family types + +.. data:: socket.SOCK_STREAM +.. data:: socket.SOCK_DGRAM + + socket types + +.. data:: socket.IPPROTO_UDP +.. data:: socket.IPPROTO_TCP +.. data:: socket.IPPROTO_SEC + + protocol numbers + +class socket +============ + +Methods +------- + + .. method:: socket.close + + Mark the socket closed. Once that happens, all future operations on the socket + object will fail. The remote end will receive no more data (after queued data is flushed). + + Sockets are automatically closed when they are garbage-collected, but it is recommended + to close() them explicitly, or to use a with statement around them. + + .. method:: socket.bind(address) + + Bind the socket to address. The socket must not already be bound. The format of ``address`` + is: ``(ipv4 address, port)`` + + .. method:: socket.listen([backlog]) + + Enable a server to accept connections. If backlog is specified, it must be at least 0 + (if it's lower, it will be set to 0); and specifies the number of unaccepted connections + tha the system will allow before refusing new connections. If not specified, a default + reasonable value is chosen. + + .. method:: socket.accept() + + Accept a connection. The socket must be bound to an address and listening for connections. + The return value is a pair (conn, address) where conn is a new socket object usable to send + and receive data on the connection, and address is the address bound to the socket on the + other end of the connection. + + .. method:: socket.connect(address) + + Connect to a remote socket at address. The format of address is: ``(ipv4 address, port)`` + + .. method:: socket.send(bytes) + + Send data to the socket. The socket must be connected to a remote socket. + + .. method:: socket.sendall(bytes) + + Send data to the socket. The socket must be connected to a remote socket. + + .. method:: socket.recv(bufsize) + + Receive data from the socket. The return value is a bytes object representing the data + received. The maximum amount of data to be received at once is specified by bufsize. + + .. method:: socket.sendto(bytes, address) + + Send data to the socket. The socket should not be connected to a remote socket, since the + destination socket is specified by address. The ``address`` has the same format as the + rest of the methods, see above. + + .. method:: socket.recvfrom(bufsize) + + Receive data from the socket. The return value is a pair (bytes, address) where bytes is a + bytes object representing the data received and address is the address of the socket sending + the data. + + .. method:: socket.setsockopt(level, optname, value) + + Set the value of the given socket option. The needed symbolic constants are defined in the + socket module (SO_* etc.). The value can be an integer or a bytes-like object representing + a buffer. + + .. method:: socket.settimeout(value) + + Set a timeout on blocking socket operations. The value argument can be a nonnegative floating + point number expressing seconds, or None. If a non-zero value is given, subsequent socket operations + will raise a timeout exception if the timeout period value has elapsed before the operation has + completed. If zero is given, the socket is put in non-blocking mode. If None is given, the socket + is put in blocking mode. + + .. method:: socket.setblocking(flag) + + Set blocking or non-blocking mode of the socket: if flag is false, the socket is set to non-blocking, + else to blocking mode. + + This method is a shorthand for certain ``settimeout()`` calls:: + + sock.setblocking(True) is equivalent to sock.settimeout(None) + sock.setblocking(False) is equivalent to sock.settimeout(0.0) + + .. method:: socket.makefile(mode='rb') + + Return a file object associated with the socket. The exact returned type depends on the arguments + given to makefile(). The support is limited to binary modes only ('rb' and 'wb'). + CPython's arguments: ``encoding``, ``errors`` and ``newline`` are not supported. + + The socket must be in blocking mode; it can have a timeout, but the file object’s internal buffer + may end up in a inconsistent state if a timeout occurs. + + .. note:: + + **CPython difference:** closing the file object returned by makefile() WILL close the + original socket as well. + + .. method:: socket.read(size) + + Read up to size bytes from the socket. Return a bytes object. If ``size`` is not given, it + behaves just like ``socket.readall()``, see below. + + .. method:: socket.readall() + + Read all data available from the socket until ``EOF``. This function will not return until + the socket is closed. + + .. method:: socket.readinto(buf[, nbytes]) + + Read bytes into the ``buf``. If ``nbytes`` is specified then read at most + that many bytes. Otherwise, read at most ``len(buf)`` bytes. + + Return value: number of bytes read and stored into ``buf``. + + .. method:: socket.readline() + + Read a line, ending in a newline character. + + Return value: the line read. + + .. method:: socket.write(buf) + + Write the buffer of bytes to the socket. + + Return value: number of bytes written. diff --git a/docs/library/ussl.rst b/docs/library/ussl.rst new file mode 100644 index 000000000..9e97fac50 --- /dev/null +++ b/docs/library/ussl.rst @@ -0,0 +1,56 @@ +:mod:`ussl` -- ssl module +=============================== + +.. module:: ussl + :synopsis: TLS/SSL wrapper for socket objects + +This module provides access to Transport Layer Security (often known as +“Secure Sockets Layer”) encryption and peer authentication facilities for +network sockets, both client-side and server-side. + +Functions +--------- + +.. function:: ssl.wrap_socket(sock, keyfile=None, certfile=None, server_side=False, cert_reqs=CERT_NONE, ca_certs=None) + + Takes an instance sock of socket.socket, and returns an instance of ssl.SSLSocket, a subtype of + ``socket.socket``, which wraps the underlying socket in an SSL context. sock must be a ``SOCK_STREAM`` + socket and protocol number ``socket.IPPROTO_SEC``; other socket types are unsupported. Example:: + + import socket + import ssl + s = socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC) + ss = ssl.wrap_socket(s) + ss.connect(socket.getaddrinfo('www.google.com', 443)[0][4]) + + Certificates must be used in order to validate the other side of the connection, and also to + authenticate ourselves with the other end. Such certificates must be stored as files using the + FTP server, and they must be placed in specific paths with specific names. + + - The certificate to validate the other side goes in: **'/flash/cert/ca.pem'** + - The certificate to authenticate ourselves goes in: **'/flash/cert/cert.pem'** + - The key for our own certificate goes in: **'/flash/cert/private.key'** + + For instance to connect to the Blynk servers using certificates, take the file ``ca.pem`` located + in the `blynk examples folder `_ + and put it in '/flash/cert/'. Then do:: + + import socket + import ssl + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC) + ss = ssl.wrap_socket(s, cert_reqs=ssl.CERT_REQUIRED, ca_certs='/flash/cert/ca.pem') + ss.connect(socket.getaddrinfo('cloud.blynk.cc', 8441)[0][4]) + +Exceptions +---------- + +.. data:: ssl.SSLError + +Constants +--------- + +.. data:: ssl.CERT_NONE +.. data:: ssl.CERT_OPTIONAL +.. data:: ssl.CERT_REQUIRED + + supported values in ``cert_reqs`` diff --git a/docs/library/wipy.rst b/docs/library/wipy.rst index 66aecd053..cdece7b82 100644 --- a/docs/library/wipy.rst +++ b/docs/library/wipy.rst @@ -1,5 +1,6 @@ +************************************* :mod:`wipy` -- WiPy specific features -===================================== +************************************* .. module:: wipy :synopsis: WiPy specific features @@ -12,4 +13,5 @@ Functions .. function:: heartbeat([enable]) - Get or set the state (enabled or disabled) of the heartbeat LED. + Get or set the state (enabled or disabled) of the heartbeat LED. Accepts and + returns boolean values (``True`` or ``False``).