mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			Merge pull request #11357 from kivaisan/offloaded_tlssocket_bg96
Offloaded TLSSocket and BG96 support for itpull/11625/head
						commit
						eeb033f814
					
				| 
						 | 
				
			
			@ -84,15 +84,15 @@ nsapi_error_t tlssocket_connect_to_srv(TLSSocket &sock, uint16_t port)
 | 
			
		|||
 | 
			
		||||
    printf("MBED: Server '%s', port %d\n", tls_addr.get_ip_address(), tls_addr.get_port());
 | 
			
		||||
 | 
			
		||||
    nsapi_error_t err = sock.set_root_ca_cert(tls_global::cert);
 | 
			
		||||
    nsapi_error_t err = sock.open(NetworkInterface::get_default_instance());
 | 
			
		||||
    if (err != NSAPI_ERROR_OK) {
 | 
			
		||||
        printf("Error from sock.set_root_ca_cert: %d\n", err);
 | 
			
		||||
        printf("Error from sock.open: %d\n", err);
 | 
			
		||||
        return err;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    err = sock.open(NetworkInterface::get_default_instance());
 | 
			
		||||
    err = sock.set_root_ca_cert(tls_global::cert);
 | 
			
		||||
    if (err != NSAPI_ERROR_OK) {
 | 
			
		||||
        printf("Error from sock.open: %d\n", err);
 | 
			
		||||
        printf("Error from sock.set_root_ca_cert: %d\n", err);
 | 
			
		||||
        return err;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -48,6 +48,10 @@ static nsapi_error_t _tlssocket_connect_to_daytime_srv(TLSSocket &sock)
 | 
			
		|||
        return err;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.set_root_ca_cert(tls_global::cert));
 | 
			
		||||
 | 
			
		||||
    sock.set_timeout(10000); // Set timeout for case TLSSocket does not support peer closed indication
 | 
			
		||||
 | 
			
		||||
    return sock.connect(tls_addr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -62,7 +66,6 @@ void TLSSOCKET_ENDPOINT_CLOSE()
 | 
			
		|||
    tc_exec_time.start();
 | 
			
		||||
 | 
			
		||||
    TLSSocket sock;
 | 
			
		||||
    TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.set_root_ca_cert(tls_global::cert));
 | 
			
		||||
    if (_tlssocket_connect_to_daytime_srv(sock) != NSAPI_ERROR_OK) {
 | 
			
		||||
        TEST_FAIL();
 | 
			
		||||
        return;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,12 +28,18 @@ using namespace utest::v1;
 | 
			
		|||
 | 
			
		||||
void TLSSOCKET_HANDSHAKE_INVALID()
 | 
			
		||||
{
 | 
			
		||||
    const int https_port = 443;
 | 
			
		||||
    SKIP_IF_TCP_UNSUPPORTED();
 | 
			
		||||
    TLSSocket sock;
 | 
			
		||||
    TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.open(NetworkInterface::get_default_instance()));
 | 
			
		||||
    TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.set_root_ca_cert(tls_global::cert));
 | 
			
		||||
    TEST_ASSERT_EQUAL(NSAPI_ERROR_AUTH_FAILURE,
 | 
			
		||||
                      sock.connect("google.com", 443)); // 443 is https port.
 | 
			
		||||
    TEST_ASSERT_EQUAL(NSAPI_ERROR_AUTH_FAILURE, sock.connect("expired.badssl.com", https_port));
 | 
			
		||||
    TEST_ASSERT_EQUAL(NSAPI_ERROR_AUTH_FAILURE, sock.connect("wrong.host.badssl.com", https_port));
 | 
			
		||||
    TEST_ASSERT_EQUAL(NSAPI_ERROR_AUTH_FAILURE, sock.connect("self-signed.badssl.com", https_port));
 | 
			
		||||
    TEST_ASSERT_EQUAL(NSAPI_ERROR_AUTH_FAILURE, sock.connect("untrusted-root.badssl.com", https_port));
 | 
			
		||||
    TEST_ASSERT_EQUAL(NSAPI_ERROR_AUTH_FAILURE, sock.connect("revoked.badssl.com", https_port));
 | 
			
		||||
    TEST_ASSERT_EQUAL(NSAPI_ERROR_AUTH_FAILURE, sock.connect("pinning-test.badssl.com", https_port));
 | 
			
		||||
    TEST_ASSERT_EQUAL(NSAPI_ERROR_AUTH_FAILURE, sock.connect("sha1-intermediate.badssl.com", https_port));
 | 
			
		||||
    TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.close());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -244,7 +244,7 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_bind)
 | 
			
		|||
    MyStack st(at, 0, IPV6_STACK);
 | 
			
		||||
    SocketAddress addr;
 | 
			
		||||
    ATHandler_stub::nsapi_error_value = NSAPI_ERROR_ALREADY;
 | 
			
		||||
    EXPECT_EQ(st.socket_bind(NULL, addr), NSAPI_ERROR_DEVICE_ERROR);
 | 
			
		||||
    EXPECT_EQ(st.socket_bind(NULL, addr), NSAPI_ERROR_NO_SOCKET);
 | 
			
		||||
 | 
			
		||||
    EXPECT_EQ(st.socket_bind(&st.socket, addr), NSAPI_ERROR_ALREADY);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -267,7 +267,7 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_connect)
 | 
			
		|||
 | 
			
		||||
    MyStack st(at, 0, IPV6_STACK);
 | 
			
		||||
    SocketAddress addr;
 | 
			
		||||
    EXPECT_EQ(st.socket_connect(NULL, addr), NSAPI_ERROR_DEVICE_ERROR);
 | 
			
		||||
    EXPECT_EQ(st.socket_connect(NULL, addr), NSAPI_ERROR_NO_SOCKET);
 | 
			
		||||
 | 
			
		||||
    EXPECT_EQ(st.socket_connect(&st.socket, addr), NSAPI_ERROR_OK);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -290,9 +290,9 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_send)
 | 
			
		|||
    ATHandler at(&fh1, que, 0, ",");
 | 
			
		||||
 | 
			
		||||
    MyStack st(at, 0, IPV6_STACK);
 | 
			
		||||
    EXPECT_EQ(st.socket_send(NULL, "addr", 4), NSAPI_ERROR_DEVICE_ERROR);
 | 
			
		||||
    EXPECT_EQ(st.socket_send(NULL, "addr", 4), NSAPI_ERROR_NO_SOCKET);
 | 
			
		||||
 | 
			
		||||
    EXPECT_EQ(st.socket_send(&st.socket, "addr", 4), NSAPI_ERROR_DEVICE_ERROR);
 | 
			
		||||
    EXPECT_EQ(st.socket_send(&st.socket, "addr", 4), NSAPI_ERROR_NO_CONNECTION);
 | 
			
		||||
 | 
			
		||||
    SocketAddress addr;
 | 
			
		||||
    st.max_sock_value = 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -312,7 +312,7 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_sendto)
 | 
			
		|||
    MyStack st(at, 0, IPV6_STACK);
 | 
			
		||||
 | 
			
		||||
    SocketAddress addr;
 | 
			
		||||
    EXPECT_EQ(st.socket_sendto(NULL, addr, "addr", 4), NSAPI_ERROR_DEVICE_ERROR);
 | 
			
		||||
    EXPECT_EQ(st.socket_sendto(NULL, addr, "addr", 4), NSAPI_ERROR_NO_SOCKET);
 | 
			
		||||
 | 
			
		||||
    st.max_sock_value = 1;
 | 
			
		||||
    st.bool_value = true;
 | 
			
		||||
