int NanostackInterface::socket_recv(void *handle, void *data, unsigned size)
{
    // Validate parameters
    NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
    if (NULL == handle) {
        MBED_ASSERT(false);
        return NSAPI_ERROR_NO_SOCKET;
    }

    nanostack_lock();

    int ret;
    if (socket->closed()) {
        ret = NSAPI_ERROR_NO_CONNECTION;
    } else if (socket->data_available()) {
        ret = socket->data_copy_and_free(data, size, NULL, true);
    } else {
        ret = NSAPI_ERROR_WOULD_BLOCK;
    }

    nanostack_unlock();

    tr_debug("socket_recv(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);

    return ret;
}
int NanostackInterface::socket_connect(void *handle, const SocketAddress &addr)
{
    // Validate parameters
    NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
    if (NULL == handle) {
        MBED_ASSERT(false);
        return NSAPI_ERROR_NO_SOCKET;
    }

    nanostack_lock();

    int ret;
    ns_address_t ns_addr;
    int random_port = socket->is_bound() ? 0 : 1;
    convert_mbed_addr_to_ns(&ns_addr, &addr);
    if (0 == ::socket_connect(socket->socket_id, &ns_addr, random_port)) {
        socket->set_connecting(&ns_addr);
        ret = 0;
    } else {
        ret = NSAPI_ERROR_DEVICE_ERROR;
    }

    nanostack_unlock();

    tr_debug("socket_connect(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);

    return ret;
}
int NanostackInterface::socket_bind(void *handle, const SocketAddress &address)
{
    // Validate parameters
    NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
    if (NULL == handle) {
        MBED_ASSERT(false);
        return NSAPI_ERROR_NO_SOCKET;
    }


    nanostack_lock();

    ns_address_t ns_address;
    ns_address.type = ADDRESS_IPV6;
    memset(ns_address.address, 0, sizeof ns_address.address);
    ns_address.identifier = address.get_port();
    int ret = NSAPI_ERROR_DEVICE_ERROR;
    if (0 == ::socket_bind(socket->socket_id, &ns_address)) {
        socket->set_bound();
        ret = 0;
    }

    nanostack_unlock();

    tr_debug("socket_bind(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);

    return ret;
}
Exemplo n.º 4
0
nsapi_error_t NanostackInterface::socket_connect(void *handle, const SocketAddress &addr)
{
    // Validate parameters
    NanostackSocket *socket = static_cast<NanostackSocket *>(handle);
    nsapi_error_t ret;
    if (handle == NULL) {
        MBED_ASSERT(false);
        return NSAPI_ERROR_NO_SOCKET;
    }

    NanostackLockGuard lock;

    if (addr.get_ip_version() != NSAPI_IPv6) {
        ret = NSAPI_ERROR_UNSUPPORTED;
        goto out;
    }

    if (socket->closed()) {
        ret = NSAPI_ERROR_NO_CONNECTION;
        goto out;
    }

    if (socket->is_connecting()) {
        ret = NSAPI_ERROR_ALREADY;
        goto out;
    }

    if (socket->is_connected()) {
        ret = NSAPI_ERROR_IS_CONNECTED;
        goto out;
    }

    ns_address_t ns_addr;

    convert_mbed_addr_to_ns(&ns_addr, &addr);
    if (::socket_connect(socket->socket_id, &ns_addr, 0) == 0) {
        if (socket->proto == SOCKET_TCP) {
            socket->set_connecting(&ns_addr);
            ret = NSAPI_ERROR_IN_PROGRESS;
        } else {
            ret = NSAPI_ERROR_OK;
        }
    } else {
        ret = NSAPI_ERROR_DEVICE_ERROR;
    }

out:
    tr_debug("socket_connect(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);

    return ret;
}
int NanostackInterface::socket_sendto(void *handle, const SocketAddress &address, const void *data, unsigned int size)
{
    // Validate parameters
    NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
    if (NULL == handle) {
        MBED_ASSERT(false);
        return NSAPI_ERROR_NO_SOCKET;
    }

    nanostack_lock();

    int ret;
    if (socket->closed()) {
        ret = NSAPI_ERROR_NO_CONNECTION;
    } else if (NANOSTACK_SOCKET_TCP == socket->proto) {
        tr_error("socket_sendto() not supported with SOCKET_STREAM!");
        ret = NSAPI_ERROR_UNSUPPORTED;
    } else {
        ns_address_t ns_address;
        convert_mbed_addr_to_ns(&ns_address, &address);
        if (!socket->is_bound()) {
            socket->set_bound();
        }
        int8_t send_to_status = ::socket_sendto(socket->socket_id, &ns_address,
                                       (uint8_t *)data, size);
        /*
         * \return 0 on success.
         * \return -1 invalid socket id.
         * \return -2 Socket memory allocation fail.
         * \return -3 TCP state not established.
         * \return -4 Socket tx process busy.
         * \return -5 TLS authentication not ready.
         * \return -6 Packet too short.
         * */
        if (-4 == send_to_status) {
            ret = NSAPI_ERROR_WOULD_BLOCK;
        } else if (0 != send_to_status) {
            tr_error("socket_sendto: error=%d", send_to_status);
            ret = NSAPI_ERROR_DEVICE_ERROR;
        } else {
            ret = size;
        }
    }

    nanostack_unlock();

    tr_debug("socket_sendto(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);

    return ret;
}
void NanostackSocket::socket_callback(void *cb) {
    nanostack_assert_locked();

    socket_callback_t *sock_cb = (socket_callback_t *) cb;
    NanostackSocket *socket = socket_tbl[sock_cb->socket_id];
    MBED_ASSERT(socket != NULL);

    tr_debug("socket_callback() sock=%d, event=%d, interface=%d, data len=%d",
                     sock_cb->socket_id, sock_cb->event_type, sock_cb->interface_id, sock_cb->d_len);

    switch (sock_cb->event_type) {
        case SOCKET_DATA:
            tr_debug("SOCKET_DATA, sock=%d, bytes=%d", sock_cb->socket_id, sock_cb->d_len);
            socket->event_data(sock_cb);
            break;
        case SOCKET_BIND_DONE:
            tr_debug("SOCKET_BIND_DONE");
            socket->event_bind_done(sock_cb);
            break;
        case SOCKET_BIND_FAIL: // Not used in NS
            tr_debug("SOCKET_BIND_FAIL");
            break;
        case SOCKET_BIND_AUTH_FAIL: // Not used in NS
            tr_debug("SOCKET_BIND_AUTH_FAIL");
            break;
        case SOCKET_SERVER_CONNECT_TO_CLIENT: // Not used in NS
            tr_debug("SOCKET_SERVER_CONNECT_TO_CLIENT");
            break;
        case SOCKET_TX_FAIL:
            tr_debug("SOCKET_TX_FAIL");
            break;
        case SOCKET_CONNECT_CLOSED:
            tr_debug("SOCKET_CONNECT_CLOSED");
            socket->event_connnect_closed(sock_cb);
            break;
        case SOCKET_CONNECT_FAIL_CLOSED: // Not used in NS
            tr_debug("SOCKET_CONNECT_FAIL_CLOSED");
            break;
        case SOCKET_NO_ROUTE:
            tr_debug("SOCKET_NO_ROUTE");
            break;
        case SOCKET_TX_DONE:
            tr_debug("SOCKET_TX_DONE, %d bytes sent", sock_cb->d_len);
            socket->event_tx_done(sock_cb);
            break;
        default:
            // SOCKET_NO_RAM, error case for SOCKET_TX_DONE
            break;
    }
}
Exemplo n.º 7
0
nsapi_error_t NanostackInterface::socket_accept(void *server, void **handle, SocketAddress *address)
{
    NanostackSocket * socket = static_cast<NanostackSocket *>(server);
    NanostackSocket *accepted_sock = NULL;
    nsapi_error_t ret;

    if (handle == NULL) {
        MBED_ASSERT(false);
        return NSAPI_ERROR_NO_SOCKET;
    }

    NanostackLockGuard lock;

    if (!socket->is_listening()) {
        ret = NSAPI_ERROR_PARAMETER;
        goto out;
    }

    accepted_sock = new NanostackSocket(socket->proto);
    if (accepted_sock == NULL) {
        ret = NSAPI_ERROR_NO_MEMORY;
        goto out;
    }

    ns_address_t ns_addr;
    int retcode;
    retcode = socket->accept(accepted_sock, &ns_addr);
    if (retcode < 0) {
        delete accepted_sock;
        if (retcode == NS_EWOULDBLOCK) {
            ret = NSAPI_ERROR_WOULD_BLOCK;
        } else {
            ret = NSAPI_ERROR_DEVICE_ERROR;
        }
        goto out;
    }
    ret = NSAPI_ERROR_OK;

    if (address) {
        convert_ns_addr_to_mbed(address, &ns_addr);
    }

    *handle = accepted_sock;

out:
    tr_debug("socket_accept() socket=%p, sock_id=%d, ret=%i", accepted_sock, accepted_sock ? accepted_sock->socket_id : -1, ret);

    return ret;
}
Exemplo n.º 8
0
nsapi_size_or_error_t NanostackInterface::socket_recvfrom(void *handle, SocketAddress *address, void *buffer, nsapi_size_t size)
{
    // Validate parameters
    NanostackSocket *socket = static_cast<NanostackSocket *>(handle);
    if (handle == NULL) {
        MBED_ASSERT(false);
        return NSAPI_ERROR_NO_SOCKET;
    }

    nsapi_size_or_error_t ret;

    NanostackLockGuard lock;

    if (socket->closed()) {
        ret = NSAPI_ERROR_NO_CONNECTION;
        goto out;
    }

    ns_address_t ns_address;

    int retcode;
    retcode = ::socket_recvfrom(socket->socket_id, buffer, size, 0, &ns_address);

    if (retcode == NS_EWOULDBLOCK) {
        ret = NSAPI_ERROR_WOULD_BLOCK;
    } else if (retcode < 0) {
        ret = NSAPI_ERROR_PARAMETER;
    } else {
        ret = retcode;
        if (address != NULL) {
            convert_ns_addr_to_mbed(address, &ns_address);
        }
    }

out:
    if (address) {
        tr_debug("socket_recvfrom(socket=%p) sock_id=%d, ret=%i, addr=[%s]:%i", socket, socket->socket_id, ret,
                 trace_ipv6(address->get_ip_bytes()), address->get_port());
    } else {
        tr_debug("socket_recv(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);
    }

    return ret;
}
int NanostackInterface::socket_send(void *handle, const void *p, unsigned size)
{
    // Validate parameters
    NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
    if (NULL == handle) {
        MBED_ASSERT(false);
        return NSAPI_ERROR_NO_SOCKET;
    }

    nanostack_lock();

    int ret;
    if (socket->closed()) {
        ret = NSAPI_ERROR_NO_CONNECTION;
    } else if (socket->is_connecting()) {
        ret = NSAPI_ERROR_WOULD_BLOCK;
    } else {
        ret = ::socket_sendto(socket->socket_id,  &socket->ns_address, (uint8_t*)p, size);
        /*
         * \return 0 on success.
         * \return -1 invalid socket id.
         * \return -2 Socket memory allocation fail.
         * \return -3 TCP state not established.
         * \return -4 Socket tx process busy.
         * \return -5 TLS authentication not ready.
         * \return -6 Packet too short.
         * */
        if (-4 == ret) {
            ret = NSAPI_ERROR_WOULD_BLOCK;
        } else if (ret != 0) {
            tr_warning("socket_sendto ret %i, socket_id %i", ret, socket->socket_id);
            ret = NSAPI_ERROR_DEVICE_ERROR;
        } else {
            ret = size;
        }
    }

    nanostack_unlock();

    tr_debug("socket_send(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);

    return ret;
}
Exemplo n.º 10
0
nsapi_error_t NanostackInterface::socket_listen(void *handle, int backlog)
{
    //Check if socket exists
    NanostackSocket *socket = static_cast<NanostackSocket *>(handle);
    if (handle == NULL) {
        MBED_ASSERT(false);
        return NSAPI_ERROR_NO_SOCKET;
    }

    nsapi_error_t ret = NSAPI_ERROR_OK;

    NanostackLockGuard lock;

    if(::socket_listen(socket->socket_id, backlog) < 0) {
        ret = NSAPI_ERROR_PARAMETER;
    } else {
        socket->set_listening();
    }

    return ret;
}
Exemplo n.º 11
0
int NanostackInterface::socket_open(void **handle, nsapi_protocol_t protocol)
{
    // Validate parameters
    if (NULL == handle) {
        MBED_ASSERT(false);
        return NSAPI_ERROR_NO_SOCKET;
    }
    int8_t ns_proto;
    if (NSAPI_UDP == protocol) {
        ns_proto = SOCKET_UDP;
    } else if (NSAPI_TCP == protocol) {
        ns_proto = SOCKET_TCP;
    } else {
        MBED_ASSERT(false);
        return NSAPI_ERROR_UNSUPPORTED;
    }
    *handle = (void*)NULL;

    nanostack_lock();

    NanostackSocket * socket = new NanostackSocket(ns_proto);
    if (NULL == socket) {
        nanostack_unlock();
        tr_debug("socket_open() ret=%i", NSAPI_ERROR_NO_MEMORY);
        return NSAPI_ERROR_NO_MEMORY;
    }
    if (!socket->open()) {
        delete socket;
        nanostack_unlock();
        tr_debug("socket_open() ret=%i", NSAPI_ERROR_DEVICE_ERROR);
        return NSAPI_ERROR_DEVICE_ERROR;
    }
    *handle = (void*)socket;

    nanostack_unlock();

    tr_debug("socket_open() socket=%p, sock_id=%d, ret=0", socket, socket->socket_id);

    return 0;
}
Exemplo n.º 12
0
int NanostackInterface::socket_recvfrom(void *handle, SocketAddress *address, void *buffer, unsigned size)
{
    // Validate parameters
    NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
    if (NULL == handle) {
        MBED_ASSERT(false);
        return NSAPI_ERROR_NO_SOCKET;
    }
    if (NULL == buffer) {
        MBED_ASSERT(false);
        return NSAPI_ERROR_PARAMETER;
    }
    if (0 == size) {
        MBED_ASSERT(false);
        return NSAPI_ERROR_PARAMETER;
    }

    nanostack_lock();

    int ret;
    if (socket->closed()) {
        ret = NSAPI_ERROR_NO_CONNECTION;
    } else if (NANOSTACK_SOCKET_TCP == socket->proto) {
        tr_error("recv_from() not supported with SOCKET_STREAM!");
        ret = NSAPI_ERROR_UNSUPPORTED;
    } else if (!socket->data_available()) {
        ret = NSAPI_ERROR_WOULD_BLOCK;
    } else {
        ret = socket->data_copy_and_free(buffer, size, address, false);
    }

    nanostack_unlock();

    tr_debug("socket_recvfrom(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);

    return ret;
}
Exemplo n.º 13
0
nsapi_size_or_error_t NanostackInterface::do_sendto(void *handle, const ns_address_t *address, const void *data, nsapi_size_t size)
{
    // Validate parameters
    NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
    if (handle == NULL) {
        MBED_ASSERT(false);
        return NSAPI_ERROR_NO_SOCKET;
    }

    nsapi_size_or_error_t ret;

    NanostackLockGuard lock;

    if (socket->closed() || (!address && !socket->is_connected())) {
        ret = NSAPI_ERROR_NO_CONNECTION;
        goto out;
    }

    if (address && socket->proto == SOCKET_TCP) {
        tr_error("socket_sendto() not supported with TCP!");
        ret = NSAPI_ERROR_IS_CONNECTED;
        goto out;
    }

    int retcode;
#if 0
    retcode = ::socket_sendto(socket->socket_id, address,
                                            data, size);
#else
    // Use sendmsg purely to get the new return style
    // of returning data written rather than 0 on success,
    // which means TCP can do partial writes. (Sadly,
    // it's the only call which takes flags so we can
    // leave the NS_MSG_LEGACY0 flag clear).
    ns_msghdr_t msg;
    ns_iovec_t iov;
    iov.iov_base = const_cast<void *>(data);
    iov.iov_len = size;
    msg.msg_name = const_cast<ns_address_t *>(address);
    msg.msg_namelen = address ? sizeof *address : 0;
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;
    msg.msg_control = NULL;
    msg.msg_controllen = 0;
    retcode = ::socket_sendmsg(socket->socket_id, &msg, 0);
#endif

    /*
     * \return length if entire amount written (which could be 0)
     * \return value >0 and <length if partial amount written (stream only)
     * \return NS_EWOULDBLOCK if nothing written due to lack of queue space.
     * \return -1 Invalid socket ID or message structure.
     * \return -2 Socket memory allocation fail.
     * \return -3 TCP state not established or address scope not defined .
     * \return -4 Socket TX process busy or unknown interface.
     * \return -5 Socket not connected
     * \return -6 Packet too short (ICMP raw socket error).
     * */
    if (retcode == NS_EWOULDBLOCK) {
        ret = NSAPI_ERROR_WOULD_BLOCK;
    } else if (retcode < 0) {
        tr_error("socket_sendmsg: error=%d", retcode);
        ret = NSAPI_ERROR_DEVICE_ERROR;
    } else {
        ret = retcode;
    }

out:
    tr_debug("socket_sendto(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);

    return ret;
}
Exemplo n.º 14
0
void NanostackSocket::socket_callback(void *cb) {
    nanostack_assert_locked();

    socket_callback_t *sock_cb = (socket_callback_t *) cb;
    NanostackSocket *socket = socket_tbl[sock_cb->socket_id];
    MBED_ASSERT(socket != NULL);

    tr_debug("socket_callback() sock=%d, event=%d, interface=%d, data len=%d",
                     sock_cb->socket_id, sock_cb->event_type, sock_cb->interface_id, sock_cb->d_len);

    switch (sock_cb->event_type) {
        case SOCKET_DATA:
            tr_debug("SOCKET_DATA, sock=%d, bytes=%d", sock_cb->socket_id, sock_cb->d_len);
            socket->event_data(sock_cb);
            break;
        case SOCKET_CONNECT_DONE:
            tr_debug("SOCKET_CONNECT_DONE");
            socket->event_connect_done(sock_cb);
            break;
        case SOCKET_CONNECT_FAIL:
            tr_debug("SOCKET_CONNECT_FAIL");
            socket->event_connect_fail(sock_cb);
            break;
        case SOCKET_CONNECT_AUTH_FAIL:
            tr_debug("SOCKET_CONNECT_AUTH_FAIL");
            break;
        case SOCKET_INCOMING_CONNECTION:
            tr_debug("SOCKET_INCOMING_CONNECTION");
            socket->event_incoming_connection(sock_cb);
            break;
        case SOCKET_TX_FAIL:
            tr_debug("SOCKET_TX_FAIL");
            socket->event_tx_fail(sock_cb);
            break;
        case SOCKET_CONNECT_CLOSED:
            tr_debug("SOCKET_CONNECT_CLOSED");
            socket->event_connect_closed(sock_cb);
            break;
        case SOCKET_CONNECTION_RESET:
            tr_debug("SOCKET_CONNECTION_RESET");
            socket->event_connection_reset(sock_cb);
            break;
        case SOCKET_NO_ROUTE:
            tr_debug("SOCKET_NO_ROUTE");
            socket->event_tx_fail(sock_cb);
            break;
        case SOCKET_TX_DONE:
            socket->event_tx_done(sock_cb);
            break;
        case SOCKET_NO_RAM:
            tr_debug("SOCKET_NO_RAM");
            socket->event_tx_fail(sock_cb);
            break;
        case SOCKET_CONNECTION_PROBLEM:
            tr_debug("SOCKET_CONNECTION_PROBLEM");
            break;
        default:
            break;
    }
}