RTC auf true

Committer:
kevman
Date:
Wed Nov 28 15:10:15 2018 +0000
Revision:
0:38ceb79fef03
RTC modified

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kevman 0:38ceb79fef03 1 /*
kevman 0:38ceb79fef03 2 * Copyright (c) 2016-2017, Arm Limited and affiliates.
kevman 0:38ceb79fef03 3 * SPDX-License-Identifier: Apache-2.0
kevman 0:38ceb79fef03 4 *
kevman 0:38ceb79fef03 5 * Licensed under the Apache License, Version 2.0 (the "License");
kevman 0:38ceb79fef03 6 * you may not use this file except in compliance with the License.
kevman 0:38ceb79fef03 7 * You may obtain a copy of the License at
kevman 0:38ceb79fef03 8 *
kevman 0:38ceb79fef03 9 * http://www.apache.org/licenses/LICENSE-2.0
kevman 0:38ceb79fef03 10 *
kevman 0:38ceb79fef03 11 * Unless required by applicable law or agreed to in writing, software
kevman 0:38ceb79fef03 12 * distributed under the License is distributed on an "AS IS" BASIS,
kevman 0:38ceb79fef03 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kevman 0:38ceb79fef03 14 * See the License for the specific language governing permissions and
kevman 0:38ceb79fef03 15 * limitations under the License.
kevman 0:38ceb79fef03 16 */
kevman 0:38ceb79fef03 17
kevman 0:38ceb79fef03 18 /* Nanostack implementation of NetworkSocketAPI */
kevman 0:38ceb79fef03 19
kevman 0:38ceb79fef03 20 #include "Nanostack.h"
kevman 0:38ceb79fef03 21 #include "NanostackLockGuard.h"
kevman 0:38ceb79fef03 22
kevman 0:38ceb79fef03 23 #include "ns_address.h"
kevman 0:38ceb79fef03 24 #include "nsdynmemLIB.h"
kevman 0:38ceb79fef03 25 #include "eventOS_scheduler.h"
kevman 0:38ceb79fef03 26 #include "eventOS_event_timer.h"
kevman 0:38ceb79fef03 27 #include "randLIB.h"
kevman 0:38ceb79fef03 28 #include "ip6string.h"
kevman 0:38ceb79fef03 29
kevman 0:38ceb79fef03 30 #include "mesh_system.h" // from inside mbed-mesh-api
kevman 0:38ceb79fef03 31 #include "socket_api.h"
kevman 0:38ceb79fef03 32 #include "net_interface.h"
kevman 0:38ceb79fef03 33
kevman 0:38ceb79fef03 34 // Uncomment to enable trace
kevman 0:38ceb79fef03 35 //#define HAVE_DEBUG
kevman 0:38ceb79fef03 36 #include "ns_trace.h"
kevman 0:38ceb79fef03 37 #define TRACE_GROUP "nsif"
kevman 0:38ceb79fef03 38
kevman 0:38ceb79fef03 39 #define NS_INTERFACE_SOCKETS_MAX 16 //same as NanoStack SOCKET_MAX
kevman 0:38ceb79fef03 40
kevman 0:38ceb79fef03 41 #define MALLOC ns_dyn_mem_alloc
kevman 0:38ceb79fef03 42 #define FREE ns_dyn_mem_free
kevman 0:38ceb79fef03 43
kevman 0:38ceb79fef03 44 // Socket state progressions:
kevman 0:38ceb79fef03 45 // UDP: UNOPENED -> DATAGRAM
kevman 0:38ceb79fef03 46 // TCP client: UNOPENED -> OPENED -> CONNECTING -> STREAM -> CLOSED
kevman 0:38ceb79fef03 47 // TCP server: UNOPENED -> OPENED -> LISTENING
kevman 0:38ceb79fef03 48 // TCP accept: UNOPENED -> STREAM -> CLOSED
kevman 0:38ceb79fef03 49 enum socket_mode_t {
kevman 0:38ceb79fef03 50 SOCKET_MODE_UNOPENED, // No socket ID
kevman 0:38ceb79fef03 51 SOCKET_MODE_DATAGRAM, // Socket is datagram type
kevman 0:38ceb79fef03 52 SOCKET_MODE_OPENED, // Socket ID but no assigned use yet
kevman 0:38ceb79fef03 53 SOCKET_MODE_CONNECTING, // Socket is connecting but not open yet
kevman 0:38ceb79fef03 54 SOCKET_MODE_STREAM, // Socket has an open stream
kevman 0:38ceb79fef03 55 SOCKET_MODE_CLOSED, // Socket is closed and resources are freed
kevman 0:38ceb79fef03 56 SOCKET_MODE_LISTENING, // Socket is listening for connections
kevman 0:38ceb79fef03 57 };
kevman 0:38ceb79fef03 58
kevman 0:38ceb79fef03 59 #define CALL_EVENT 0x12
kevman 0:38ceb79fef03 60
kevman 0:38ceb79fef03 61 class NanostackSocket {
kevman 0:38ceb79fef03 62 public:
kevman 0:38ceb79fef03 63 static void socket_callback(void *cb);
kevman 0:38ceb79fef03 64 static void* operator new(std::size_t sz);
kevman 0:38ceb79fef03 65 static void operator delete(void* ptr);
kevman 0:38ceb79fef03 66
kevman 0:38ceb79fef03 67 NanostackSocket(int8_t protocol);
kevman 0:38ceb79fef03 68 ~NanostackSocket(void);
kevman 0:38ceb79fef03 69 bool open(void);
kevman 0:38ceb79fef03 70 int accept(NanostackSocket *accepted_socket, ns_address_t *addr);
kevman 0:38ceb79fef03 71 void close(void);
kevman 0:38ceb79fef03 72 bool closed(void) {return SOCKET_MODE_CLOSED == mode;}
kevman 0:38ceb79fef03 73 bool is_connecting(void);
kevman 0:38ceb79fef03 74 void set_connecting(ns_address_t *addr);
kevman 0:38ceb79fef03 75 bool is_connected(void);
kevman 0:38ceb79fef03 76 void set_connected(void);
kevman 0:38ceb79fef03 77 bool is_listening(void);
kevman 0:38ceb79fef03 78 void set_listening(void);
kevman 0:38ceb79fef03 79
kevman 0:38ceb79fef03 80 // Socket events from nanostack
kevman 0:38ceb79fef03 81 void event_data(socket_callback_t *sock_cb);
kevman 0:38ceb79fef03 82 void event_connect_done(socket_callback_t *sock_cb);
kevman 0:38ceb79fef03 83 void event_connect_fail(socket_callback_t *sock_cb);
kevman 0:38ceb79fef03 84 void event_connect_closed(socket_callback_t *sock_cb);
kevman 0:38ceb79fef03 85 void event_connection_reset(socket_callback_t *sock_cb);
kevman 0:38ceb79fef03 86 void event_tx_done(socket_callback_t *sock_cb);
kevman 0:38ceb79fef03 87 void event_tx_fail(socket_callback_t *sock_cb);
kevman 0:38ceb79fef03 88 void event_incoming_connection(socket_callback_t *sock_cb);
kevman 0:38ceb79fef03 89
kevman 0:38ceb79fef03 90 // Run callback to signal the next layer of the NSAPI
kevman 0:38ceb79fef03 91 void signal_event(void);
kevman 0:38ceb79fef03 92
kevman 0:38ceb79fef03 93 void (*callback)(void *);
kevman 0:38ceb79fef03 94 void *callback_data;
kevman 0:38ceb79fef03 95 int8_t socket_id; /*!< allocated socket ID */
kevman 0:38ceb79fef03 96 int8_t proto; /*!< UDP or TCP */
kevman 0:38ceb79fef03 97 bool addr_valid;
kevman 0:38ceb79fef03 98 ns_address_t ns_address;
kevman 0:38ceb79fef03 99 private:
kevman 0:38ceb79fef03 100 bool attach(int8_t socket_id);
kevman 0:38ceb79fef03 101 socket_mode_t mode;
kevman 0:38ceb79fef03 102 };
kevman 0:38ceb79fef03 103
kevman 0:38ceb79fef03 104 static NanostackSocket * socket_tbl[NS_INTERFACE_SOCKETS_MAX];
kevman 0:38ceb79fef03 105
kevman 0:38ceb79fef03 106 nsapi_error_t map_mesh_error(mesh_error_t err)
kevman 0:38ceb79fef03 107 {
kevman 0:38ceb79fef03 108 switch (err) {
kevman 0:38ceb79fef03 109 case MESH_ERROR_NONE: return 0;
kevman 0:38ceb79fef03 110 case MESH_ERROR_MEMORY: return NSAPI_ERROR_NO_MEMORY;
kevman 0:38ceb79fef03 111 case MESH_ERROR_PARAM: return NSAPI_ERROR_UNSUPPORTED;
kevman 0:38ceb79fef03 112 case MESH_ERROR_STATE: return NSAPI_ERROR_DEVICE_ERROR;
kevman 0:38ceb79fef03 113 default: return NSAPI_ERROR_DEVICE_ERROR;
kevman 0:38ceb79fef03 114 }
kevman 0:38ceb79fef03 115 }
kevman 0:38ceb79fef03 116
kevman 0:38ceb79fef03 117 static void convert_mbed_addr_to_ns(ns_address_t *ns_addr,
kevman 0:38ceb79fef03 118 const SocketAddress *s_addr)
kevman 0:38ceb79fef03 119 {
kevman 0:38ceb79fef03 120 ns_addr->type = ADDRESS_IPV6;
kevman 0:38ceb79fef03 121 ns_addr->identifier = s_addr->get_port();
kevman 0:38ceb79fef03 122 memcpy(ns_addr->address, s_addr->get_ip_bytes(), 16);
kevman 0:38ceb79fef03 123 }
kevman 0:38ceb79fef03 124
kevman 0:38ceb79fef03 125 static void convert_ns_addr_to_mbed(SocketAddress *s_addr, const ns_address_t *ns_addr)
kevman 0:38ceb79fef03 126 {
kevman 0:38ceb79fef03 127 s_addr->set_port(ns_addr->identifier);
kevman 0:38ceb79fef03 128 s_addr->set_ip_bytes(ns_addr->address, NSAPI_IPv6);
kevman 0:38ceb79fef03 129 }
kevman 0:38ceb79fef03 130
kevman 0:38ceb79fef03 131 static int8_t find_interface_by_address(const uint8_t target_addr[16])
kevman 0:38ceb79fef03 132 {
kevman 0:38ceb79fef03 133 for (int if_id = 1; if_id <= 127; if_id++) {
kevman 0:38ceb79fef03 134 int i = 0;
kevman 0:38ceb79fef03 135 uint8_t if_addr[16];
kevman 0:38ceb79fef03 136 while (arm_net_address_list_get_next(if_id, &i, if_addr) == 0) {
kevman 0:38ceb79fef03 137 if (memcmp(target_addr, if_addr, 16) == 0) {
kevman 0:38ceb79fef03 138 return if_id;
kevman 0:38ceb79fef03 139 }
kevman 0:38ceb79fef03 140 }
kevman 0:38ceb79fef03 141 }
kevman 0:38ceb79fef03 142 return -1;
kevman 0:38ceb79fef03 143 }
kevman 0:38ceb79fef03 144
kevman 0:38ceb79fef03 145 void* NanostackSocket::operator new(std::size_t sz) {
kevman 0:38ceb79fef03 146 return MALLOC(sz);
kevman 0:38ceb79fef03 147 }
kevman 0:38ceb79fef03 148 void NanostackSocket::operator delete(void* ptr) {
kevman 0:38ceb79fef03 149 FREE(ptr);
kevman 0:38ceb79fef03 150 }
kevman 0:38ceb79fef03 151
kevman 0:38ceb79fef03 152 NanostackSocket::NanostackSocket(int8_t protocol)
kevman 0:38ceb79fef03 153 {
kevman 0:38ceb79fef03 154 nanostack_assert_locked();
kevman 0:38ceb79fef03 155
kevman 0:38ceb79fef03 156 callback = NULL;
kevman 0:38ceb79fef03 157 callback_data = NULL;
kevman 0:38ceb79fef03 158 socket_id = -1;
kevman 0:38ceb79fef03 159 proto = protocol;
kevman 0:38ceb79fef03 160 addr_valid = false;
kevman 0:38ceb79fef03 161 memset(&ns_address, 0, sizeof(ns_address));
kevman 0:38ceb79fef03 162 mode = SOCKET_MODE_UNOPENED;
kevman 0:38ceb79fef03 163 }
kevman 0:38ceb79fef03 164
kevman 0:38ceb79fef03 165 NanostackSocket::~NanostackSocket()
kevman 0:38ceb79fef03 166 {
kevman 0:38ceb79fef03 167 nanostack_assert_locked();
kevman 0:38ceb79fef03 168
kevman 0:38ceb79fef03 169 if (mode != SOCKET_MODE_CLOSED) {
kevman 0:38ceb79fef03 170 close();
kevman 0:38ceb79fef03 171 }
kevman 0:38ceb79fef03 172 }
kevman 0:38ceb79fef03 173
kevman 0:38ceb79fef03 174 bool NanostackSocket::open(void)
kevman 0:38ceb79fef03 175 {
kevman 0:38ceb79fef03 176 nanostack_assert_locked();
kevman 0:38ceb79fef03 177 MBED_ASSERT(SOCKET_MODE_UNOPENED == mode);
kevman 0:38ceb79fef03 178
kevman 0:38ceb79fef03 179 int temp_socket = socket_open(proto, 0, socket_callback);
kevman 0:38ceb79fef03 180
kevman 0:38ceb79fef03 181 if (temp_socket < 0) {
kevman 0:38ceb79fef03 182 tr_error("NanostackSocket::open() failed");
kevman 0:38ceb79fef03 183 return false;
kevman 0:38ceb79fef03 184 }
kevman 0:38ceb79fef03 185
kevman 0:38ceb79fef03 186 if (proto == SOCKET_TCP) {
kevman 0:38ceb79fef03 187 /* Receive and send buffers enabled by default */
kevman 0:38ceb79fef03 188 mode = SOCKET_MODE_OPENED;
kevman 0:38ceb79fef03 189 } else {
kevman 0:38ceb79fef03 190 static const int32_t rcvbuf_size = 2048;
kevman 0:38ceb79fef03 191 socket_setsockopt(temp_socket, SOCKET_SOL_SOCKET, SOCKET_SO_RCVBUF, &rcvbuf_size, sizeof rcvbuf_size);
kevman 0:38ceb79fef03 192 mode = SOCKET_MODE_DATAGRAM;
kevman 0:38ceb79fef03 193 }
kevman 0:38ceb79fef03 194
kevman 0:38ceb79fef03 195 return attach(temp_socket);
kevman 0:38ceb79fef03 196 }
kevman 0:38ceb79fef03 197
kevman 0:38ceb79fef03 198 int NanostackSocket::accept(NanostackSocket *accepted_socket, ns_address_t *addr)
kevman 0:38ceb79fef03 199 {
kevman 0:38ceb79fef03 200 nanostack_assert_locked();
kevman 0:38ceb79fef03 201 MBED_ASSERT(SOCKET_MODE_LISTENING == mode && SOCKET_MODE_UNOPENED == accepted_socket->mode);
kevman 0:38ceb79fef03 202
kevman 0:38ceb79fef03 203 int temp_socket = socket_accept(socket_id, addr, socket_callback);
kevman 0:38ceb79fef03 204 if (temp_socket < 0) {
kevman 0:38ceb79fef03 205 tr_error("NanostackSocket::accept() failed");
kevman 0:38ceb79fef03 206 return temp_socket;
kevman 0:38ceb79fef03 207 }
kevman 0:38ceb79fef03 208 if (!accepted_socket->attach(temp_socket)) {
kevman 0:38ceb79fef03 209 return -1;
kevman 0:38ceb79fef03 210 }
kevman 0:38ceb79fef03 211 accepted_socket->mode = SOCKET_MODE_STREAM;
kevman 0:38ceb79fef03 212 return temp_socket;
kevman 0:38ceb79fef03 213 }
kevman 0:38ceb79fef03 214
kevman 0:38ceb79fef03 215 bool NanostackSocket::attach(int8_t temp_socket)
kevman 0:38ceb79fef03 216 {
kevman 0:38ceb79fef03 217 nanostack_assert_locked();
kevman 0:38ceb79fef03 218 if (temp_socket >= NS_INTERFACE_SOCKETS_MAX) {
kevman 0:38ceb79fef03 219 MBED_ASSERT(false);
kevman 0:38ceb79fef03 220 return false;
kevman 0:38ceb79fef03 221 }
kevman 0:38ceb79fef03 222 if (socket_tbl[temp_socket] != NULL) {
kevman 0:38ceb79fef03 223 MBED_ASSERT(false);
kevman 0:38ceb79fef03 224 return false;
kevman 0:38ceb79fef03 225 }
kevman 0:38ceb79fef03 226 socket_id = temp_socket;
kevman 0:38ceb79fef03 227 socket_tbl[socket_id] = this;
kevman 0:38ceb79fef03 228 return true;
kevman 0:38ceb79fef03 229 }
kevman 0:38ceb79fef03 230
kevman 0:38ceb79fef03 231 void NanostackSocket::close()
kevman 0:38ceb79fef03 232 {
kevman 0:38ceb79fef03 233 nanostack_assert_locked();
kevman 0:38ceb79fef03 234 MBED_ASSERT(mode != SOCKET_MODE_CLOSED);
kevman 0:38ceb79fef03 235
kevman 0:38ceb79fef03 236 if (socket_id >= 0) {
kevman 0:38ceb79fef03 237 nsapi_error_t ret = socket_close(socket_id);
kevman 0:38ceb79fef03 238 MBED_ASSERT(0 == ret);
kevman 0:38ceb79fef03 239 MBED_ASSERT(socket_tbl[socket_id] == this);
kevman 0:38ceb79fef03 240 socket_tbl[socket_id] = NULL;
kevman 0:38ceb79fef03 241 socket_id = -1;
kevman 0:38ceb79fef03 242 } else {
kevman 0:38ceb79fef03 243 MBED_ASSERT(SOCKET_MODE_UNOPENED == mode);
kevman 0:38ceb79fef03 244 }
kevman 0:38ceb79fef03 245
kevman 0:38ceb79fef03 246 mode = SOCKET_MODE_CLOSED;
kevman 0:38ceb79fef03 247 signal_event();
kevman 0:38ceb79fef03 248 }
kevman 0:38ceb79fef03 249
kevman 0:38ceb79fef03 250 bool NanostackSocket::is_connecting()
kevman 0:38ceb79fef03 251 {
kevman 0:38ceb79fef03 252 return SOCKET_MODE_CONNECTING == mode;
kevman 0:38ceb79fef03 253 }
kevman 0:38ceb79fef03 254
kevman 0:38ceb79fef03 255 void NanostackSocket::set_connecting(ns_address_t *addr)
kevman 0:38ceb79fef03 256 {
kevman 0:38ceb79fef03 257 nanostack_assert_locked();
kevman 0:38ceb79fef03 258 MBED_ASSERT(SOCKET_MODE_OPENED == mode);
kevman 0:38ceb79fef03 259
kevman 0:38ceb79fef03 260 memcpy(&ns_address, addr, sizeof(ns_address_t));
kevman 0:38ceb79fef03 261 mode = SOCKET_MODE_CONNECTING;
kevman 0:38ceb79fef03 262 }
kevman 0:38ceb79fef03 263
kevman 0:38ceb79fef03 264 bool NanostackSocket::is_connected()
kevman 0:38ceb79fef03 265 {
kevman 0:38ceb79fef03 266 return SOCKET_MODE_STREAM == mode;
kevman 0:38ceb79fef03 267 }
kevman 0:38ceb79fef03 268
kevman 0:38ceb79fef03 269 void NanostackSocket::set_connected()
kevman 0:38ceb79fef03 270 {
kevman 0:38ceb79fef03 271 nanostack_assert_locked();
kevman 0:38ceb79fef03 272 MBED_ASSERT(SOCKET_MODE_CONNECTING == mode);
kevman 0:38ceb79fef03 273
kevman 0:38ceb79fef03 274 mode = SOCKET_MODE_STREAM;
kevman 0:38ceb79fef03 275 }
kevman 0:38ceb79fef03 276
kevman 0:38ceb79fef03 277 bool NanostackSocket::is_listening()
kevman 0:38ceb79fef03 278 {
kevman 0:38ceb79fef03 279 return SOCKET_MODE_LISTENING == mode;
kevman 0:38ceb79fef03 280 }
kevman 0:38ceb79fef03 281
kevman 0:38ceb79fef03 282 void NanostackSocket::set_listening()
kevman 0:38ceb79fef03 283 {
kevman 0:38ceb79fef03 284 nanostack_assert_locked();
kevman 0:38ceb79fef03 285 MBED_ASSERT(SOCKET_MODE_OPENED == mode);
kevman 0:38ceb79fef03 286
kevman 0:38ceb79fef03 287 mode = SOCKET_MODE_LISTENING;
kevman 0:38ceb79fef03 288 }
kevman 0:38ceb79fef03 289
kevman 0:38ceb79fef03 290 void NanostackSocket::signal_event()
kevman 0:38ceb79fef03 291 {
kevman 0:38ceb79fef03 292 nanostack_assert_locked();
kevman 0:38ceb79fef03 293
kevman 0:38ceb79fef03 294 if (callback != NULL) {
kevman 0:38ceb79fef03 295 callback(callback_data);
kevman 0:38ceb79fef03 296 }
kevman 0:38ceb79fef03 297 }
kevman 0:38ceb79fef03 298
kevman 0:38ceb79fef03 299 void NanostackSocket::socket_callback(void *cb) {
kevman 0:38ceb79fef03 300 nanostack_assert_locked();
kevman 0:38ceb79fef03 301
kevman 0:38ceb79fef03 302 socket_callback_t *sock_cb = (socket_callback_t *) cb;
kevman 0:38ceb79fef03 303 NanostackSocket *socket = socket_tbl[sock_cb->socket_id];
kevman 0:38ceb79fef03 304 MBED_ASSERT(socket != NULL);
kevman 0:38ceb79fef03 305
kevman 0:38ceb79fef03 306 tr_debug("socket_callback() sock=%d, event=%d, interface=%d, data len=%d",
kevman 0:38ceb79fef03 307 sock_cb->socket_id, sock_cb->event_type, sock_cb->interface_id, sock_cb->d_len);
kevman 0:38ceb79fef03 308
kevman 0:38ceb79fef03 309 switch (sock_cb->event_type) {
kevman 0:38ceb79fef03 310 case SOCKET_DATA:
kevman 0:38ceb79fef03 311 tr_debug("SOCKET_DATA, sock=%d, bytes=%d", sock_cb->socket_id, sock_cb->d_len);
kevman 0:38ceb79fef03 312 socket->event_data(sock_cb);
kevman 0:38ceb79fef03 313 break;
kevman 0:38ceb79fef03 314 case SOCKET_CONNECT_DONE:
kevman 0:38ceb79fef03 315 tr_debug("SOCKET_CONNECT_DONE");
kevman 0:38ceb79fef03 316 socket->event_connect_done(sock_cb);
kevman 0:38ceb79fef03 317 break;
kevman 0:38ceb79fef03 318 case SOCKET_CONNECT_FAIL:
kevman 0:38ceb79fef03 319 tr_debug("SOCKET_CONNECT_FAIL");
kevman 0:38ceb79fef03 320 socket->event_connect_fail(sock_cb);
kevman 0:38ceb79fef03 321 break;
kevman 0:38ceb79fef03 322 case SOCKET_CONNECT_AUTH_FAIL:
kevman 0:38ceb79fef03 323 tr_debug("SOCKET_CONNECT_AUTH_FAIL");
kevman 0:38ceb79fef03 324 break;
kevman 0:38ceb79fef03 325 case SOCKET_INCOMING_CONNECTION:
kevman 0:38ceb79fef03 326 tr_debug("SOCKET_INCOMING_CONNECTION");
kevman 0:38ceb79fef03 327 socket->event_incoming_connection(sock_cb);
kevman 0:38ceb79fef03 328 break;
kevman 0:38ceb79fef03 329 case SOCKET_TX_FAIL:
kevman 0:38ceb79fef03 330 tr_debug("SOCKET_TX_FAIL");
kevman 0:38ceb79fef03 331 socket->event_tx_fail(sock_cb);
kevman 0:38ceb79fef03 332 break;
kevman 0:38ceb79fef03 333 case SOCKET_CONNECT_CLOSED:
kevman 0:38ceb79fef03 334 tr_debug("SOCKET_CONNECT_CLOSED");
kevman 0:38ceb79fef03 335 socket->event_connect_closed(sock_cb);
kevman 0:38ceb79fef03 336 break;
kevman 0:38ceb79fef03 337 case SOCKET_CONNECTION_RESET:
kevman 0:38ceb79fef03 338 tr_debug("SOCKET_CONNECTION_RESET");
kevman 0:38ceb79fef03 339 socket->event_connection_reset(sock_cb);
kevman 0:38ceb79fef03 340 break;
kevman 0:38ceb79fef03 341 case SOCKET_NO_ROUTE:
kevman 0:38ceb79fef03 342 tr_debug("SOCKET_NO_ROUTE");
kevman 0:38ceb79fef03 343 socket->event_tx_fail(sock_cb);
kevman 0:38ceb79fef03 344 break;
kevman 0:38ceb79fef03 345 case SOCKET_TX_DONE:
kevman 0:38ceb79fef03 346 socket->event_tx_done(sock_cb);
kevman 0:38ceb79fef03 347 break;
kevman 0:38ceb79fef03 348 case SOCKET_NO_RAM:
kevman 0:38ceb79fef03 349 tr_debug("SOCKET_NO_RAM");
kevman 0:38ceb79fef03 350 socket->event_tx_fail(sock_cb);
kevman 0:38ceb79fef03 351 break;
kevman 0:38ceb79fef03 352 case SOCKET_CONNECTION_PROBLEM:
kevman 0:38ceb79fef03 353 tr_debug("SOCKET_CONNECTION_PROBLEM");
kevman 0:38ceb79fef03 354 break;
kevman 0:38ceb79fef03 355 default:
kevman 0:38ceb79fef03 356 break;
kevman 0:38ceb79fef03 357 }
kevman 0:38ceb79fef03 358 }
kevman 0:38ceb79fef03 359
kevman 0:38ceb79fef03 360
kevman 0:38ceb79fef03 361 void NanostackSocket::event_data(socket_callback_t *sock_cb)
kevman 0:38ceb79fef03 362 {
kevman 0:38ceb79fef03 363 nanostack_assert_locked();
kevman 0:38ceb79fef03 364 MBED_ASSERT((SOCKET_MODE_STREAM == mode) ||
kevman 0:38ceb79fef03 365 (SOCKET_MODE_DATAGRAM == mode));
kevman 0:38ceb79fef03 366
kevman 0:38ceb79fef03 367 signal_event();
kevman 0:38ceb79fef03 368 }
kevman 0:38ceb79fef03 369
kevman 0:38ceb79fef03 370 void NanostackSocket::event_tx_done(socket_callback_t *sock_cb)
kevman 0:38ceb79fef03 371 {
kevman 0:38ceb79fef03 372 nanostack_assert_locked();
kevman 0:38ceb79fef03 373 MBED_ASSERT((SOCKET_MODE_STREAM == mode) ||
kevman 0:38ceb79fef03 374 (SOCKET_MODE_DATAGRAM == mode));
kevman 0:38ceb79fef03 375
kevman 0:38ceb79fef03 376 if (mode == SOCKET_MODE_DATAGRAM) {
kevman 0:38ceb79fef03 377 tr_debug("SOCKET_TX_DONE, %d bytes sent", sock_cb->d_len);
kevman 0:38ceb79fef03 378 } else if (mode == SOCKET_MODE_STREAM) {
kevman 0:38ceb79fef03 379 tr_debug("SOCKET_TX_DONE, %d bytes remaining", sock_cb->d_len);
kevman 0:38ceb79fef03 380 }
kevman 0:38ceb79fef03 381
kevman 0:38ceb79fef03 382 signal_event();
kevman 0:38ceb79fef03 383 }
kevman 0:38ceb79fef03 384
kevman 0:38ceb79fef03 385 void NanostackSocket::event_connect_done(socket_callback_t *sock_cb)
kevman 0:38ceb79fef03 386 {
kevman 0:38ceb79fef03 387 nanostack_assert_locked();
kevman 0:38ceb79fef03 388 MBED_ASSERT(SOCKET_MODE_CONNECTING == mode);
kevman 0:38ceb79fef03 389
kevman 0:38ceb79fef03 390 set_connected();
kevman 0:38ceb79fef03 391 signal_event();
kevman 0:38ceb79fef03 392 }
kevman 0:38ceb79fef03 393
kevman 0:38ceb79fef03 394 void NanostackSocket::event_connect_fail(socket_callback_t *sock_cb)
kevman 0:38ceb79fef03 395 {
kevman 0:38ceb79fef03 396 nanostack_assert_locked();
kevman 0:38ceb79fef03 397 MBED_ASSERT(mode == SOCKET_MODE_CONNECTING);
kevman 0:38ceb79fef03 398 close();
kevman 0:38ceb79fef03 399 }
kevman 0:38ceb79fef03 400
kevman 0:38ceb79fef03 401 void NanostackSocket::event_incoming_connection(socket_callback_t *sock_cb)
kevman 0:38ceb79fef03 402 {
kevman 0:38ceb79fef03 403 nanostack_assert_locked();
kevman 0:38ceb79fef03 404 MBED_ASSERT(mode == SOCKET_MODE_LISTENING);
kevman 0:38ceb79fef03 405 signal_event();
kevman 0:38ceb79fef03 406 }
kevman 0:38ceb79fef03 407
kevman 0:38ceb79fef03 408 void NanostackSocket::event_connect_closed(socket_callback_t *sock_cb)
kevman 0:38ceb79fef03 409 {
kevman 0:38ceb79fef03 410 nanostack_assert_locked();
kevman 0:38ceb79fef03 411
kevman 0:38ceb79fef03 412 // Can happen if we have an orderly close()
kevman 0:38ceb79fef03 413 // Might never happen as we have not implemented shutdown() in abstraction layer.
kevman 0:38ceb79fef03 414 MBED_ASSERT(mode == SOCKET_MODE_STREAM);
kevman 0:38ceb79fef03 415 close();
kevman 0:38ceb79fef03 416 }
kevman 0:38ceb79fef03 417
kevman 0:38ceb79fef03 418 void NanostackSocket::event_tx_fail(socket_callback_t *sock_cb)
kevman 0:38ceb79fef03 419 {
kevman 0:38ceb79fef03 420 nanostack_assert_locked();
kevman 0:38ceb79fef03 421
kevman 0:38ceb79fef03 422 switch (mode) {
kevman 0:38ceb79fef03 423 case SOCKET_MODE_CONNECTING:
kevman 0:38ceb79fef03 424 case SOCKET_MODE_STREAM:
kevman 0:38ceb79fef03 425 // TX_FAIL is fatal for stream sockets
kevman 0:38ceb79fef03 426 close();
kevman 0:38ceb79fef03 427 break;
kevman 0:38ceb79fef03 428 case SOCKET_MODE_DATAGRAM:
kevman 0:38ceb79fef03 429 // TX_FAIL is non-fatal for datagram sockets
kevman 0:38ceb79fef03 430 break;
kevman 0:38ceb79fef03 431 default:
kevman 0:38ceb79fef03 432 MBED_ASSERT(false);
kevman 0:38ceb79fef03 433 break;
kevman 0:38ceb79fef03 434 }
kevman 0:38ceb79fef03 435 }
kevman 0:38ceb79fef03 436
kevman 0:38ceb79fef03 437 void NanostackSocket::event_connection_reset(socket_callback_t *sock_cb)
kevman 0:38ceb79fef03 438 {
kevman 0:38ceb79fef03 439 nanostack_assert_locked();
kevman 0:38ceb79fef03 440
kevman 0:38ceb79fef03 441 // Only TCP sockets can be closed by the remote end
kevman 0:38ceb79fef03 442 MBED_ASSERT((SOCKET_MODE_STREAM == mode) ||
kevman 0:38ceb79fef03 443 (SOCKET_MODE_CONNECTING == mode));
kevman 0:38ceb79fef03 444 close();
kevman 0:38ceb79fef03 445 }
kevman 0:38ceb79fef03 446
kevman 0:38ceb79fef03 447 Nanostack::Nanostack()
kevman 0:38ceb79fef03 448 : call_event_tasklet(-1)
kevman 0:38ceb79fef03 449 {
kevman 0:38ceb79fef03 450 mesh_system_init();
kevman 0:38ceb79fef03 451 }
kevman 0:38ceb79fef03 452
kevman 0:38ceb79fef03 453 void Nanostack::call_event_tasklet_main(arm_event_s *event)
kevman 0:38ceb79fef03 454 {
kevman 0:38ceb79fef03 455 if (event->event_id == CALL_EVENT) {
kevman 0:38ceb79fef03 456 nanostack_callback *cb = static_cast<nanostack_callback *>(event->data_ptr);
kevman 0:38ceb79fef03 457 cb->callback();
kevman 0:38ceb79fef03 458 delete cb;
kevman 0:38ceb79fef03 459 }
kevman 0:38ceb79fef03 460 }
kevman 0:38ceb79fef03 461
kevman 0:38ceb79fef03 462 nsapi_error_t Nanostack::call_in(int delay, mbed::Callback<void()> func)
kevman 0:38ceb79fef03 463 {
kevman 0:38ceb79fef03 464 if (call_event_tasklet < 0) {
kevman 0:38ceb79fef03 465 call_event_tasklet = eventOS_event_handler_create(&call_event_tasklet_main, 0);
kevman 0:38ceb79fef03 466 if (call_event_tasklet < 0) {
kevman 0:38ceb79fef03 467 return NSAPI_ERROR_NO_MEMORY;
kevman 0:38ceb79fef03 468 }
kevman 0:38ceb79fef03 469 }
kevman 0:38ceb79fef03 470
kevman 0:38ceb79fef03 471 nanostack_callback *cb = new nanostack_callback;
kevman 0:38ceb79fef03 472 if (!cb) {
kevman 0:38ceb79fef03 473 return NSAPI_ERROR_NO_MEMORY;
kevman 0:38ceb79fef03 474 }
kevman 0:38ceb79fef03 475
kevman 0:38ceb79fef03 476 cb->callback = func;
kevman 0:38ceb79fef03 477
kevman 0:38ceb79fef03 478 arm_event_s event;
kevman 0:38ceb79fef03 479
kevman 0:38ceb79fef03 480 event.sender = call_event_tasklet,
kevman 0:38ceb79fef03 481 event.event_id = CALL_EVENT,
kevman 0:38ceb79fef03 482 event.receiver = call_event_tasklet,
kevman 0:38ceb79fef03 483 event.data_ptr = cb;
kevman 0:38ceb79fef03 484 event.event_type = APPLICATION_EVENT;
kevman 0:38ceb79fef03 485 event.priority = ARM_LIB_LOW_PRIORITY_EVENT;
kevman 0:38ceb79fef03 486
kevman 0:38ceb79fef03 487 if (delay) {
kevman 0:38ceb79fef03 488 uint32_t ticks = eventOS_event_timer_ms_to_ticks(delay);
kevman 0:38ceb79fef03 489 if (!eventOS_event_send_in(&event, ticks)) {
kevman 0:38ceb79fef03 490 delete cb;
kevman 0:38ceb79fef03 491 return NSAPI_ERROR_NO_MEMORY;
kevman 0:38ceb79fef03 492 }
kevman 0:38ceb79fef03 493 } else {
kevman 0:38ceb79fef03 494 if (eventOS_event_send(&event) < 0) {
kevman 0:38ceb79fef03 495 delete cb;
kevman 0:38ceb79fef03 496 return NSAPI_ERROR_NO_MEMORY;
kevman 0:38ceb79fef03 497 }
kevman 0:38ceb79fef03 498 }
kevman 0:38ceb79fef03 499
kevman 0:38ceb79fef03 500 return NSAPI_ERROR_OK;
kevman 0:38ceb79fef03 501 }
kevman 0:38ceb79fef03 502
kevman 0:38ceb79fef03 503 Nanostack::call_in_callback_cb_t Nanostack::get_call_in_callback()
kevman 0:38ceb79fef03 504 {
kevman 0:38ceb79fef03 505 call_in_callback_cb_t cb(this, &Nanostack::call_in);
kevman 0:38ceb79fef03 506 return cb;
kevman 0:38ceb79fef03 507 }
kevman 0:38ceb79fef03 508
kevman 0:38ceb79fef03 509 const char * Nanostack::get_ip_address()
kevman 0:38ceb79fef03 510 {
kevman 0:38ceb79fef03 511 NanostackLockGuard lock;
kevman 0:38ceb79fef03 512
kevman 0:38ceb79fef03 513 for (int if_id = 1; if_id <= 127; if_id++) {
kevman 0:38ceb79fef03 514 uint8_t address[16];
kevman 0:38ceb79fef03 515 int ret = arm_net_address_get(if_id, ADDR_IPV6_GP, address);
kevman 0:38ceb79fef03 516 if (ret == 0) {
kevman 0:38ceb79fef03 517 ip6tos(address, text_ip_address);
kevman 0:38ceb79fef03 518 return text_ip_address;
kevman 0:38ceb79fef03 519 }
kevman 0:38ceb79fef03 520 }
kevman 0:38ceb79fef03 521 // Must result a valid IPv6 address
kevman 0:38ceb79fef03 522 // For gethostbyname() to detect IP version.
kevman 0:38ceb79fef03 523 return "::";
kevman 0:38ceb79fef03 524 }
kevman 0:38ceb79fef03 525
kevman 0:38ceb79fef03 526 nsapi_error_t Nanostack::socket_open(void **handle, nsapi_protocol_t protocol)
kevman 0:38ceb79fef03 527 {
kevman 0:38ceb79fef03 528 // Validate parameters
kevman 0:38ceb79fef03 529 if (NULL == handle) {
kevman 0:38ceb79fef03 530 MBED_ASSERT(false);
kevman 0:38ceb79fef03 531 return NSAPI_ERROR_NO_SOCKET;
kevman 0:38ceb79fef03 532 }
kevman 0:38ceb79fef03 533 int8_t ns_proto;
kevman 0:38ceb79fef03 534 if (NSAPI_UDP == protocol) {
kevman 0:38ceb79fef03 535 ns_proto = SOCKET_UDP;
kevman 0:38ceb79fef03 536 } else if (NSAPI_TCP == protocol) {
kevman 0:38ceb79fef03 537 ns_proto = SOCKET_TCP;
kevman 0:38ceb79fef03 538 } else {
kevman 0:38ceb79fef03 539 MBED_ASSERT(false);
kevman 0:38ceb79fef03 540 return NSAPI_ERROR_UNSUPPORTED;
kevman 0:38ceb79fef03 541 }
kevman 0:38ceb79fef03 542 *handle = (void*)NULL;
kevman 0:38ceb79fef03 543
kevman 0:38ceb79fef03 544 NanostackLockGuard lock;
kevman 0:38ceb79fef03 545
kevman 0:38ceb79fef03 546 NanostackSocket * socket = new NanostackSocket(ns_proto);
kevman 0:38ceb79fef03 547 if (socket == NULL) {
kevman 0:38ceb79fef03 548 tr_debug("socket_open() ret=%i", NSAPI_ERROR_NO_MEMORY);
kevman 0:38ceb79fef03 549 return NSAPI_ERROR_NO_MEMORY;
kevman 0:38ceb79fef03 550 }
kevman 0:38ceb79fef03 551 if (!socket->open()) {
kevman 0:38ceb79fef03 552 delete socket;
kevman 0:38ceb79fef03 553 tr_debug("socket_open() ret=%i", NSAPI_ERROR_NO_MEMORY);
kevman 0:38ceb79fef03 554 return NSAPI_ERROR_NO_MEMORY;
kevman 0:38ceb79fef03 555 }
kevman 0:38ceb79fef03 556 *handle = (void*)socket;
kevman 0:38ceb79fef03 557
kevman 0:38ceb79fef03 558 tr_debug("socket_open() socket=%p, sock_id=%d, ret=0", socket, socket->socket_id);
kevman 0:38ceb79fef03 559
kevman 0:38ceb79fef03 560 return NSAPI_ERROR_OK;
kevman 0:38ceb79fef03 561 }
kevman 0:38ceb79fef03 562
kevman 0:38ceb79fef03 563 nsapi_error_t Nanostack::socket_close(void *handle)
kevman 0:38ceb79fef03 564 {
kevman 0:38ceb79fef03 565 NanostackLockGuard lock;
kevman 0:38ceb79fef03 566 // Validate parameters
kevman 0:38ceb79fef03 567 NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
kevman 0:38ceb79fef03 568 if (NULL == handle) {
kevman 0:38ceb79fef03 569 MBED_ASSERT(false);
kevman 0:38ceb79fef03 570 return NSAPI_ERROR_NO_SOCKET;
kevman 0:38ceb79fef03 571 }
kevman 0:38ceb79fef03 572 tr_debug("socket_close(socket=%p) sock_id=%d", socket, socket->socket_id);
kevman 0:38ceb79fef03 573
kevman 0:38ceb79fef03 574 delete socket;
kevman 0:38ceb79fef03 575
kevman 0:38ceb79fef03 576 return 0;
kevman 0:38ceb79fef03 577
kevman 0:38ceb79fef03 578 }
kevman 0:38ceb79fef03 579
kevman 0:38ceb79fef03 580 nsapi_size_or_error_t Nanostack::do_sendto(void *handle, const ns_address_t *address, const void *data, nsapi_size_t size)
kevman 0:38ceb79fef03 581 {
kevman 0:38ceb79fef03 582 // Validate parameters
kevman 0:38ceb79fef03 583 NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
kevman 0:38ceb79fef03 584 if (handle == NULL) {
kevman 0:38ceb79fef03 585 MBED_ASSERT(false);
kevman 0:38ceb79fef03 586 return NSAPI_ERROR_NO_SOCKET;
kevman 0:38ceb79fef03 587 }
kevman 0:38ceb79fef03 588
kevman 0:38ceb79fef03 589 nsapi_size_or_error_t ret;
kevman 0:38ceb79fef03 590
kevman 0:38ceb79fef03 591 NanostackLockGuard lock;
kevman 0:38ceb79fef03 592
kevman 0:38ceb79fef03 593 if (socket->closed() || (!address && !socket->is_connected())) {
kevman 0:38ceb79fef03 594 ret = NSAPI_ERROR_NO_CONNECTION;
kevman 0:38ceb79fef03 595 goto out;
kevman 0:38ceb79fef03 596 }
kevman 0:38ceb79fef03 597
kevman 0:38ceb79fef03 598 if (address && socket->proto == SOCKET_TCP) {
kevman 0:38ceb79fef03 599 tr_error("socket_sendto() not supported with TCP!");
kevman 0:38ceb79fef03 600 ret = NSAPI_ERROR_IS_CONNECTED;
kevman 0:38ceb79fef03 601 goto out;
kevman 0:38ceb79fef03 602 }
kevman 0:38ceb79fef03 603
kevman 0:38ceb79fef03 604 int retcode;
kevman 0:38ceb79fef03 605 #if 0
kevman 0:38ceb79fef03 606 retcode = ::socket_sendto(socket->socket_id, address,
kevman 0:38ceb79fef03 607 data, size);
kevman 0:38ceb79fef03 608 #else
kevman 0:38ceb79fef03 609 // Use sendmsg purely to get the new return style
kevman 0:38ceb79fef03 610 // of returning data written rather than 0 on success,
kevman 0:38ceb79fef03 611 // which means TCP can do partial writes. (Sadly,
kevman 0:38ceb79fef03 612 // it's the only call which takes flags so we can
kevman 0:38ceb79fef03 613 // leave the NS_MSG_LEGACY0 flag clear).
kevman 0:38ceb79fef03 614 ns_msghdr_t msg;
kevman 0:38ceb79fef03 615 ns_iovec_t iov;
kevman 0:38ceb79fef03 616 iov.iov_base = const_cast<void *>(data);
kevman 0:38ceb79fef03 617 iov.iov_len = size;
kevman 0:38ceb79fef03 618 msg.msg_name = const_cast<ns_address_t *>(address);
kevman 0:38ceb79fef03 619 msg.msg_namelen = address ? sizeof *address : 0;
kevman 0:38ceb79fef03 620 msg.msg_iov = &iov;
kevman 0:38ceb79fef03 621 msg.msg_iovlen = 1;
kevman 0:38ceb79fef03 622 msg.msg_control = NULL;
kevman 0:38ceb79fef03 623 msg.msg_controllen = 0;
kevman 0:38ceb79fef03 624 retcode = ::socket_sendmsg(socket->socket_id, &msg, 0);
kevman 0:38ceb79fef03 625 #endif
kevman 0:38ceb79fef03 626
kevman 0:38ceb79fef03 627 /*
kevman 0:38ceb79fef03 628 * \return length if entire amount written (which could be 0)
kevman 0:38ceb79fef03 629 * \return value >0 and <length if partial amount written (stream only)
kevman 0:38ceb79fef03 630 * \return NS_EWOULDBLOCK if nothing written due to lack of queue space.
kevman 0:38ceb79fef03 631 * \return -1 Invalid socket ID or message structure.
kevman 0:38ceb79fef03 632 * \return -2 Socket memory allocation fail.
kevman 0:38ceb79fef03 633 * \return -3 TCP state not established or address scope not defined .
kevman 0:38ceb79fef03 634 * \return -4 Socket TX process busy or unknown interface.
kevman 0:38ceb79fef03 635 * \return -5 Socket not connected
kevman 0:38ceb79fef03 636 * \return -6 Packet too short (ICMP raw socket error).
kevman 0:38ceb79fef03 637 * */
kevman 0:38ceb79fef03 638 if (retcode == NS_EWOULDBLOCK) {
kevman 0:38ceb79fef03 639 ret = NSAPI_ERROR_WOULD_BLOCK;
kevman 0:38ceb79fef03 640 } else if (retcode < 0) {
kevman 0:38ceb79fef03 641 tr_error("socket_sendmsg: error=%d", retcode);
kevman 0:38ceb79fef03 642 ret = NSAPI_ERROR_DEVICE_ERROR;
kevman 0:38ceb79fef03 643 } else {
kevman 0:38ceb79fef03 644 ret = retcode;
kevman 0:38ceb79fef03 645 }
kevman 0:38ceb79fef03 646
kevman 0:38ceb79fef03 647 out:
kevman 0:38ceb79fef03 648 tr_debug("socket_sendto(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);
kevman 0:38ceb79fef03 649
kevman 0:38ceb79fef03 650 return ret;
kevman 0:38ceb79fef03 651 }
kevman 0:38ceb79fef03 652
kevman 0:38ceb79fef03 653 nsapi_size_or_error_t Nanostack::socket_sendto(void *handle, const SocketAddress &address, const void *data, nsapi_size_t size)
kevman 0:38ceb79fef03 654 {
kevman 0:38ceb79fef03 655 if (address.get_ip_version() != NSAPI_IPv6) {
kevman 0:38ceb79fef03 656 return NSAPI_ERROR_UNSUPPORTED;
kevman 0:38ceb79fef03 657 }
kevman 0:38ceb79fef03 658
kevman 0:38ceb79fef03 659 ns_address_t ns_address;
kevman 0:38ceb79fef03 660 convert_mbed_addr_to_ns(&ns_address, &address);
kevman 0:38ceb79fef03 661 /*No lock gaurd needed here as do_sendto() will handle locks.*/
kevman 0:38ceb79fef03 662 return do_sendto(handle, &ns_address, data, size);
kevman 0:38ceb79fef03 663 }
kevman 0:38ceb79fef03 664
kevman 0:38ceb79fef03 665 nsapi_size_or_error_t Nanostack::socket_recvfrom(void *handle, SocketAddress *address, void *buffer, nsapi_size_t size)
kevman 0:38ceb79fef03 666 {
kevman 0:38ceb79fef03 667 // Validate parameters
kevman 0:38ceb79fef03 668 NanostackSocket *socket = static_cast<NanostackSocket *>(handle);
kevman 0:38ceb79fef03 669 if (handle == NULL) {
kevman 0:38ceb79fef03 670 MBED_ASSERT(false);
kevman 0:38ceb79fef03 671 return NSAPI_ERROR_NO_SOCKET;
kevman 0:38ceb79fef03 672 }
kevman 0:38ceb79fef03 673
kevman 0:38ceb79fef03 674 nsapi_size_or_error_t ret;
kevman 0:38ceb79fef03 675
kevman 0:38ceb79fef03 676 NanostackLockGuard lock;
kevman 0:38ceb79fef03 677
kevman 0:38ceb79fef03 678 if (socket->closed()) {
kevman 0:38ceb79fef03 679 ret = NSAPI_ERROR_NO_CONNECTION;
kevman 0:38ceb79fef03 680 goto out;
kevman 0:38ceb79fef03 681 }
kevman 0:38ceb79fef03 682
kevman 0:38ceb79fef03 683 ns_address_t ns_address;
kevman 0:38ceb79fef03 684
kevman 0:38ceb79fef03 685 int retcode;
kevman 0:38ceb79fef03 686 retcode = ::socket_recvfrom(socket->socket_id, buffer, size, 0, &ns_address);
kevman 0:38ceb79fef03 687
kevman 0:38ceb79fef03 688 if (retcode == NS_EWOULDBLOCK) {
kevman 0:38ceb79fef03 689 ret = NSAPI_ERROR_WOULD_BLOCK;
kevman 0:38ceb79fef03 690 } else if (retcode < 0) {
kevman 0:38ceb79fef03 691 ret = NSAPI_ERROR_PARAMETER;
kevman 0:38ceb79fef03 692 } else {
kevman 0:38ceb79fef03 693 ret = retcode;
kevman 0:38ceb79fef03 694 if (address != NULL) {
kevman 0:38ceb79fef03 695 convert_ns_addr_to_mbed(address, &ns_address);
kevman 0:38ceb79fef03 696 }
kevman 0:38ceb79fef03 697 }
kevman 0:38ceb79fef03 698
kevman 0:38ceb79fef03 699 out:
kevman 0:38ceb79fef03 700 if (address) {
kevman 0:38ceb79fef03 701 tr_debug("socket_recvfrom(socket=%p) sock_id=%d, ret=%i, addr=[%s]:%i", socket, socket->socket_id, ret,
kevman 0:38ceb79fef03 702 trace_ipv6(address->get_ip_bytes()), address->get_port());
kevman 0:38ceb79fef03 703 } else {
kevman 0:38ceb79fef03 704 tr_debug("socket_recv(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);
kevman 0:38ceb79fef03 705 }
kevman 0:38ceb79fef03 706
kevman 0:38ceb79fef03 707 return ret;
kevman 0:38ceb79fef03 708 }
kevman 0:38ceb79fef03 709
kevman 0:38ceb79fef03 710 nsapi_error_t Nanostack::socket_bind(void *handle, const SocketAddress &address)
kevman 0:38ceb79fef03 711 {
kevman 0:38ceb79fef03 712 // Validate parameters
kevman 0:38ceb79fef03 713 NanostackSocket *socket = static_cast<NanostackSocket *>(handle);
kevman 0:38ceb79fef03 714 if (handle == NULL) {
kevman 0:38ceb79fef03 715 MBED_ASSERT(false);
kevman 0:38ceb79fef03 716 return NSAPI_ERROR_NO_SOCKET;
kevman 0:38ceb79fef03 717 }
kevman 0:38ceb79fef03 718
kevman 0:38ceb79fef03 719 const void *addr_field;
kevman 0:38ceb79fef03 720 switch (address.get_ip_version()) {
kevman 0:38ceb79fef03 721 case NSAPI_IPv6:
kevman 0:38ceb79fef03 722 addr_field = address.get_ip_bytes();
kevman 0:38ceb79fef03 723 break;
kevman 0:38ceb79fef03 724 case NSAPI_UNSPEC:
kevman 0:38ceb79fef03 725 addr_field = &ns_in6addr_any;
kevman 0:38ceb79fef03 726 break;
kevman 0:38ceb79fef03 727 default:
kevman 0:38ceb79fef03 728 return NSAPI_ERROR_UNSUPPORTED;
kevman 0:38ceb79fef03 729 }
kevman 0:38ceb79fef03 730
kevman 0:38ceb79fef03 731 NanostackLockGuard lock;
kevman 0:38ceb79fef03 732
kevman 0:38ceb79fef03 733 ns_address_t ns_address;
kevman 0:38ceb79fef03 734 ns_address.type = ADDRESS_IPV6;
kevman 0:38ceb79fef03 735 memcpy(ns_address.address, addr_field, sizeof ns_address.address);
kevman 0:38ceb79fef03 736 ns_address.identifier = address.get_port();
kevman 0:38ceb79fef03 737 nsapi_error_t ret;
kevman 0:38ceb79fef03 738 int retcode = ::socket_bind(socket->socket_id, &ns_address);
kevman 0:38ceb79fef03 739
kevman 0:38ceb79fef03 740 if (retcode == 0) {
kevman 0:38ceb79fef03 741 ret = NSAPI_ERROR_OK;
kevman 0:38ceb79fef03 742 } else {
kevman 0:38ceb79fef03 743 ret = NSAPI_ERROR_PARAMETER;
kevman 0:38ceb79fef03 744 }
kevman 0:38ceb79fef03 745
kevman 0:38ceb79fef03 746 tr_debug("socket_bind(socket=%p) sock_id=%d, retcode=%i, ret=%i", socket, socket->socket_id, retcode, ret);
kevman 0:38ceb79fef03 747
kevman 0:38ceb79fef03 748 return ret;
kevman 0:38ceb79fef03 749 }
kevman 0:38ceb79fef03 750
kevman 0:38ceb79fef03 751 nsapi_error_t Nanostack::setsockopt(void *handle, int level, int optname, const void *optval, unsigned optlen)
kevman 0:38ceb79fef03 752 {
kevman 0:38ceb79fef03 753 NanostackSocket *socket = static_cast<NanostackSocket *>(handle);
kevman 0:38ceb79fef03 754 if (handle == NULL) {
kevman 0:38ceb79fef03 755 MBED_ASSERT(false);
kevman 0:38ceb79fef03 756 return NSAPI_ERROR_NO_SOCKET;
kevman 0:38ceb79fef03 757 }
kevman 0:38ceb79fef03 758
kevman 0:38ceb79fef03 759 NanostackLockGuard lock;
kevman 0:38ceb79fef03 760
kevman 0:38ceb79fef03 761 ns_ipv6_mreq_t ns_mreq;
kevman 0:38ceb79fef03 762
kevman 0:38ceb79fef03 763 if (level == NSAPI_SOCKET) {
kevman 0:38ceb79fef03 764 switch (optname) {
kevman 0:38ceb79fef03 765 case NSAPI_ADD_MEMBERSHIP:
kevman 0:38ceb79fef03 766 case NSAPI_DROP_MEMBERSHIP: {
kevman 0:38ceb79fef03 767 if (optlen != sizeof(nsapi_ip_mreq_t)) {
kevman 0:38ceb79fef03 768 return NSAPI_ERROR_PARAMETER;
kevman 0:38ceb79fef03 769 }
kevman 0:38ceb79fef03 770 const nsapi_ip_mreq_t *imr = static_cast<const nsapi_ip_mreq_t *>(optval);
kevman 0:38ceb79fef03 771
kevman 0:38ceb79fef03 772 /* Check address types are IPv6, or unspecified for interface */
kevman 0:38ceb79fef03 773 if (imr->imr_multiaddr.version != NSAPI_IPv6 ||
kevman 0:38ceb79fef03 774 (imr->imr_interface.version != NSAPI_UNSPEC && imr->imr_interface.version != NSAPI_IPv6)) {
kevman 0:38ceb79fef03 775 return NSAPI_ERROR_PARAMETER;
kevman 0:38ceb79fef03 776 }
kevman 0:38ceb79fef03 777
kevman 0:38ceb79fef03 778 /* Convert all parameters to Nanostack native, and proceed with setsockopt */
kevman 0:38ceb79fef03 779 memcpy(ns_mreq.ipv6mr_multiaddr, imr->imr_multiaddr.bytes, 16);
kevman 0:38ceb79fef03 780 if (imr->imr_interface.version == NSAPI_UNSPEC || memcmp(imr->imr_interface.bytes, ns_in6addr_any, 16) == 0) {
kevman 0:38ceb79fef03 781 ns_mreq.ipv6mr_interface = 0;
kevman 0:38ceb79fef03 782 } else {
kevman 0:38ceb79fef03 783 // If this fails, Nanostack will itself fault the invalid -1 interface ID
kevman 0:38ceb79fef03 784 ns_mreq.ipv6mr_interface = find_interface_by_address(imr->imr_interface.bytes);
kevman 0:38ceb79fef03 785 }
kevman 0:38ceb79fef03 786
kevman 0:38ceb79fef03 787 level = SOCKET_IPPROTO_IPV6;
kevman 0:38ceb79fef03 788 optname = optname == NSAPI_ADD_MEMBERSHIP ? SOCKET_IPV6_JOIN_GROUP : SOCKET_IPV6_LEAVE_GROUP;
kevman 0:38ceb79fef03 789 optval = &ns_mreq;
kevman 0:38ceb79fef03 790 optlen = sizeof ns_mreq;
kevman 0:38ceb79fef03 791 break;
kevman 0:38ceb79fef03 792 }
kevman 0:38ceb79fef03 793 default:
kevman 0:38ceb79fef03 794 return NSAPI_ERROR_UNSUPPORTED;
kevman 0:38ceb79fef03 795 }
kevman 0:38ceb79fef03 796 }
kevman 0:38ceb79fef03 797
kevman 0:38ceb79fef03 798 int retcode = ::socket_setsockopt(socket->socket_id, level, optname, optval, optlen);
kevman 0:38ceb79fef03 799 if (retcode == 0) {
kevman 0:38ceb79fef03 800 return NSAPI_ERROR_OK;
kevman 0:38ceb79fef03 801 } else if (retcode == -2) {
kevman 0:38ceb79fef03 802 return NSAPI_ERROR_UNSUPPORTED;
kevman 0:38ceb79fef03 803 } else {
kevman 0:38ceb79fef03 804 return NSAPI_ERROR_PARAMETER;
kevman 0:38ceb79fef03 805 }
kevman 0:38ceb79fef03 806 }
kevman 0:38ceb79fef03 807
kevman 0:38ceb79fef03 808 nsapi_error_t Nanostack::getsockopt(void *handle, int level, int optname, void *optval, unsigned *optlen)
kevman 0:38ceb79fef03 809 {
kevman 0:38ceb79fef03 810 NanostackSocket *socket = static_cast<NanostackSocket *>(handle);
kevman 0:38ceb79fef03 811 if (handle == NULL) {
kevman 0:38ceb79fef03 812 MBED_ASSERT(false);
kevman 0:38ceb79fef03 813 return NSAPI_ERROR_NO_SOCKET;
kevman 0:38ceb79fef03 814 }
kevman 0:38ceb79fef03 815
kevman 0:38ceb79fef03 816 NanostackLockGuard lock;
kevman 0:38ceb79fef03 817
kevman 0:38ceb79fef03 818 uint16_t optlen16 = *optlen;
kevman 0:38ceb79fef03 819
kevman 0:38ceb79fef03 820 int retcode = ::socket_getsockopt(socket->socket_id, level, optname, optval, &optlen16);
kevman 0:38ceb79fef03 821 if (retcode == 0) {
kevman 0:38ceb79fef03 822 *optlen = optlen16;
kevman 0:38ceb79fef03 823 return NSAPI_ERROR_OK;
kevman 0:38ceb79fef03 824 } else if (retcode == -2) {
kevman 0:38ceb79fef03 825 return NSAPI_ERROR_UNSUPPORTED;
kevman 0:38ceb79fef03 826 } else {
kevman 0:38ceb79fef03 827 return NSAPI_ERROR_PARAMETER;
kevman 0:38ceb79fef03 828 }
kevman 0:38ceb79fef03 829 }
kevman 0:38ceb79fef03 830
kevman 0:38ceb79fef03 831 nsapi_error_t Nanostack::socket_listen(void *handle, int backlog)
kevman 0:38ceb79fef03 832 {
kevman 0:38ceb79fef03 833 //Check if socket exists
kevman 0:38ceb79fef03 834 NanostackSocket *socket = static_cast<NanostackSocket *>(handle);
kevman 0:38ceb79fef03 835 if (handle == NULL) {
kevman 0:38ceb79fef03 836 MBED_ASSERT(false);
kevman 0:38ceb79fef03 837 return NSAPI_ERROR_NO_SOCKET;
kevman 0:38ceb79fef03 838 }
kevman 0:38ceb79fef03 839
kevman 0:38ceb79fef03 840 nsapi_error_t ret = NSAPI_ERROR_OK;
kevman 0:38ceb79fef03 841
kevman 0:38ceb79fef03 842 NanostackLockGuard lock;
kevman 0:38ceb79fef03 843
kevman 0:38ceb79fef03 844 if(::socket_listen(socket->socket_id, backlog) < 0) {
kevman 0:38ceb79fef03 845 ret = NSAPI_ERROR_PARAMETER;
kevman 0:38ceb79fef03 846 } else {
kevman 0:38ceb79fef03 847 socket->set_listening();
kevman 0:38ceb79fef03 848 }
kevman 0:38ceb79fef03 849
kevman 0:38ceb79fef03 850 return ret;
kevman 0:38ceb79fef03 851 }
kevman 0:38ceb79fef03 852
kevman 0:38ceb79fef03 853 nsapi_error_t Nanostack::socket_connect(void *handle, const SocketAddress &addr)
kevman 0:38ceb79fef03 854 {
kevman 0:38ceb79fef03 855 // Validate parameters
kevman 0:38ceb79fef03 856 NanostackSocket *socket = static_cast<NanostackSocket *>(handle);
kevman 0:38ceb79fef03 857 nsapi_error_t ret;
kevman 0:38ceb79fef03 858 if (handle == NULL) {
kevman 0:38ceb79fef03 859 MBED_ASSERT(false);
kevman 0:38ceb79fef03 860 return NSAPI_ERROR_NO_SOCKET;
kevman 0:38ceb79fef03 861 }
kevman 0:38ceb79fef03 862
kevman 0:38ceb79fef03 863 NanostackLockGuard lock;
kevman 0:38ceb79fef03 864
kevman 0:38ceb79fef03 865 if (addr.get_ip_version() != NSAPI_IPv6) {
kevman 0:38ceb79fef03 866 ret = NSAPI_ERROR_UNSUPPORTED;
kevman 0:38ceb79fef03 867 goto out;
kevman 0:38ceb79fef03 868 }
kevman 0:38ceb79fef03 869
kevman 0:38ceb79fef03 870 if (socket->closed()) {
kevman 0:38ceb79fef03 871 ret = NSAPI_ERROR_NO_CONNECTION;
kevman 0:38ceb79fef03 872 goto out;
kevman 0:38ceb79fef03 873 }
kevman 0:38ceb79fef03 874
kevman 0:38ceb79fef03 875 if (socket->is_connecting()) {
kevman 0:38ceb79fef03 876 ret = NSAPI_ERROR_ALREADY;
kevman 0:38ceb79fef03 877 goto out;
kevman 0:38ceb79fef03 878 }
kevman 0:38ceb79fef03 879
kevman 0:38ceb79fef03 880 if (socket->is_connected()) {
kevman 0:38ceb79fef03 881 ret = NSAPI_ERROR_IS_CONNECTED;
kevman 0:38ceb79fef03 882 goto out;
kevman 0:38ceb79fef03 883 }
kevman 0:38ceb79fef03 884
kevman 0:38ceb79fef03 885 ns_address_t ns_addr;
kevman 0:38ceb79fef03 886
kevman 0:38ceb79fef03 887 convert_mbed_addr_to_ns(&ns_addr, &addr);
kevman 0:38ceb79fef03 888 if (::socket_connect(socket->socket_id, &ns_addr, 0) == 0) {
kevman 0:38ceb79fef03 889 if (socket->proto == SOCKET_TCP) {
kevman 0:38ceb79fef03 890 socket->set_connecting(&ns_addr);
kevman 0:38ceb79fef03 891 ret = NSAPI_ERROR_IN_PROGRESS;
kevman 0:38ceb79fef03 892 } else {
kevman 0:38ceb79fef03 893 ret = NSAPI_ERROR_OK;
kevman 0:38ceb79fef03 894 }
kevman 0:38ceb79fef03 895 } else {
kevman 0:38ceb79fef03 896 ret = NSAPI_ERROR_DEVICE_ERROR;
kevman 0:38ceb79fef03 897 }
kevman 0:38ceb79fef03 898
kevman 0:38ceb79fef03 899 out:
kevman 0:38ceb79fef03 900 tr_debug("socket_connect(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);
kevman 0:38ceb79fef03 901
kevman 0:38ceb79fef03 902 return ret;
kevman 0:38ceb79fef03 903 }
kevman 0:38ceb79fef03 904
kevman 0:38ceb79fef03 905 nsapi_error_t Nanostack::socket_accept(void *server, void **handle, SocketAddress *address)
kevman 0:38ceb79fef03 906 {
kevman 0:38ceb79fef03 907 NanostackSocket * socket = static_cast<NanostackSocket *>(server);
kevman 0:38ceb79fef03 908 NanostackSocket *accepted_sock = NULL;
kevman 0:38ceb79fef03 909 nsapi_error_t ret;
kevman 0:38ceb79fef03 910
kevman 0:38ceb79fef03 911 if (handle == NULL) {
kevman 0:38ceb79fef03 912 MBED_ASSERT(false);
kevman 0:38ceb79fef03 913 return NSAPI_ERROR_NO_SOCKET;
kevman 0:38ceb79fef03 914 }
kevman 0:38ceb79fef03 915
kevman 0:38ceb79fef03 916 NanostackLockGuard lock;
kevman 0:38ceb79fef03 917
kevman 0:38ceb79fef03 918 if (!socket->is_listening()) {
kevman 0:38ceb79fef03 919 ret = NSAPI_ERROR_PARAMETER;
kevman 0:38ceb79fef03 920 goto out;
kevman 0:38ceb79fef03 921 }
kevman 0:38ceb79fef03 922
kevman 0:38ceb79fef03 923 accepted_sock = new NanostackSocket(socket->proto);
kevman 0:38ceb79fef03 924 if (accepted_sock == NULL) {
kevman 0:38ceb79fef03 925 ret = NSAPI_ERROR_NO_MEMORY;
kevman 0:38ceb79fef03 926 goto out;
kevman 0:38ceb79fef03 927 }
kevman 0:38ceb79fef03 928
kevman 0:38ceb79fef03 929 ns_address_t ns_addr;
kevman 0:38ceb79fef03 930 int retcode;
kevman 0:38ceb79fef03 931 retcode = socket->accept(accepted_sock, &ns_addr);
kevman 0:38ceb79fef03 932 if (retcode < 0) {
kevman 0:38ceb79fef03 933 delete accepted_sock;
kevman 0:38ceb79fef03 934 if (retcode == NS_EWOULDBLOCK) {
kevman 0:38ceb79fef03 935 ret = NSAPI_ERROR_WOULD_BLOCK;
kevman 0:38ceb79fef03 936 } else {
kevman 0:38ceb79fef03 937 ret = NSAPI_ERROR_DEVICE_ERROR;
kevman 0:38ceb79fef03 938 }
kevman 0:38ceb79fef03 939 goto out;
kevman 0:38ceb79fef03 940 }
kevman 0:38ceb79fef03 941 ret = NSAPI_ERROR_OK;
kevman 0:38ceb79fef03 942
kevman 0:38ceb79fef03 943 if (address) {
kevman 0:38ceb79fef03 944 convert_ns_addr_to_mbed(address, &ns_addr);
kevman 0:38ceb79fef03 945 }
kevman 0:38ceb79fef03 946
kevman 0:38ceb79fef03 947 *handle = accepted_sock;
kevman 0:38ceb79fef03 948
kevman 0:38ceb79fef03 949 out:
kevman 0:38ceb79fef03 950 tr_debug("socket_accept() socket=%p, sock_id=%d, ret=%i", accepted_sock, accepted_sock ? accepted_sock->socket_id : -1, ret);
kevman 0:38ceb79fef03 951
kevman 0:38ceb79fef03 952 return ret;
kevman 0:38ceb79fef03 953 }
kevman 0:38ceb79fef03 954
kevman 0:38ceb79fef03 955 nsapi_size_or_error_t Nanostack::socket_send(void *handle, const void *data, nsapi_size_t size)
kevman 0:38ceb79fef03 956 {
kevman 0:38ceb79fef03 957 return do_sendto(handle, NULL, data, size);
kevman 0:38ceb79fef03 958 }
kevman 0:38ceb79fef03 959
kevman 0:38ceb79fef03 960 nsapi_size_or_error_t Nanostack::socket_recv(void *handle, void *data, nsapi_size_t size)
kevman 0:38ceb79fef03 961 {
kevman 0:38ceb79fef03 962 return socket_recvfrom(handle, NULL, data, size);
kevman 0:38ceb79fef03 963 }
kevman 0:38ceb79fef03 964
kevman 0:38ceb79fef03 965 void Nanostack::socket_attach(void *handle, void (*callback)(void *), void *id)
kevman 0:38ceb79fef03 966 {
kevman 0:38ceb79fef03 967 // Validate parameters
kevman 0:38ceb79fef03 968 NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
kevman 0:38ceb79fef03 969 if (handle == NULL) {
kevman 0:38ceb79fef03 970 MBED_ASSERT(false);
kevman 0:38ceb79fef03 971 return;
kevman 0:38ceb79fef03 972 }
kevman 0:38ceb79fef03 973
kevman 0:38ceb79fef03 974 NanostackLockGuard lock;
kevman 0:38ceb79fef03 975
kevman 0:38ceb79fef03 976 socket->callback = callback;
kevman 0:38ceb79fef03 977 socket->callback_data = id;
kevman 0:38ceb79fef03 978
kevman 0:38ceb79fef03 979 tr_debug("socket_attach(socket=%p) sock_id=%d", socket, socket->socket_id);
kevman 0:38ceb79fef03 980 }
kevman 0:38ceb79fef03 981
kevman 0:38ceb79fef03 982 Nanostack &Nanostack::get_instance() {
kevman 0:38ceb79fef03 983 static Nanostack nanostack;
kevman 0:38ceb79fef03 984 return nanostack;
kevman 0:38ceb79fef03 985 }
kevman 0:38ceb79fef03 986
kevman 0:38ceb79fef03 987 // This works as long as it's not ever set to something which corresponds to
kevman 0:38ceb79fef03 988 // a macro defined as a non-integer. Eg `#define Nanostack "Foo"`
kevman 0:38ceb79fef03 989 #define NANOSTACK 0x99119911
kevman 0:38ceb79fef03 990 #if MBED_CONF_NSAPI_DEFAULT_STACK == NANOSTACK
kevman 0:38ceb79fef03 991 #undef NANOSTACK
kevman 0:38ceb79fef03 992 OnboardNetworkStack &OnboardNetworkStack::get_default_instance() {
kevman 0:38ceb79fef03 993 return Nanostack::get_instance();
kevman 0:38ceb79fef03 994 }
kevman 0:38ceb79fef03 995 #endif