mbed-os

Dependents:   cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more

Committer:
be_bryan
Date:
Mon Dec 11 17:54:04 2017 +0000
Revision:
0:b74591d5ab33
motor ++

Who changed what in which revision?

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