2018-11-16 07:40:38 +00:00
|
|
|
/* CellularNonIPSocket
|
|
|
|
#include <CellularNonIPSocket.h>
|
|
|
|
* Copyright (c) 2015 ARM Limited
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "platform/Callback.h"
|
|
|
|
#include "CellularNonIPSocket.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
using namespace mbed;
|
|
|
|
|
2019-12-04 11:04:48 +00:00
|
|
|
ControlPlane_netif *CellularNonIPSocket::_cp_netif;
|
|
|
|
|
2020-02-21 11:49:26 +00:00
|
|
|
CellularNonIPSocket::CellularNonIPSocket() = default;
|
2018-11-16 07:40:38 +00:00
|
|
|
|
|
|
|
nsapi_error_t CellularNonIPSocket::open(CellularContext *cellular_context)
|
|
|
|
{
|
2020-02-21 11:49:26 +00:00
|
|
|
if (cellular_context == nullptr) {
|
2018-12-27 14:39:17 +00:00
|
|
|
return NSAPI_ERROR_PARAMETER;
|
|
|
|
}
|
|
|
|
|
2018-11-16 07:40:38 +00:00
|
|
|
return open(cellular_context->get_cp_netif());
|
|
|
|
}
|
|
|
|
|
|
|
|
CellularNonIPSocket::~CellularNonIPSocket()
|
|
|
|
{
|
|
|
|
close();
|
|
|
|
}
|
|
|
|
|
|
|
|
nsapi_error_t CellularNonIPSocket::open(ControlPlane_netif *cp_netif)
|
|
|
|
{
|
|
|
|
_lock.lock();
|
|
|
|
|
2020-02-21 11:49:26 +00:00
|
|
|
if (cp_netif == nullptr || _opened) {
|
2018-11-16 07:40:38 +00:00
|
|
|
_lock.unlock();
|
|
|
|
return NSAPI_ERROR_PARAMETER;
|
|
|
|
}
|
2019-12-04 11:04:48 +00:00
|
|
|
|
|
|
|
if (_cp_netif) {
|
|
|
|
_lock.unlock();
|
|
|
|
return NSAPI_ERROR_NO_SOCKET;
|
|
|
|
}
|
2018-11-16 07:40:38 +00:00
|
|
|
_cp_netif = cp_netif;
|
|
|
|
|
|
|
|
_event = callback(this, &CellularNonIPSocket::event);
|
|
|
|
_cp_netif->attach(Callback<void()>::thunk, &_event);
|
|
|
|
_opened = true;
|
|
|
|
|
|
|
|
_lock.unlock();
|
|
|
|
return NSAPI_ERROR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsapi_error_t CellularNonIPSocket::close()
|
|
|
|
{
|
|
|
|
_lock.lock();
|
|
|
|
|
|
|
|
nsapi_error_t ret = NSAPI_ERROR_OK;
|
|
|
|
if (!_opened) {
|
|
|
|
return NSAPI_ERROR_NO_SOCKET;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Just in case - tell the stack not to callback any more, then remove this socket.
|
2020-02-21 11:49:26 +00:00
|
|
|
_cp_netif->attach(nullptr, nullptr);
|
2018-11-16 07:40:38 +00:00
|
|
|
_opened = false;
|
2020-02-21 11:49:26 +00:00
|
|
|
_cp_netif = nullptr; // Invalidate the cp_netif pointer - otherwise open() fails.
|
2018-11-16 07:40:38 +00:00
|
|
|
|
|
|
|
// Wakeup anything in a blocking operation
|
|
|
|
// on this socket
|
|
|
|
event();
|
|
|
|
|
|
|
|
// Wait until all readers and writers are gone
|
|
|
|
while (_readers || _writers) {
|
|
|
|
_lock.unlock();
|
|
|
|
_event_flag.wait_any(FINISHED_FLAG, osWaitForever);
|
|
|
|
_lock.lock();
|
|
|
|
}
|
|
|
|
|
|
|
|
_lock.unlock();
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsapi_size_or_error_t CellularNonIPSocket::send(const void *data, nsapi_size_t size)
|
|
|
|
{
|
2019-12-04 11:04:48 +00:00
|
|
|
if (!data) {
|
|
|
|
return NSAPI_ERROR_PARAMETER;
|
|
|
|
}
|
2018-11-16 07:40:38 +00:00
|
|
|
_lock.lock();
|
|
|
|
nsapi_size_or_error_t ret;
|
|
|
|
|
|
|
|
_writers++;
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
if (!_opened) {
|
|
|
|
ret = NSAPI_ERROR_NO_SOCKET;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-02-21 11:49:26 +00:00
|
|
|
core_util_atomic_flag_clear(&_pending);
|
2018-11-16 07:40:38 +00:00
|
|
|
nsapi_size_or_error_t sent = _cp_netif->send(data, size);
|
|
|
|
if ((0 == _timeout) || (NSAPI_ERROR_WOULD_BLOCK != sent)) {
|
|
|
|
ret = sent;
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
uint32_t flag;
|
|
|
|
|
|
|
|
// Release lock before blocking so other threads
|
|
|
|
// accessing this object aren't blocked
|
|
|
|
_lock.unlock();
|
|
|
|
flag = _event_flag.wait_any(WRITE_FLAG, _timeout);
|
|
|
|
_lock.lock();
|
|
|
|
|
|
|
|
if (flag & osFlagsError) {
|
|
|
|
// Timeout break
|
|
|
|
ret = NSAPI_ERROR_WOULD_BLOCK;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_writers--;
|
|
|
|
if (!_opened || !_writers) {
|
|
|
|
_event_flag.set(FINISHED_FLAG);
|
|
|
|
}
|
|
|
|
_lock.unlock();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsapi_size_or_error_t CellularNonIPSocket::recv(void *buffer, nsapi_size_t size)
|
|
|
|
{
|
|
|
|
_lock.lock();
|
2019-12-09 12:36:29 +00:00
|
|
|
nsapi_size_or_error_t ret = NSAPI_ERROR_NO_SOCKET;
|
2018-11-16 07:40:38 +00:00
|
|
|
|
|
|
|
_readers++;
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
if (!_opened) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-02-21 11:49:26 +00:00
|
|
|
core_util_atomic_flag_clear(&_pending);
|
2018-11-16 07:40:38 +00:00
|
|
|
nsapi_size_or_error_t recv = _cp_netif->recv(buffer, size);
|
|
|
|
|
|
|
|
// Non-blocking sockets always return. Blocking only returns when success or errors other than WOULD_BLOCK
|
|
|
|
if ((0 == _timeout) || (NSAPI_ERROR_WOULD_BLOCK != recv)) {
|
|
|
|
ret = recv;
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
uint32_t flag;
|
|
|
|
|
|
|
|
// Release lock before blocking so other threads
|
|
|
|
// accessing this object aren't blocked
|
|
|
|
_lock.unlock();
|
|
|
|
flag = _event_flag.wait_any(READ_FLAG, _timeout);
|
|
|
|
_lock.lock();
|
|
|
|
|
|
|
|
if (flag & osFlagsError) {
|
|
|
|
// Timeout break
|
2019-12-09 12:36:29 +00:00
|
|
|
// Poll once more for a possibly missed data received indication
|
|
|
|
ret = _cp_netif->recv(buffer, size);
|
2018-11-16 07:40:38 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_readers--;
|
|
|
|
if (!_opened || !_readers) {
|
|
|
|
_event_flag.set(FINISHED_FLAG);
|
|
|
|
}
|
|
|
|
|
|
|
|
_lock.unlock();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CellularNonIPSocket::set_blocking(bool blocking)
|
|
|
|
{
|
|
|
|
set_timeout(blocking ? -1 : 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CellularNonIPSocket::set_timeout(int timeout)
|
|
|
|
{
|
|
|
|
_lock.lock();
|
|
|
|
|
|
|
|
if (timeout >= 0) {
|
|
|
|
_timeout = (uint32_t)timeout;
|
|
|
|
} else {
|
|
|
|
_timeout = osWaitForever;
|
|
|
|
}
|
|
|
|
|
|
|
|
_lock.unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CellularNonIPSocket::event()
|
|
|
|
{
|
|
|
|
_event_flag.set(READ_FLAG | WRITE_FLAG);
|
|
|
|
|
2020-02-21 11:49:26 +00:00
|
|
|
if (_callback && !core_util_atomic_flag_test_and_set(&_pending)) {
|
2018-11-16 07:40:38 +00:00
|
|
|
_callback();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CellularNonIPSocket::sigio(Callback<void()> callback)
|
|
|
|
{
|
|
|
|
_lock.lock();
|
|
|
|
_callback = callback;
|
|
|
|
_lock.unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
nsapi_error_t CellularNonIPSocket::connect(const SocketAddress &address)
|
|
|
|
{
|
|
|
|
return NSAPI_ERROR_UNSUPPORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
Socket *CellularNonIPSocket::accept(nsapi_error_t *error)
|
|
|
|
{
|
|
|
|
if (error) {
|
|
|
|
*error = NSAPI_ERROR_UNSUPPORTED;
|
|
|
|
}
|
2020-02-21 11:49:26 +00:00
|
|
|
return nullptr;
|
2018-11-16 07:40:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nsapi_error_t CellularNonIPSocket::listen(int backlog)
|
|
|
|
{
|
|
|
|
return NSAPI_ERROR_UNSUPPORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsapi_size_or_error_t CellularNonIPSocket::sendto(const SocketAddress &address,
|
2019-01-31 12:15:01 +00:00
|
|
|
const void *data, nsapi_size_t size)
|
2018-11-16 07:40:38 +00:00
|
|
|
{
|
|
|
|
return NSAPI_ERROR_UNSUPPORTED;
|
|
|
|
}
|
|
|
|
nsapi_size_or_error_t CellularNonIPSocket::recvfrom(SocketAddress *address,
|
2019-01-31 12:15:01 +00:00
|
|
|
void *data, nsapi_size_t size)
|
2018-11-16 07:40:38 +00:00
|
|
|
{
|
|
|
|
return NSAPI_ERROR_UNSUPPORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsapi_error_t CellularNonIPSocket::setsockopt(int level, int optname, const void *optval, unsigned optlen)
|
|
|
|
{
|
|
|
|
return NSAPI_ERROR_UNSUPPORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsapi_error_t CellularNonIPSocket::getsockopt(int level, int optname, void *optval, unsigned *optlen)
|
|
|
|
{
|
|
|
|
return NSAPI_ERROR_UNSUPPORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsapi_error_t CellularNonIPSocket::getpeername(SocketAddress *address)
|
|
|
|
{
|
|
|
|
return NSAPI_ERROR_UNSUPPORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsapi_error_t CellularNonIPSocket::bind(const SocketAddress &address)
|
|
|
|
{
|
|
|
|
return NSAPI_ERROR_UNSUPPORTED;
|
|
|
|
}
|