mbed-os5 only for TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Committer:
kenjiArai
Date:
Tue Dec 17 23:23:45 2019 +0000
Revision:
0:5b88d5760320
mbed-os5 only for TYBLE16

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kenjiArai 0:5b88d5760320 1 /* InternetSocket
kenjiArai 0:5b88d5760320 2 * Copyright (c) 2015 ARM Limited
kenjiArai 0:5b88d5760320 3 *
kenjiArai 0:5b88d5760320 4 * Licensed under the Apache License, Version 2.0 (the "License");
kenjiArai 0:5b88d5760320 5 * you may not use this file except in compliance with the License.
kenjiArai 0:5b88d5760320 6 * You may obtain a copy of the License at
kenjiArai 0:5b88d5760320 7 *
kenjiArai 0:5b88d5760320 8 * http://www.apache.org/licenses/LICENSE-2.0
kenjiArai 0:5b88d5760320 9 *
kenjiArai 0:5b88d5760320 10 * Unless required by applicable law or agreed to in writing, software
kenjiArai 0:5b88d5760320 11 * distributed under the License is distributed on an "AS IS" BASIS,
kenjiArai 0:5b88d5760320 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kenjiArai 0:5b88d5760320 13 * See the License for the specific language governing permissions and
kenjiArai 0:5b88d5760320 14 * limitations under the License.
kenjiArai 0:5b88d5760320 15 */
kenjiArai 0:5b88d5760320 16
kenjiArai 0:5b88d5760320 17 #include "InternetSocket.h"
kenjiArai 0:5b88d5760320 18 #include "platform/mbed_critical.h"
kenjiArai 0:5b88d5760320 19 #include "platform/Callback.h"
kenjiArai 0:5b88d5760320 20
kenjiArai 0:5b88d5760320 21 using namespace mbed;
kenjiArai 0:5b88d5760320 22
kenjiArai 0:5b88d5760320 23 InternetSocket::InternetSocket()
kenjiArai 0:5b88d5760320 24 : _stack(0), _socket(0), _timeout(osWaitForever),
kenjiArai 0:5b88d5760320 25 _remote_peer(),
kenjiArai 0:5b88d5760320 26 _readers(0), _writers(0),
kenjiArai 0:5b88d5760320 27 _factory_allocated(false)
kenjiArai 0:5b88d5760320 28 {
kenjiArai 0:5b88d5760320 29 core_util_atomic_flag_clear(&_pending);
kenjiArai 0:5b88d5760320 30 _socket_stats.stats_new_socket_entry(this);
kenjiArai 0:5b88d5760320 31 }
kenjiArai 0:5b88d5760320 32
kenjiArai 0:5b88d5760320 33 InternetSocket::~InternetSocket()
kenjiArai 0:5b88d5760320 34 {
kenjiArai 0:5b88d5760320 35 close();
kenjiArai 0:5b88d5760320 36 }
kenjiArai 0:5b88d5760320 37
kenjiArai 0:5b88d5760320 38 nsapi_error_t InternetSocket::open(NetworkStack *stack)
kenjiArai 0:5b88d5760320 39 {
kenjiArai 0:5b88d5760320 40 _lock.lock();
kenjiArai 0:5b88d5760320 41
kenjiArai 0:5b88d5760320 42 if (_stack != NULL || stack == NULL) {
kenjiArai 0:5b88d5760320 43 _lock.unlock();
kenjiArai 0:5b88d5760320 44 return NSAPI_ERROR_PARAMETER;
kenjiArai 0:5b88d5760320 45 }
kenjiArai 0:5b88d5760320 46 _stack = stack;
kenjiArai 0:5b88d5760320 47
kenjiArai 0:5b88d5760320 48 nsapi_socket_t socket;
kenjiArai 0:5b88d5760320 49 nsapi_error_t err = _stack->socket_open(&socket, get_proto());
kenjiArai 0:5b88d5760320 50 if (err) {
kenjiArai 0:5b88d5760320 51 _lock.unlock();
kenjiArai 0:5b88d5760320 52 return err;
kenjiArai 0:5b88d5760320 53 }
kenjiArai 0:5b88d5760320 54
kenjiArai 0:5b88d5760320 55 _socket_stats.stats_update_socket_state(this, SOCK_OPEN);
kenjiArai 0:5b88d5760320 56 _socket = socket;
kenjiArai 0:5b88d5760320 57 _event = callback(this, &InternetSocket::event);
kenjiArai 0:5b88d5760320 58 _stack->socket_attach(_socket, Callback<void()>::thunk, &_event);
kenjiArai 0:5b88d5760320 59 _interface_name[0] = '\0';
kenjiArai 0:5b88d5760320 60 _lock.unlock();
kenjiArai 0:5b88d5760320 61 return NSAPI_ERROR_OK;
kenjiArai 0:5b88d5760320 62 }
kenjiArai 0:5b88d5760320 63
kenjiArai 0:5b88d5760320 64 nsapi_error_t InternetSocket::close()
kenjiArai 0:5b88d5760320 65 {
kenjiArai 0:5b88d5760320 66 _lock.lock();
kenjiArai 0:5b88d5760320 67
kenjiArai 0:5b88d5760320 68 nsapi_error_t ret = NSAPI_ERROR_OK;
kenjiArai 0:5b88d5760320 69 if (!_socket) {
kenjiArai 0:5b88d5760320 70 _lock.unlock();
kenjiArai 0:5b88d5760320 71 return NSAPI_ERROR_NO_SOCKET;
kenjiArai 0:5b88d5760320 72 }
kenjiArai 0:5b88d5760320 73
kenjiArai 0:5b88d5760320 74 // Just in case - tell the stack not to callback any more, then remove this socket.
kenjiArai 0:5b88d5760320 75 _stack->socket_attach(_socket, 0, 0);
kenjiArai 0:5b88d5760320 76 nsapi_socket_t socket = _socket;
kenjiArai 0:5b88d5760320 77 _socket = 0;
kenjiArai 0:5b88d5760320 78 ret = _stack->socket_close(socket);
kenjiArai 0:5b88d5760320 79 _stack = 0; // Invalidate the stack pointer - otherwise open() fails.
kenjiArai 0:5b88d5760320 80 _socket_stats.stats_update_socket_state(this, SOCK_CLOSED);
kenjiArai 0:5b88d5760320 81 // Wakeup anything in a blocking operation
kenjiArai 0:5b88d5760320 82 // on this socket
kenjiArai 0:5b88d5760320 83 event();
kenjiArai 0:5b88d5760320 84
kenjiArai 0:5b88d5760320 85 // Wait until all readers and writers are gone
kenjiArai 0:5b88d5760320 86 while (_readers || _writers) {
kenjiArai 0:5b88d5760320 87 _lock.unlock();
kenjiArai 0:5b88d5760320 88 _event_flag.wait_any(FINISHED_FLAG, osWaitForever);
kenjiArai 0:5b88d5760320 89 _lock.lock();
kenjiArai 0:5b88d5760320 90 }
kenjiArai 0:5b88d5760320 91 _interface_name[0] = '\0';
kenjiArai 0:5b88d5760320 92 _lock.unlock();
kenjiArai 0:5b88d5760320 93
kenjiArai 0:5b88d5760320 94 // When allocated by accept() call, will destroy itself on close();
kenjiArai 0:5b88d5760320 95 if (_factory_allocated) {
kenjiArai 0:5b88d5760320 96 delete this;
kenjiArai 0:5b88d5760320 97 }
kenjiArai 0:5b88d5760320 98 return ret;
kenjiArai 0:5b88d5760320 99 }
kenjiArai 0:5b88d5760320 100
kenjiArai 0:5b88d5760320 101 int InternetSocket::modify_multicast_group(const SocketAddress &address, nsapi_socket_option_t socketopt)
kenjiArai 0:5b88d5760320 102 {
kenjiArai 0:5b88d5760320 103 nsapi_ip_mreq_t mreq;
kenjiArai 0:5b88d5760320 104
kenjiArai 0:5b88d5760320 105 // Set up group address
kenjiArai 0:5b88d5760320 106 mreq.imr_multiaddr = address.get_addr();
kenjiArai 0:5b88d5760320 107 mreq.imr_interface = nsapi_addr_t(); // Default address, NSAPI_UNSPEC
kenjiArai 0:5b88d5760320 108
kenjiArai 0:5b88d5760320 109 return this->setsockopt(NSAPI_SOCKET, socketopt, &mreq, sizeof(mreq));
kenjiArai 0:5b88d5760320 110 }
kenjiArai 0:5b88d5760320 111
kenjiArai 0:5b88d5760320 112 int InternetSocket::join_multicast_group(const SocketAddress &address)
kenjiArai 0:5b88d5760320 113 {
kenjiArai 0:5b88d5760320 114 return modify_multicast_group(address, NSAPI_ADD_MEMBERSHIP);
kenjiArai 0:5b88d5760320 115 }
kenjiArai 0:5b88d5760320 116
kenjiArai 0:5b88d5760320 117 int InternetSocket::leave_multicast_group(const SocketAddress &address)
kenjiArai 0:5b88d5760320 118 {
kenjiArai 0:5b88d5760320 119 return modify_multicast_group(address, NSAPI_DROP_MEMBERSHIP);
kenjiArai 0:5b88d5760320 120 }
kenjiArai 0:5b88d5760320 121
kenjiArai 0:5b88d5760320 122
kenjiArai 0:5b88d5760320 123 nsapi_error_t InternetSocket::bind(uint16_t port)
kenjiArai 0:5b88d5760320 124 {
kenjiArai 0:5b88d5760320 125 // Underlying bind is thread safe
kenjiArai 0:5b88d5760320 126 SocketAddress addr(0, port);
kenjiArai 0:5b88d5760320 127 return bind(addr);
kenjiArai 0:5b88d5760320 128 }
kenjiArai 0:5b88d5760320 129
kenjiArai 0:5b88d5760320 130 nsapi_error_t InternetSocket::bind(const char *address, uint16_t port)
kenjiArai 0:5b88d5760320 131 {
kenjiArai 0:5b88d5760320 132 // Underlying bind is thread safe
kenjiArai 0:5b88d5760320 133 SocketAddress addr(address, port);
kenjiArai 0:5b88d5760320 134 return bind(addr);
kenjiArai 0:5b88d5760320 135 }
kenjiArai 0:5b88d5760320 136
kenjiArai 0:5b88d5760320 137 nsapi_error_t InternetSocket::bind(const SocketAddress &address)
kenjiArai 0:5b88d5760320 138 {
kenjiArai 0:5b88d5760320 139 _lock.lock();
kenjiArai 0:5b88d5760320 140 nsapi_error_t ret;
kenjiArai 0:5b88d5760320 141
kenjiArai 0:5b88d5760320 142 if (!_socket) {
kenjiArai 0:5b88d5760320 143 ret = NSAPI_ERROR_NO_SOCKET;
kenjiArai 0:5b88d5760320 144 } else {
kenjiArai 0:5b88d5760320 145 ret = _stack->socket_bind(_socket, address);
kenjiArai 0:5b88d5760320 146 }
kenjiArai 0:5b88d5760320 147
kenjiArai 0:5b88d5760320 148 _lock.unlock();
kenjiArai 0:5b88d5760320 149 return ret;
kenjiArai 0:5b88d5760320 150 }
kenjiArai 0:5b88d5760320 151
kenjiArai 0:5b88d5760320 152 void InternetSocket::set_blocking(bool blocking)
kenjiArai 0:5b88d5760320 153 {
kenjiArai 0:5b88d5760320 154 // InternetSocket::set_timeout is thread safe
kenjiArai 0:5b88d5760320 155 set_timeout(blocking ? -1 : 0);
kenjiArai 0:5b88d5760320 156 }
kenjiArai 0:5b88d5760320 157
kenjiArai 0:5b88d5760320 158 void InternetSocket::set_timeout(int timeout)
kenjiArai 0:5b88d5760320 159 {
kenjiArai 0:5b88d5760320 160 _lock.lock();
kenjiArai 0:5b88d5760320 161
kenjiArai 0:5b88d5760320 162 if (timeout >= 0) {
kenjiArai 0:5b88d5760320 163 _timeout = (uint32_t)timeout;
kenjiArai 0:5b88d5760320 164 } else {
kenjiArai 0:5b88d5760320 165 _timeout = osWaitForever;
kenjiArai 0:5b88d5760320 166 }
kenjiArai 0:5b88d5760320 167
kenjiArai 0:5b88d5760320 168 _lock.unlock();
kenjiArai 0:5b88d5760320 169 }
kenjiArai 0:5b88d5760320 170
kenjiArai 0:5b88d5760320 171 nsapi_error_t InternetSocket::setsockopt(int level, int optname, const void *optval, unsigned optlen)
kenjiArai 0:5b88d5760320 172 {
kenjiArai 0:5b88d5760320 173 _lock.lock();
kenjiArai 0:5b88d5760320 174 nsapi_error_t ret;
kenjiArai 0:5b88d5760320 175
kenjiArai 0:5b88d5760320 176 if (!_socket) {
kenjiArai 0:5b88d5760320 177 ret = NSAPI_ERROR_NO_SOCKET;
kenjiArai 0:5b88d5760320 178 } else {
kenjiArai 0:5b88d5760320 179 ret = _stack->setsockopt(_socket, level, optname, optval, optlen);
kenjiArai 0:5b88d5760320 180 if (optname == NSAPI_BIND_TO_DEVICE && level == NSAPI_SOCKET) {
kenjiArai 0:5b88d5760320 181 strncpy(_interface_name, static_cast<const char *>(optval), optlen);
kenjiArai 0:5b88d5760320 182 }
kenjiArai 0:5b88d5760320 183 }
kenjiArai 0:5b88d5760320 184
kenjiArai 0:5b88d5760320 185 _lock.unlock();
kenjiArai 0:5b88d5760320 186 return ret;
kenjiArai 0:5b88d5760320 187 }
kenjiArai 0:5b88d5760320 188
kenjiArai 0:5b88d5760320 189 nsapi_error_t InternetSocket::getsockopt(int level, int optname, void *optval, unsigned *optlen)
kenjiArai 0:5b88d5760320 190 {
kenjiArai 0:5b88d5760320 191 _lock.lock();
kenjiArai 0:5b88d5760320 192 nsapi_error_t ret;
kenjiArai 0:5b88d5760320 193
kenjiArai 0:5b88d5760320 194 if (!_socket) {
kenjiArai 0:5b88d5760320 195 ret = NSAPI_ERROR_NO_SOCKET;
kenjiArai 0:5b88d5760320 196 } else {
kenjiArai 0:5b88d5760320 197 ret = _stack->getsockopt(_socket, level, optname, optval, optlen);
kenjiArai 0:5b88d5760320 198 }
kenjiArai 0:5b88d5760320 199
kenjiArai 0:5b88d5760320 200 _lock.unlock();
kenjiArai 0:5b88d5760320 201 return ret;
kenjiArai 0:5b88d5760320 202
kenjiArai 0:5b88d5760320 203 }
kenjiArai 0:5b88d5760320 204 void InternetSocket::event()
kenjiArai 0:5b88d5760320 205 {
kenjiArai 0:5b88d5760320 206 _event_flag.set(READ_FLAG | WRITE_FLAG);
kenjiArai 0:5b88d5760320 207
kenjiArai 0:5b88d5760320 208 if (_callback && !core_util_atomic_flag_test_and_set(&_pending)) {
kenjiArai 0:5b88d5760320 209 _callback();
kenjiArai 0:5b88d5760320 210 }
kenjiArai 0:5b88d5760320 211 }
kenjiArai 0:5b88d5760320 212
kenjiArai 0:5b88d5760320 213 void InternetSocket::sigio(Callback<void()> callback)
kenjiArai 0:5b88d5760320 214 {
kenjiArai 0:5b88d5760320 215 core_util_critical_section_enter();
kenjiArai 0:5b88d5760320 216 _callback = callback;
kenjiArai 0:5b88d5760320 217 core_util_critical_section_exit();
kenjiArai 0:5b88d5760320 218 }
kenjiArai 0:5b88d5760320 219
kenjiArai 0:5b88d5760320 220 void InternetSocket::attach(Callback<void()> callback)
kenjiArai 0:5b88d5760320 221 {
kenjiArai 0:5b88d5760320 222 sigio(callback);
kenjiArai 0:5b88d5760320 223 }
kenjiArai 0:5b88d5760320 224
kenjiArai 0:5b88d5760320 225 nsapi_error_t InternetSocket::getpeername(SocketAddress *address)
kenjiArai 0:5b88d5760320 226 {
kenjiArai 0:5b88d5760320 227 if (!_socket) {
kenjiArai 0:5b88d5760320 228 return NSAPI_ERROR_NO_SOCKET;
kenjiArai 0:5b88d5760320 229 }
kenjiArai 0:5b88d5760320 230 if (!_remote_peer) {
kenjiArai 0:5b88d5760320 231 return NSAPI_ERROR_NO_CONNECTION;
kenjiArai 0:5b88d5760320 232 }
kenjiArai 0:5b88d5760320 233 *address = _remote_peer;
kenjiArai 0:5b88d5760320 234 return NSAPI_ERROR_OK;
kenjiArai 0:5b88d5760320 235 }