| 
						 | 
				
			
			@ -334,7 +334,7 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_recv)
 | 
			
		|||
 | 
			
		||||
    MyStack st(at, 0, IPV6_STACK);
 | 
			
		||||
    char table[4];
 | 
			
		||||
    EXPECT_EQ(st.socket_recv(NULL, table, 4), NSAPI_ERROR_DEVICE_ERROR);
 | 
			
		||||
    EXPECT_EQ(st.socket_recv(NULL, table, 4), NSAPI_ERROR_NO_SOCKET);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_recvfrom)
 | 
			
		||||
| 
						 | 
				
			
			@ -345,7 +345,7 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_recvfrom)
 | 
			
		|||
 | 
			
		||||
    MyStack st(at, 0, IPV6_STACK);
 | 
			
		||||
    char table[4];
 | 
			
		||||
    EXPECT_EQ(st.socket_recvfrom(NULL, NULL, table, 4), NSAPI_ERROR_DEVICE_ERROR);
 | 
			
		||||
    EXPECT_EQ(st.socket_recvfrom(NULL, NULL, table, 4), NSAPI_ERROR_NO_SOCKET);
 | 
			
		||||
 | 
			
		||||
    SocketAddress addr;
 | 
			
		||||
    st.max_sock_value = 1;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -161,7 +161,7 @@ nsapi_error_t AT_CellularStack::socket_close(nsapi_socket_t handle)
 | 
			
		|||
 | 
			
		||||
    struct CellularSocket *socket = (struct CellularSocket *)handle;
 | 
			
		||||
    if (!socket) {
 | 
			
		||||
        return err;
 | 
			
		||||
        return NSAPI_ERROR_NO_SOCKET;
 | 
			
		||||
    }
 | 
			
		||||
    int sock_id = socket->id;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -197,7 +197,7 @@ nsapi_error_t AT_CellularStack::socket_bind(nsapi_socket_t handle, const SocketA
 | 
			
		|||
{
 | 
			
		||||
    struct CellularSocket *socket = (CellularSocket *)handle;
 | 
			
		||||
    if (!socket) {
 | 
			
		||||
        return NSAPI_ERROR_DEVICE_ERROR;
 | 
			
		||||
        return NSAPI_ERROR_NO_SOCKET;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (addr) {
 | 
			
		||||
| 
						 | 
				
			
			@ -225,14 +225,14 @@ nsapi_error_t AT_CellularStack::socket_bind(nsapi_socket_t handle, const SocketA
 | 
			
		|||
 | 
			
		||||
nsapi_error_t AT_CellularStack::socket_listen(nsapi_socket_t handle, int backlog)
 | 
			
		||||
{
 | 
			
		||||
    return NSAPI_ERROR_UNSUPPORTED;;
 | 
			
		||||
    return NSAPI_ERROR_UNSUPPORTED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nsapi_error_t AT_CellularStack::socket_connect(nsapi_socket_t handle, const SocketAddress &addr)
 | 
			
		||||
{
 | 
			
		||||
    CellularSocket *socket = (CellularSocket *)handle;
 | 
			
		||||
    if (!socket) {
 | 
			
		||||
        return NSAPI_ERROR_DEVICE_ERROR;
 | 
			
		||||
        return NSAPI_ERROR_NO_SOCKET;
 | 
			
		||||
    }
 | 
			
		||||
    socket->remoteAddress = addr;
 | 
			
		||||
    socket->connected = true;
 | 
			
		||||
| 
						 | 
				
			
			@ -242,14 +242,17 @@ nsapi_error_t AT_CellularStack::socket_connect(nsapi_socket_t handle, const Sock
 | 
			
		|||
 | 
			
		||||
nsapi_error_t AT_CellularStack::socket_accept(void *server, void **socket, SocketAddress *addr)
 | 
			
		||||
{
 | 
			
		||||
    return NSAPI_ERROR_UNSUPPORTED;;
 | 
			
		||||
    return NSAPI_ERROR_UNSUPPORTED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nsapi_size_or_error_t AT_CellularStack::socket_send(nsapi_socket_t handle, const void *data, unsigned size)
 | 
			
		||||
{
 | 
			
		||||
    CellularSocket *socket = (CellularSocket *)handle;
 | 
			
		||||
    if (!socket || !socket->connected) {
 | 
			
		||||
        return NSAPI_ERROR_DEVICE_ERROR;
 | 
			
		||||
    if (!socket) {
 | 
			
		||||
        return NSAPI_ERROR_NO_SOCKET;
 | 
			
		||||
    }
 | 
			
		||||
    if (!socket->connected) {
 | 
			
		||||
        return NSAPI_ERROR_NO_CONNECTION;
 | 
			
		||||
    }
 | 
			
		||||
    return socket_sendto(handle, socket->remoteAddress, data, size);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -258,7 +261,7 @@ nsapi_size_or_error_t AT_CellularStack::socket_sendto(nsapi_socket_t handle, con
 | 
			
		|||
{
 | 
			
		||||
    CellularSocket *socket = (CellularSocket *)handle;
 | 
			
		||||
    if (!socket) {
 | 
			
		||||
        return NSAPI_ERROR_DEVICE_ERROR;
 | 
			
		||||
        return NSAPI_ERROR_NO_SOCKET;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (socket->closed && !socket->rx_avail) {
 | 
			
		||||
| 
						 | 
				
			
			@ -324,7 +327,7 @@ nsapi_size_or_error_t AT_CellularStack::socket_recvfrom(nsapi_socket_t handle, S
 | 
			
		|||
{
 | 
			
		||||
    CellularSocket *socket = (CellularSocket *)handle;
 | 
			
		||||
    if (!socket) {
 | 
			
		||||
        return NSAPI_ERROR_DEVICE_ERROR;
 | 
			
		||||
        return NSAPI_ERROR_NO_SOCKET;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (socket->closed) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -110,6 +110,7 @@ protected:
 | 
			
		|||
            started(false),
 | 
			
		||||
            tx_ready(false),
 | 
			
		||||
            rx_avail(false),
 | 
			
		||||
            tls_socket(false),
 | 
			
		||||
            pending_bytes(0)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -127,6 +128,7 @@ protected:
 | 
			
		|||
        bool started; // socket has been opened on modem stack
 | 
			
		||||
        bool tx_ready; // socket is ready for sending on modem stack
 | 
			
		||||
        bool rx_avail; // socket has data for reading on modem stack
 | 
			
		||||
        bool tls_socket; // socket uses modem's internal TLS socket functionality
 | 
			
		||||
        nsapi_size_t pending_bytes; // The number of received bytes pending
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,6 +18,15 @@
 | 
			
		|||
#include <string.h>
 | 
			
		||||
#include "QUECTEL/BG96/QUECTEL_BG96_CellularStack.h"
 | 
			
		||||
#include "CellularLog.h"
 | 
			
		||||
#include "netsocket/TLSSocket.h"
 | 
			
		||||
 | 
			
		||||
// Ref: Quectel_BG96_SSL_AT_Commands_Manual, ch 2.1.1 AT+QSSLCFG
 | 
			
		||||
static const int BG96_SUPPORTED_SSL_VERSION     = 4; // All
 | 
			
		||||
static const char BG96_SUPPORTED_CIPHER_SUITE[] = "0xFFFF"; // Support all
 | 
			
		||||
 | 
			
		||||
// TODO: At the moment we support only one active SSL context
 | 
			
		||||
//       Later can be expanded to support multiple contexts. Modem supports IDs 0-5.
 | 
			
		||||
static const int sslctxID = 0;
 | 
			
		||||
 | 
			
		||||
using namespace mbed;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -25,12 +34,27 @@ QUECTEL_BG96_CellularStack::QUECTEL_BG96_CellularStack(ATHandler &atHandler, int
 | 
			
		|||
#ifdef MBED_CONF_CELLULAR_OFFLOAD_DNS_QUERIES
 | 
			
		||||
    , _dns_callback(NULL), _dns_version(NSAPI_UNSPEC)
 | 
			
		||||
#endif
 | 
			
		||||
    , _tls_sec_level(0)
 | 
			
		||||
{
 | 
			
		||||
    _at.set_urc_handler("+QIURC: \"recv", mbed::Callback<void()>(this, &QUECTEL_BG96_CellularStack::urc_qiurc_recv));
 | 
			
		||||
    _at.set_urc_handler("+QIURC: \"close", mbed::Callback<void()>(this, &QUECTEL_BG96_CellularStack::urc_qiurc_closed));
 | 
			
		||||
#ifdef MBED_CONF_CELLULAR_OFFLOAD_DNS_QUERIES
 | 
			
		||||
    _at.set_urc_handler("+QIURC: \"dnsgip\",", mbed::Callback<void()>(this, &QUECTEL_BG96_CellularStack::urc_qiurc_dnsgip));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    _at.set_urc_handler("+QSSLURC: \"recv", mbed::Callback<void()>(this, &QUECTEL_BG96_CellularStack::urc_qiurc_recv));
 | 
			
		||||
    _at.set_urc_handler("+QSSLURC: \"close", mbed::Callback<void()>(this, &QUECTEL_BG96_CellularStack::urc_qiurc_closed));
 | 
			
		||||
 | 
			
		||||
    // TODO: this needs to be handled properly, but now making just a quick hack
 | 
			
		||||
    // Close all SSL sockets if open. This can happen for example if application processor
 | 
			
		||||
    // was reset but modem not. Old sockets are still up and running and it prevents
 | 
			
		||||
    // new SSL configurations and creating new sockets.
 | 
			
		||||
    for (int i = 0; i < 12; i++) {
 | 
			
		||||
        _at.clear_error();
 | 
			
		||||
        tr_debug("Closing SSL socket %d...", i);
 | 
			
		||||
        _at.at_cmd_discard("+QSSLCLOSE", "=", "%d", i);
 | 
			
		||||
    }
 | 
			
		||||
    _at.clear_error();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QUECTEL_BG96_CellularStack::~QUECTEL_BG96_CellularStack()
 | 
			
		||||
| 
						 | 
				
			
			@ -52,7 +76,7 @@ nsapi_error_t QUECTEL_BG96_CellularStack::socket_connect(nsapi_socket_t handle,
 | 
			
		|||
    CellularSocket *socket = (CellularSocket *)handle;
 | 
			
		||||
 | 
			
		||||
    int modem_connect_id = -1;
 | 
			
		||||
    int err = -1;
 | 
			
		||||
    int err = NSAPI_ERROR_NO_CONNECTION;
 | 
			
		||||
 | 
			
		||||
    int request_connect_id = find_socket_index(socket);
 | 
			
		||||
    // assert here as its a programming error if the socket container doesn't contain
 | 
			
		||||
| 
						 | 
				
			
			@ -61,12 +85,15 @@ nsapi_error_t QUECTEL_BG96_CellularStack::socket_connect(nsapi_socket_t handle,
 | 
			
		|||
 | 
			
		||||
    _at.lock();
 | 
			
		||||
    if (socket->proto == NSAPI_TCP) {
 | 
			
		||||
        char ipdot[NSAPI_IP_SIZE];
 | 
			
		||||
        ip2dot(address, ipdot);
 | 
			
		||||
        _at.at_cmd_discard("+QIOPEN", "=", "%d%d%s%s%d%d%d", _cid, request_connect_id, "TCP",
 | 
			
		||||
                           ipdot, address.get_port(), socket->localAddress.get_port(), 0);
 | 
			
		||||
        if (socket->tls_socket) {
 | 
			
		||||
            if (_tls_sec_level == 0) {
 | 
			
		||||
                _at.unlock();
 | 
			
		||||
                return NSAPI_ERROR_AUTH_FAILURE;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        handle_open_socket_response(modem_connect_id, err);
 | 
			
		||||
            _at.at_cmd_discard("+QSSLOPEN", "=", "%d%d%d%s%d%d", _cid, sslctxID, request_connect_id,
 | 
			
		||||
                               address.get_ip_address(), address.get_port(), 0);
 | 
			
		||||
            handle_open_socket_response(modem_connect_id, err, true);
 | 
			
		||||
 | 
			
		||||
            if ((_at.get_last_error() == NSAPI_ERROR_OK) && err) {
 | 
			
		||||
                if (err == BG96_SOCKET_BIND_FAIL) {
 | 
			
		||||
| 
						 | 
				
			
			@ -74,12 +101,33 @@ nsapi_error_t QUECTEL_BG96_CellularStack::socket_connect(nsapi_socket_t handle,
 | 
			
		|||
                    _at.unlock();
 | 
			
		||||
                    return NSAPI_ERROR_PARAMETER;
 | 
			
		||||
                }
 | 
			
		||||
            _at.at_cmd_discard("+QICLOSE", "=", "%d", modem_connect_id);
 | 
			
		||||
                socket_close_impl(modem_connect_id);
 | 
			
		||||
 | 
			
		||||
                _at.at_cmd_discard("+QSSLOPEN", "=", "%d%d%d%s%d%d", _cid, sslctxID, request_connect_id,
 | 
			
		||||
                                   address.get_ip_address(), address.get_port(), 0);
 | 
			
		||||
                handle_open_socket_response(modem_connect_id, err, true);
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            char ipdot[NSAPI_IP_SIZE];
 | 
			
		||||
            ip2dot(address, ipdot);
 | 
			
		||||
            _at.at_cmd_discard("+QIOPEN", "=", "%d%d%s%s%d%d%d", _cid, request_connect_id, "TCP",
 | 
			
		||||
                               ipdot, address.get_port(), socket->localAddress.get_port(), 0);
 | 
			
		||||
 | 
			
		||||
            handle_open_socket_response(modem_connect_id, err, false);
 | 
			
		||||
 | 
			
		||||
            if ((_at.get_last_error() == NSAPI_ERROR_OK) && err) {
 | 
			
		||||
                if (err == BG96_SOCKET_BIND_FAIL) {
 | 
			
		||||
                    socket->id = -1;
 | 
			
		||||
                    _at.unlock();
 | 
			
		||||
                    return NSAPI_ERROR_PARAMETER;
 | 
			
		||||
                }
 | 
			
		||||
                socket_close_impl(modem_connect_id);
 | 
			
		||||
 | 
			
		||||
                _at.at_cmd_discard("+QIOPEN", "=", "%d%d%s%s%d%d%d", _cid, request_connect_id, "TCP",
 | 
			
		||||
                                   ipdot, address.get_port(), socket->localAddress.get_port(), 0);
 | 
			
		||||
 | 
			
		||||
            handle_open_socket_response(modem_connect_id, err);
 | 
			
		||||
                handle_open_socket_response(modem_connect_id, err, false);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -91,14 +139,14 @@ nsapi_error_t QUECTEL_BG96_CellularStack::socket_connect(nsapi_socket_t handle,
 | 
			
		|||
    nsapi_error_t ret_val = _at.get_last_error();
 | 
			
		||||
    _at.unlock();
 | 
			
		||||
 | 
			
		||||
    if ((ret_val == NSAPI_ERROR_OK) && (modem_connect_id == request_connect_id)) {
 | 
			
		||||
    if ((!err) && (ret_val == NSAPI_ERROR_OK) && (modem_connect_id == request_connect_id)) {
 | 
			
		||||
        socket->id = request_connect_id;
 | 
			
		||||
        socket->remoteAddress = address;
 | 
			
		||||
        socket->connected = true;
 | 
			
		||||
        return NSAPI_ERROR_OK;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return NSAPI_ERROR_NO_CONNECTION;
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void QUECTEL_BG96_CellularStack::urc_qiurc_recv()
 | 
			
		||||
| 
						 | 
				
			
			@ -182,21 +230,41 @@ bool QUECTEL_BG96_CellularStack::is_protocol_supported(nsapi_protocol_t protocol
 | 
			
		|||
nsapi_error_t QUECTEL_BG96_CellularStack::socket_close_impl(int sock_id)
 | 
			
		||||
{
 | 
			
		||||
    _at.set_at_timeout(BG96_CLOSE_SOCKET_TIMEOUT);
 | 
			
		||||
    nsapi_error_t err = _at.at_cmd_discard("+QICLOSE", "=", "%d", sock_id);
 | 
			
		||||
    nsapi_error_t err;
 | 
			
		||||
    CellularSocket *socket = find_socket(sock_id);
 | 
			
		||||
    if (socket && socket->tls_socket) {
 | 
			
		||||
        err = _at.at_cmd_discard("+QSSLCLOSE", "=", "%d", sock_id);
 | 
			
		||||
        if (err == NSAPI_ERROR_OK) {
 | 
			
		||||
            // Disable TLSSocket settings to prevent reuse on next socket without setting the values
 | 
			
		||||
            _tls_sec_level = 0;
 | 
			
		||||
            err = _at.at_cmd_discard("+QSSLCFG", "=\"seclevel\",", "%d%d", sslctxID, _tls_sec_level);
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        err = _at.at_cmd_discard("+QICLOSE", "=", "%d", sock_id);
 | 
			
		||||
    }
 | 
			
		||||
    _at.restore_at_timeout();
 | 
			
		||||
 | 
			
		||||
    return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void QUECTEL_BG96_CellularStack::handle_open_socket_response(int &modem_connect_id, int &err)
 | 
			
		||||
void QUECTEL_BG96_CellularStack::handle_open_socket_response(int &modem_connect_id, int &err, bool tlssocket)
 | 
			
		||||
{
 | 
			
		||||
    // OK
 | 
			
		||||
    // QIOPEN -> should be handled as URC?
 | 
			
		||||
    _at.set_at_timeout(BG96_CREATE_SOCKET_TIMEOUT);
 | 
			
		||||
 | 
			
		||||
    if (tlssocket) {
 | 
			
		||||
        _at.resp_start("+QSSLOPEN:");
 | 
			
		||||
    } else {
 | 
			
		||||
        _at.resp_start("+QIOPEN:");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _at.restore_at_timeout();
 | 
			
		||||
    modem_connect_id = _at.read_int();
 | 
			
		||||
    err = _at.read_int();
 | 
			
		||||
    if (tlssocket && err != 0) {
 | 
			
		||||
        err = NSAPI_ERROR_AUTH_FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nsapi_error_t QUECTEL_BG96_CellularStack::create_socket_impl(CellularSocket *socket)
 | 
			
		||||
| 
						 | 
				
			
			@ -215,7 +283,7 @@ nsapi_error_t QUECTEL_BG96_CellularStack::create_socket_impl(CellularSocket *soc
 | 
			
		|||
                           (_ip_ver_sendto == NSAPI_IPv4) ? "127.0.0.1" : "0:0:0:0:0:0:0:1",
 | 
			
		||||
                           remote_port, socket->localAddress.get_port(), 0);
 | 
			
		||||
 | 
			
		||||
        handle_open_socket_response(modem_connect_id, err);
 | 
			
		||||
        handle_open_socket_response(modem_connect_id, err, false);
 | 
			
		||||
 | 
			
		||||
        if ((_at.get_last_error() == NSAPI_ERROR_OK) && err) {
 | 
			
		||||
            if (err == BG96_SOCKET_BIND_FAIL) {
 | 
			
		||||
| 
						 | 
				
			
			@ -228,7 +296,7 @@ nsapi_error_t QUECTEL_BG96_CellularStack::create_socket_impl(CellularSocket *soc
 | 
			
		|||
                               (_ip_ver_sendto == NSAPI_IPv4) ? "127.0.0.1" : "0:0:0:0:0:0:0:1",
 | 
			
		||||
                               remote_port, socket->localAddress.get_port(), 0);
 | 
			
		||||
 | 
			
		||||
            handle_open_socket_response(modem_connect_id, err);
 | 
			
		||||
            handle_open_socket_response(modem_connect_id, err, false);
 | 
			
		||||
        }
 | 
			
		||||
    } else if (socket->proto == NSAPI_UDP && socket->connected) {
 | 
			
		||||
        char ipdot[NSAPI_IP_SIZE];
 | 
			
		||||
| 
						 | 
				
			
			@ -236,7 +304,7 @@ nsapi_error_t QUECTEL_BG96_CellularStack::create_socket_impl(CellularSocket *soc
 | 
			
		|||
        _at.at_cmd_discard("+QIOPEN", "=", "%d%d%s%s%d", _cid, request_connect_id, "UDP",
 | 
			
		||||
                           ipdot, socket->remoteAddress.get_port());
 | 
			
		||||
 | 
			
		||||
        handle_open_socket_response(modem_connect_id, err);
 | 
			
		||||
        handle_open_socket_response(modem_connect_id, err, false);
 | 
			
		||||
 | 
			
		||||
        if ((_at.get_last_error() == NSAPI_ERROR_OK) && err) {
 | 
			
		||||
            if (err == BG96_SOCKET_BIND_FAIL) {
 | 
			
		||||
| 
						 | 
				
			
			@ -248,7 +316,7 @@ nsapi_error_t QUECTEL_BG96_CellularStack::create_socket_impl(CellularSocket *soc
 | 
			
		|||
            _at.at_cmd_discard("+QIOPEN", "=", "%d%d%s%s%d", _cid, request_connect_id, "UDP",
 | 
			
		||||
                               ipdot, socket->remoteAddress.get_port());
 | 
			
		||||
 | 
			
		||||
            handle_open_socket_response(modem_connect_id, err);
 | 
			
		||||
            handle_open_socket_response(modem_connect_id, err, false);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -283,8 +351,12 @@ nsapi_size_or_error_t QUECTEL_BG96_CellularStack::socket_sendto_impl(CellularSoc
 | 
			
		|||
    int sent_len_before = 0;
 | 
			
		||||
    int sent_len_after = 0;
 | 
			
		||||
 | 
			
		||||
    if (socket->tls_socket) {
 | 
			
		||||
        sent_len_after = size;
 | 
			
		||||
    } else {
 | 
			
		||||
        // Get the sent count before sending
 | 
			
		||||
        _at.at_cmd_int("+QISEND", "=", sent_len_before, "%d%d", socket->id, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Send
 | 
			
		||||
    if (socket->proto == NSAPI_UDP) {
 | 
			
		||||
| 
						 | 
				
			
			@ -292,9 +364,13 @@ nsapi_size_or_error_t QUECTEL_BG96_CellularStack::socket_sendto_impl(CellularSoc
 | 
			
		|||
        ip2dot(address, ipdot);
 | 
			
		||||
        _at.cmd_start_stop("+QISEND", "=", "%d%d%s%d", socket->id, size,
 | 
			
		||||
                           ipdot, address.get_port());
 | 
			
		||||
    } else {
 | 
			
		||||
        if (socket->tls_socket) {
 | 
			
		||||
            _at.cmd_start_stop("+QSSLSEND", "=", "%d%d", socket->id, size);
 | 
			
		||||
        } else {
 | 
			
		||||
            _at.cmd_start_stop("+QISEND", "=", "%d%d", socket->id, size);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _at.resp_start(">");
 | 
			
		||||
    _at.write_bytes((uint8_t *)data, size);
 | 
			
		||||
| 
						 | 
				
			
			@ -310,7 +386,12 @@ nsapi_size_or_error_t QUECTEL_BG96_CellularStack::socket_sendto_impl(CellularSoc
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    // Get the sent count after sending
 | 
			
		||||
    nsapi_size_or_error_t err = _at.at_cmd_int("+QISEND", "=", sent_len_after, "%d%d", socket->id, 0);
 | 
			
		||||
    nsapi_size_or_error_t err = NSAPI_ERROR_OK;
 | 
			
		||||
 | 
			
		||||
    if (!socket->tls_socket) {
 | 
			
		||||
        err = _at.at_cmd_int("+QISEND", "=", sent_len_after, "%d%d", socket->id, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (err == NSAPI_ERROR_OK) {
 | 
			
		||||
        sent_len = sent_len_after - sent_len_before;
 | 
			
		||||
        return sent_len;
 | 
			
		||||
| 
						 | 
				
			
			@ -323,22 +404,34 @@ nsapi_size_or_error_t QUECTEL_BG96_CellularStack::socket_recvfrom_impl(CellularS
 | 
			
		|||
                                                                       void *buffer, nsapi_size_t size)
 | 
			
		||||
{
 | 
			
		||||
    nsapi_size_or_error_t recv_len = 0;
 | 
			
		||||
    int port;
 | 
			
		||||
    int port = -1;
 | 
			
		||||
    char ip_address[NSAPI_IP_SIZE + 1];
 | 
			
		||||
 | 
			
		||||
    if (socket->proto == NSAPI_TCP) {
 | 
			
		||||
        // do not read more than max size
 | 
			
		||||
        size = size > BG96_MAX_RECV_SIZE ? BG96_MAX_RECV_SIZE : size;
 | 
			
		||||
        if (socket->tls_socket) {
 | 
			
		||||
            _at.cmd_start_stop("+QSSLRECV", "=", "%d%d", socket->id, size);
 | 
			
		||||
        } else {
 | 
			
		||||
            _at.cmd_start_stop("+QIRD", "=", "%d%d", socket->id, size);
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        _at.cmd_start_stop("+QIRD", "=", "%d", socket->id);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (socket->tls_socket) {
 | 
			
		||||
        _at.resp_start("+QSSLRECV:");
 | 
			
		||||
    } else {
 | 
			
		||||
        _at.resp_start("+QIRD:");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    recv_len = _at.read_int();
 | 
			
		||||
    if (recv_len > 0) {
 | 
			
		||||
        // UDP has remote_IP and remote_port parameters
 | 
			
		||||
        if (socket->proto == NSAPI_UDP) {
 | 
			
		||||
            _at.read_string(ip_address, sizeof(ip_address));
 | 
			
		||||
            port = _at.read_int();
 | 
			
		||||
    if (recv_len > 0) {
 | 
			
		||||
        }
 | 
			
		||||
        // do not read more than buffer size
 | 
			
		||||
        recv_len = recv_len > (nsapi_size_or_error_t)size ? size : recv_len;
 | 
			
		||||
        _at.read_bytes((uint8_t *)buffer, recv_len);
 | 
			
		||||
| 
						 | 
				
			
			@ -436,3 +529,120 @@ void QUECTEL_BG96_CellularStack::ip2dot(const SocketAddress &ip, char *dot)
 | 
			
		|||
        *dot = '\0';
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nsapi_error_t QUECTEL_BG96_CellularStack::set_to_modem_impl(const char *filename, const char *config, const char *data, size_t size)
 | 
			
		||||
{
 | 
			
		||||
    // Delete old file from the modem.
 | 
			
		||||
    _at.at_cmd_discard("+QFDEL", "=", "%s", filename);
 | 
			
		||||
    _at.clear_error(); // Ignore error if file didn't exist
 | 
			
		||||
 | 
			
		||||
    // Upload new file to modem
 | 
			
		||||
    _at.cmd_start_stop("+QFUPL", "=", "%s%d", filename, size);
 | 
			
		||||
    _at.resp_start("CONNECT");
 | 
			
		||||
    _at.write_bytes((uint8_t *)data, size);
 | 
			
		||||
    _at.resp_start("+QFUPL:");
 | 
			
		||||
    size_t upload_size = _at.read_int();
 | 
			
		||||
    _at.resp_stop();
 | 
			
		||||
    if (upload_size != size) {
 | 
			
		||||
        tr_error("Upload error! orig = %d, uploaded = %d", size, upload_size);
 | 
			
		||||
        return NSAPI_ERROR_DEVICE_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Configure into use
 | 
			
		||||
    _at.at_cmd_discard("+QSSLCFG", "=", "%s%d%s", config, sslctxID, filename);
 | 
			
		||||
 | 
			
		||||
    return _at.get_last_error();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
nsapi_error_t QUECTEL_BG96_CellularStack::setsockopt(nsapi_socket_t handle, int level,
 | 
			
		||||
                                                     int optname, const void *optval, unsigned optlen)
 | 
			
		||||
{
 | 
			
		||||
    CellularSocket *socket = (CellularSocket *)handle;
 | 
			
		||||
    nsapi_error_t ret = NSAPI_ERROR_OK;
 | 
			
		||||
 | 
			
		||||
    if (level == NSAPI_TLSSOCKET_LEVEL) {
 | 
			
		||||
        if (optval) {
 | 
			
		||||
            _at.lock();
 | 
			
		||||
            switch (optname) {
 | 
			
		||||
                case NSAPI_TLSSOCKET_ENABLE: {
 | 
			
		||||
                    MBED_ASSERT(optlen == sizeof(bool));
 | 
			
		||||
                    bool *enabled = (bool *)optval;
 | 
			
		||||
                    if (socket->proto == NSAPI_TCP) {
 | 
			
		||||
                        socket->tls_socket = enabled;
 | 
			
		||||
 | 
			
		||||
                        if (enabled) {
 | 
			
		||||
                            _at.at_cmd_discard("+QSSLCFG", "=\"seclevel\",", "%d%d", sslctxID, _tls_sec_level);
 | 
			
		||||
 | 
			
		||||
                            _at.at_cmd_discard("+QSSLCFG", "=\"sslversion\",", "%d%d", sslctxID, BG96_SUPPORTED_SSL_VERSION);
 | 
			
		||||
 | 
			
		||||
                            _at.cmd_start("AT+QSSLCFG=\"ciphersuite\",");
 | 
			
		||||
                            _at.write_int(sslctxID);
 | 
			
		||||
                            _at.write_string(BG96_SUPPORTED_CIPHER_SUITE, false);
 | 
			
		||||
                            _at.cmd_stop_read_resp();
 | 
			
		||||
 | 
			
		||||
                            ret = _at.get_last_error();
 | 
			
		||||
                        }
 | 
			
		||||
                    } else {
 | 
			
		||||
                        tr_error("Trying to set non-TCPSocket as TLSSocket");
 | 
			
		||||
                        ret = NSAPI_ERROR_PARAMETER;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
                case NSAPI_TLSSOCKET_SET_HOSTNAME: {
 | 
			
		||||
                    const char *hostname = (const char *)optval;
 | 
			
		||||
                    _at.at_cmd_discard("+QSSLCFG", "=\"checkhost\",", "%d%s", sslctxID, hostname);
 | 
			
		||||
                    ret = _at.get_last_error();
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
                case NSAPI_TLSSOCKET_SET_CACERT: {
 | 
			
		||||
                    const char *cacert = (const char *)optval;
 | 
			
		||||
                    ret = set_to_modem_impl("cacert.pem", "cacert", cacert, optlen);
 | 
			
		||||
 | 
			
		||||
                    // Set sec level to "Manage server authentication" if only cacert is in use
 | 
			
		||||
                    if (ret == NSAPI_ERROR_OK && _tls_sec_level == 0) {
 | 
			
		||||
                        _tls_sec_level = 1;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
                case NSAPI_TLSSOCKET_SET_CLCERT: {
 | 
			
		||||
                    const char *clcert = (const char *)optval;
 | 
			
		||||
                    ret = set_to_modem_impl("clcert.pem", "clientcert", clcert, optlen);
 | 
			
		||||
 | 
			
		||||
                    // Set sec level to "Manage server and client authentication if requested by the remote server"
 | 
			
		||||
                    if (ret == NSAPI_ERROR_OK) {
 | 
			
		||||
                        _tls_sec_level = 2;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
                case NSAPI_TLSSOCKET_SET_CLKEY: {
 | 
			
		||||
                    const char *clkey = (const char *)optval;
 | 
			
		||||
                    ret = set_to_modem_impl("client.key", "clientkey", clkey, optlen);
 | 
			
		||||
 | 
			
		||||
                    // Set sec level to "Manage server and client authentication if requested by the remote server"
 | 
			
		||||
                    if (ret == NSAPI_ERROR_OK) {
 | 
			
		||||
                        _tls_sec_level = 2;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
                default:
 | 
			
		||||
                    tr_error("Unsupported sockopt (%d)", optname);
 | 
			
		||||
                    ret = NSAPI_ERROR_UNSUPPORTED;
 | 
			
		||||
            }
 | 
			
		||||
            _at.unlock();
 | 
			
		||||
        } else {
 | 
			
		||||
            tr_error("No optval!");
 | 
			
		||||
            ret = NSAPI_ERROR_PARAMETER;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        tr_warning("Unsupported level (%d)", level);
 | 
			
		||||
        ret = NSAPI_ERROR_UNSUPPORTED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -55,6 +55,9 @@ protected: // NetworkStack
 | 
			
		|||
    virtual nsapi_error_t gethostbyname_async_cancel(int id);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    virtual nsapi_error_t setsockopt(nsapi_socket_t handle, int level,
 | 
			
		||||
                                     int optname, const void *optval, unsigned optlen);
 | 
			
		||||
 | 
			
		||||
protected: // AT_CellularStack
 | 
			
		||||
 | 
			
		||||
    virtual int get_max_socket_count();
 | 
			
		||||
| 
						 | 
				
			
			@ -79,7 +82,9 @@ private:
 | 
			
		|||
    // URC handler for socket being closed
 | 
			
		||||
    void urc_qiurc_closed();
 | 
			
		||||
 | 
			
		||||
    void handle_open_socket_response(int &modem_connect_id, int &err);
 | 
			
		||||
    void handle_open_socket_response(int &modem_connect_id, int &err, bool tlssocket);
 | 
			
		||||
 | 
			
		||||
    nsapi_error_t set_to_modem_impl(const char *filename, const char *config, const char *data, size_t size);
 | 
			
		||||
 | 
			
		||||
#ifdef MBED_CONF_CELLULAR_OFFLOAD_DNS_QUERIES
 | 
			
		||||
    // URC handler for DNS query
 | 
			
		||||
| 
						 | 
				
			
			@ -89,6 +94,9 @@ private:
 | 
			
		|||
    hostbyname_cb_t _dns_callback;
 | 
			
		||||
    nsapi_version_t _dns_version;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    uint8_t _tls_sec_level;
 | 
			
		||||
 | 
			
		||||
    /** Convert IP address to dotted string representation
 | 
			
		||||
     *
 | 
			
		||||
     *  BG96 requires consecutive zeros so can't use get_ip_address or ip6tos directly.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,6 +20,8 @@
 | 
			
		|||
#define TRACE_GROUP "TLSS"
 | 
			
		||||
#include "mbed-trace/mbed_trace.h"
 | 
			
		||||
 | 
			
		||||
#if !defined(MBED_CONF_NSAPI_OFFLOAD_TLSSOCKET) || !(MBED_CONF_NSAPI_OFFLOAD_TLSSOCKET)
 | 
			
		||||
 | 
			
		||||
// This class requires Mbed TLS SSL/TLS client code
 | 
			
		||||
#if defined(MBEDTLS_SSL_CLI_C)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -46,5 +48,71 @@ TLSSocket::~TLSSocket()
 | 
			
		|||
     */
 | 
			
		||||
    close();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // MBEDTLS_SSL_CLI_C
 | 
			
		||||
 | 
			
		||||
#else // MBED_CONF_NSAPI_OFFLOAD_TLSSOCKET
 | 
			
		||||
 | 
			
		||||
TLSSocket::TLSSocket()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TLSSocket::~TLSSocket()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
nsapi_error_t TLSSocket::set_hostname(const char *hostname)
 | 
			
		||||
{
 | 
			
		||||
    return setsockopt(NSAPI_TLSSOCKET_LEVEL, NSAPI_TLSSOCKET_SET_HOSTNAME, hostname, strlen(hostname));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nsapi_error_t TLSSocket::set_root_ca_cert(const void *root_ca, size_t len)
 | 
			
		||||
{
 | 
			
		||||
    return setsockopt(NSAPI_TLSSOCKET_LEVEL, NSAPI_TLSSOCKET_SET_CACERT, root_ca, len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nsapi_error_t TLSSocket::set_root_ca_cert(const char *root_ca_pem)
 | 
			
		||||
{
 | 
			
		||||
    return set_root_ca_cert(root_ca_pem, strlen(root_ca_pem));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nsapi_error_t TLSSocket::set_client_cert_key(const void *client_cert, size_t client_cert_len,
 | 
			
		||||
                                             const void *client_private_key_pem, size_t client_private_key_len)
 | 
			
		||||
{
 | 
			
		||||
    nsapi_error_t ret = setsockopt(NSAPI_TLSSOCKET_LEVEL, NSAPI_TLSSOCKET_SET_CLCERT, client_cert, client_cert_len);
 | 
			
		||||
    if (ret == NSAPI_ERROR_OK) {
 | 
			
		||||
        ret = setsockopt(NSAPI_TLSSOCKET_LEVEL, NSAPI_TLSSOCKET_SET_CLKEY, client_private_key_pem, client_private_key_len);
 | 
			
		||||
    }
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nsapi_error_t TLSSocket::set_client_cert_key(const char *client_cert_pem, const char *client_private_key_pem)
 | 
			
		||||
{
 | 
			
		||||
    return set_client_cert_key(client_cert_pem, strlen(client_cert_pem), client_private_key_pem, strlen(client_private_key_pem));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nsapi_error_t TLSSocket::connect(const char *host, uint16_t port)
 | 
			
		||||
{
 | 
			
		||||
    nsapi_error_t ret = enable_tlssocket();
 | 
			
		||||
    if (ret == NSAPI_ERROR_OK) {
 | 
			
		||||
        ret = TCPSocket::connect(host, port);
 | 
			
		||||
    }
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nsapi_error_t TLSSocket::connect(const SocketAddress &address)
 | 
			
		||||
{
 | 
			
		||||
    nsapi_error_t ret = enable_tlssocket();
 | 
			
		||||
    if (ret == NSAPI_ERROR_OK) {
 | 
			
		||||
        ret = TCPSocket::connect(address);
 | 
			
		||||
    }
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nsapi_error_t TLSSocket::enable_tlssocket()
 | 
			
		||||
{
 | 
			
		||||
    bool enabled = true;
 | 
			
		||||
    return setsockopt(NSAPI_TLSSOCKET_LEVEL, NSAPI_TLSSOCKET_ENABLE, &enabled, sizeof(enabled));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // MBED_CONF_NSAPI_OFFLOAD_TLSSOCKET
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,7 +23,6 @@
 | 
			
		|||
#define _MBED_HTTPS_TLS_TCP_SOCKET_H_
 | 
			
		||||
 | 
			
		||||
#include "netsocket/TCPSocket.h"
 | 
			
		||||
#include "TLSSocketWrapper.h"
 | 
			
		||||
 | 
			
		||||
#include "mbedtls/platform.h"
 | 
			
		||||
#include "mbedtls/ssl.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -31,9 +30,13 @@
 | 
			
		|||
#include "mbedtls/ctr_drbg.h"
 | 
			
		||||
#include "mbedtls/error.h"
 | 
			
		||||
 | 
			
		||||
#if !defined(MBED_CONF_NSAPI_OFFLOAD_TLSSOCKET) || !(MBED_CONF_NSAPI_OFFLOAD_TLSSOCKET)
 | 
			
		||||
 | 
			
		||||
// This class requires Mbed TLS SSL/TLS client code
 | 
			
		||||
#if defined(MBEDTLS_SSL_CLI_C) || defined(DOXYGEN_ONLY)
 | 
			
		||||
 | 
			
		||||
#include "TLSSocketWrapper.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief TLSSocket is a wrapper around TCPSocket for interacting with TLS servers.
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -62,7 +65,7 @@ public:
 | 
			
		|||
     *        clear internal TLS memory structures.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param stack    Network stack as target for socket.
 | 
			
		||||
     *  @return         0 on success, negative error code on failure.
 | 
			
		||||
     *  @return         NSAPI_ERROR_OK on success, negative error code on failure.
 | 
			
		||||
     */
 | 
			
		||||
    virtual nsapi_error_t open(NetworkStack *stack)
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -87,15 +90,80 @@ public:
 | 
			
		|||
     *
 | 
			
		||||
     *  @param host     Hostname of the remote host.
 | 
			
		||||
     *  @param port     Port of the remote host.
 | 
			
		||||
     *  @return         0 on success, negative error code on failure.
 | 
			
		||||
     *  @return         NSAPI_ERROR_OK on success, negative error code on failure.
 | 
			
		||||
     */
 | 
			
		||||
    nsapi_error_t connect(const char *host, uint16_t port);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    TCPSocket tcp_socket;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // MBEDTLS_SSL_CLI_C
 | 
			
		||||
 | 
			
		||||
#else // MBED_CONF_NSAPI_OFFLOAD_TLSSOCKET
 | 
			
		||||
 | 
			
		||||
class TLSSocket : public TCPSocket {
 | 
			
		||||
public:
 | 
			
		||||
    TLSSocket();
 | 
			
		||||
    virtual ~TLSSocket();
 | 
			
		||||
 | 
			
		||||
    /** Set hostname.
 | 
			
		||||
     *
 | 
			
		||||
     * TLSSocket requires hostname used to verify the certificate.
 | 
			
		||||
     * If hostname is not given in constructor, this function must be used before
 | 
			
		||||
     * starting the TLS handshake.
 | 
			
		||||
     *
 | 
			
		||||
     * @param hostname     Hostname of the remote host, used for certificate checking.
 | 
			
		||||
     */
 | 
			
		||||
    nsapi_error_t set_hostname(const char *hostname);
 | 
			
		||||
 | 
			
		||||
    /** Sets the certification of Root CA.
 | 
			
		||||
     *
 | 
			
		||||
     * @note Must be called after open() before calling connect()
 | 
			
		||||
     *
 | 
			
		||||
     * @param root_ca Root CA Certificate in any Mbed TLS-supported format.
 | 
			
		||||
     * @param len     Length of certificate (including terminating 0 for PEM).
 | 
			
		||||
     * @return        NSAPI_ERROR_OK on success, negative error code on failure.
 | 
			
		||||
     */
 | 
			
		||||
    virtual nsapi_error_t set_root_ca_cert(const void *root_ca, size_t len);
 | 
			
		||||
 | 
			
		||||
    /** Sets the certification of Root CA.
 | 
			
		||||
     *
 | 
			
		||||
     * @note Must be called after open() before calling connect()
 | 
			
		||||
     *
 | 
			
		||||
     * @param root_ca_pem Root CA Certificate in PEM format.
 | 
			
		||||
     */
 | 
			
		||||
    virtual nsapi_error_t set_root_ca_cert(const char *root_ca_pem);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /** Sets client certificate, and client private key.
 | 
			
		||||
     *
 | 
			
		||||
     * @param client_cert Client certification in PEM or DER format.
 | 
			
		||||
     * @param client_cert_len Certificate size including the terminating null byte for PEM data.
 | 
			
		||||
     * @param client_private_key_pem Client private key in PEM or DER format.
 | 
			
		||||
     * @param client_private_key_len Key size including the terminating null byte for PEM data
 | 
			
		||||
     * @return   NSAPI_ERROR_OK on success, negative error code on failure.
 | 
			
		||||
     */
 | 
			
		||||
    virtual nsapi_error_t set_client_cert_key(const void *client_cert, size_t client_cert_len,
 | 
			
		||||
                                              const void *client_private_key_pem, size_t client_private_key_len);
 | 
			
		||||
 | 
			
		||||
    /** Sets client certificate, and client private key.
 | 
			
		||||
     *
 | 
			
		||||
     * @param client_cert_pem Client certification in PEM format.
 | 
			
		||||
     * @param client_private_key_pem Client private key in PEM format.
 | 
			
		||||
     * @return   NSAPI_ERROR_OK on success, negative error code on failure.
 | 
			
		||||
     */
 | 
			
		||||
    virtual nsapi_error_t set_client_cert_key(const char *client_cert_pem, const char *client_private_key_pem);
 | 
			
		||||
 | 
			
		||||
    // From TCPSocket
 | 
			
		||||
    virtual nsapi_error_t connect(const char *host, uint16_t port);
 | 
			
		||||
    virtual nsapi_error_t connect(const SocketAddress &address);
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    virtual nsapi_error_t enable_tlssocket();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // MBED_CONF_NSAPI_OFFLOAD_TLSSOCKET
 | 
			
		||||
 | 
			
		||||
#endif // _MBED_HTTPS_TLS_TCP_SOCKET_H_
 | 
			
		||||
 | 
			
		||||
/** @} */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -65,6 +65,10 @@
 | 
			
		|||
        "socket-stats-max-count": {
 | 
			
		||||
            "help": "Maximum number of socket statistics cached",
 | 
			
		||||
            "value": 10
 | 
			
		||||
        },
 | 
			
		||||
        "offload-tlssocket" : {
 | 
			
		||||
            "help": "Use external TLSSocket implementation. Used network stack must support external TLSSocket setsockopt values (see nsapi_types.h)",
 | 
			
		||||
            "value": null
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    "target_overrides": {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -269,6 +269,18 @@ typedef enum nsapi_socket_option {
 | 
			
		|||
    NSAPI_BIND_TO_DEVICE,        /*!< Bind socket network interface name*/
 | 
			
		||||
} nsapi_socket_option_t;
 | 
			
		||||
 | 
			
		||||
typedef enum nsapi_tlssocket_level {
 | 
			
		||||
    NSAPI_TLSSOCKET_LEVEL   = 7099, /*!< TLSSocket option level - see nsapi_tlssocket_option_t for options*/
 | 
			
		||||
} nsapi_tlssocket_level_t;
 | 
			
		||||
 | 
			
		||||
typedef enum nsapi_tlssocket_option {
 | 
			
		||||
    NSAPI_TLSSOCKET_SET_HOSTNAME,   /*!< Set host name */
 | 
			
		||||
    NSAPI_TLSSOCKET_SET_CACERT,     /*!< Set server CA certificate */
 | 
			
		||||
    NSAPI_TLSSOCKET_SET_CLCERT,     /*!< Set client certificate */
 | 
			
		||||
    NSAPI_TLSSOCKET_SET_CLKEY,      /*!< Set client key */
 | 
			
		||||
    NSAPI_TLSSOCKET_ENABLE          /*!< Enable TLSSocket */
 | 
			
		||||
} nsapi_tlssocket_option_t;
 | 
			
		||||
 | 
			
		||||
/** Supported IP protocol versions of IP stack
 | 
			
		||||
 *
 | 
			
		||||
 *  @enum nsapi_ip_stack
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue