BBR 1 Ebene

Committer:
borlanic
Date:
Mon May 14 11:29:06 2018 +0000
Revision:
0:fbdae7e6d805
BBR

Who changed what in which revision?

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