mbed-os

Fork of mbed-os by erkin yucel

Committer:
xuaner
Date:
Thu Jul 20 14:26:57 2017 +0000
Revision:
1:3deb71413561
Parent:
0:f269e3021894
mbed_os

Who changed what in which revision?

UserRevisionLine numberNew contents of line
elessair 0:f269e3021894 1 /* Nanostack implementation of NetworkSocketAPI
elessair 0:f269e3021894 2 * Copyright (c) 2016 ARM Limited
elessair 0:f269e3021894 3 *
elessair 0:f269e3021894 4 * Licensed under the Apache License, Version 2.0 (the "License");
elessair 0:f269e3021894 5 * you may not use this file except in compliance with the License.
elessair 0:f269e3021894 6 * You may obtain a copy of the License at
elessair 0:f269e3021894 7 *
elessair 0:f269e3021894 8 * http://www.apache.org/licenses/LICENSE-2.0
elessair 0:f269e3021894 9 *
elessair 0:f269e3021894 10 * Unless required by applicable law or agreed to in writing, software
elessair 0:f269e3021894 11 * distributed under the License is distributed on an "AS IS" BASIS,
elessair 0:f269e3021894 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
elessair 0:f269e3021894 13 * See the License for the specific language governing permissions and
elessair 0:f269e3021894 14 * limitations under the License.
elessair 0:f269e3021894 15 */
elessair 0:f269e3021894 16
elessair 0:f269e3021894 17 #include "mbed.h"
elessair 0:f269e3021894 18 #include "rtos.h"
elessair 0:f269e3021894 19 #include "NanostackInterface.h"
elessair 0:f269e3021894 20
elessair 0:f269e3021894 21 #include "ns_address.h"
elessair 0:f269e3021894 22 #include "nsdynmemLIB.h"
elessair 0:f269e3021894 23 #include "eventOS_scheduler.h"
elessair 0:f269e3021894 24 #include "randLIB.h"
elessair 0:f269e3021894 25
elessair 0:f269e3021894 26 #include "mbed-mesh-api/MeshInterfaceFactory.h"
elessair 0:f269e3021894 27
elessair 0:f269e3021894 28 #include "mesh_system.h" // from inside mbed-mesh-api
elessair 0:f269e3021894 29 #include "socket_api.h"
elessair 0:f269e3021894 30 #include "net_interface.h"
elessair 0:f269e3021894 31 #include "ip6string.h"
elessair 0:f269e3021894 32 // Uncomment to enable trace
elessair 0:f269e3021894 33 //#define HAVE_DEBUG
elessair 0:f269e3021894 34 #include "ns_trace.h"
elessair 0:f269e3021894 35 #define TRACE_GROUP "nsif"
elessair 0:f269e3021894 36
elessair 0:f269e3021894 37 #define NS_INTERFACE_SOCKETS_MAX 16 //same as NanoStack SOCKET_MAX
elessair 0:f269e3021894 38 #define NANOSTACK_SOCKET_UDP 17 // same as nanostack SOCKET_UDP
elessair 0:f269e3021894 39 #define NANOSTACK_SOCKET_TCP 6 // same as nanostack SOCKET_TCP
elessair 0:f269e3021894 40
elessair 0:f269e3021894 41 #define MALLOC ns_dyn_mem_alloc
elessair 0:f269e3021894 42 #define FREE ns_dyn_mem_free
elessair 0:f269e3021894 43
elessair 0:f269e3021894 44 #define nanostack_lock() eventOS_scheduler_mutex_wait()
elessair 0:f269e3021894 45 #define nanostack_unlock() eventOS_scheduler_mutex_release()
elessair 0:f269e3021894 46 #define nanostack_assert_locked() //MBED_ASSERT(eventOS_scheduler_mutex_is_owner())
elessair 0:f269e3021894 47
elessair 0:f269e3021894 48 enum socket_mode_t {
elessair 0:f269e3021894 49 SOCKET_MODE_UNOPENED, // No socket ID
elessair 0:f269e3021894 50 SOCKET_MODE_OPENED, // Socket ID but no assigned use yet
elessair 0:f269e3021894 51 SOCKET_MODE_CONNECTING, // Socket is connecting but not open yet
elessair 0:f269e3021894 52 SOCKET_MODE_DATAGRAM, // Socket is bound to a port and listening for datagrams
elessair 0:f269e3021894 53 SOCKET_MODE_STREAM, // Socket has an open stream
elessair 0:f269e3021894 54 SOCKET_MODE_CLOSED, // Socket is closed and resources are freed
elessair 0:f269e3021894 55 };
elessair 0:f269e3021894 56
elessair 0:f269e3021894 57 class NanostackBuffer {
elessair 0:f269e3021894 58 public:
elessair 0:f269e3021894 59 NanostackBuffer *next; /*<! next buffer */
elessair 0:f269e3021894 60 ns_address_t ns_address; /*<! address where data is received */
elessair 0:f269e3021894 61 uint16_t length; /*<! data length in this buffer */
elessair 0:f269e3021894 62 uint8_t payload[1]; /*<! Trailing buffer data */
elessair 0:f269e3021894 63 };
elessair 0:f269e3021894 64
elessair 0:f269e3021894 65 class NanostackSocket {
elessair 0:f269e3021894 66 public:
elessair 0:f269e3021894 67 static void socket_callback(void *cb);
elessair 0:f269e3021894 68 static void* operator new(std::size_t sz);
elessair 0:f269e3021894 69 static void operator delete(void* ptr);
elessair 0:f269e3021894 70
elessair 0:f269e3021894 71 NanostackSocket(int8_t protocol);
elessair 0:f269e3021894 72 ~NanostackSocket(void);
elessair 0:f269e3021894 73 bool open(void);
elessair 0:f269e3021894 74 void close(void);
elessair 0:f269e3021894 75 bool closed(void) {return SOCKET_MODE_CLOSED == mode;}
elessair 0:f269e3021894 76 bool is_bound(void);
elessair 0:f269e3021894 77 void set_bound(void);
elessair 0:f269e3021894 78 bool is_connecting(void);
elessair 0:f269e3021894 79 void set_connecting(ns_address_t *addr);
elessair 0:f269e3021894 80 void set_connected(void);
elessair 0:f269e3021894 81
elessair 0:f269e3021894 82 // Socket events from nanostack
elessair 0:f269e3021894 83 void event_data(socket_callback_t *sock_cb);
elessair 0:f269e3021894 84 void event_bind_done(socket_callback_t *sock_cb);
elessair 0:f269e3021894 85 void event_connnect_closed(socket_callback_t *sock_cb);
elessair 0:f269e3021894 86 void event_tx_done(socket_callback_t *sock_cb);
elessair 0:f269e3021894 87
elessair 0:f269e3021894 88 // Run callback to signal the next layer of the NSAPI
elessair 0:f269e3021894 89 void signal_event(void);
elessair 0:f269e3021894 90
elessair 0:f269e3021894 91 // Add or remove a socket to the listening socket
elessair 0:f269e3021894 92 void accept_list_add(NanostackSocket *socket);
elessair 0:f269e3021894 93 NanostackSocket * accept_list_remove(void);
elessair 0:f269e3021894 94
elessair 0:f269e3021894 95 bool data_available(void);
elessair 0:f269e3021894 96 size_t data_copy_and_free(void *dest, size_t len, SocketAddress *address, bool stream);
elessair 0:f269e3021894 97 void data_free_all(void);
elessair 0:f269e3021894 98 void data_attach(NanostackBuffer *data_buf);
elessair 0:f269e3021894 99
elessair 0:f269e3021894 100 void (*callback)(void *);
elessair 0:f269e3021894 101 void *callback_data;
elessair 0:f269e3021894 102 int8_t socket_id; /*!< allocated socket ID */
elessair 0:f269e3021894 103 int8_t proto; /*!< UDP or TCP */
elessair 0:f269e3021894 104 bool addr_valid;
elessair 0:f269e3021894 105 ns_address_t ns_address;
elessair 0:f269e3021894 106 private:
elessair 0:f269e3021894 107 NanostackBuffer *rxBufChain; /*!< Receive buffers */
elessair 0:f269e3021894 108 socket_mode_t mode;
elessair 0:f269e3021894 109 };
elessair 0:f269e3021894 110
elessair 0:f269e3021894 111 static NanostackSocket * socket_tbl[NS_INTERFACE_SOCKETS_MAX];
elessair 0:f269e3021894 112
elessair 0:f269e3021894 113 static int map_mesh_error(mesh_error_t err)
elessair 0:f269e3021894 114 {
elessair 0:f269e3021894 115 switch (err) {
elessair 0:f269e3021894 116 case MESH_ERROR_NONE: return 0;
elessair 0:f269e3021894 117 case MESH_ERROR_MEMORY: return NSAPI_ERROR_NO_MEMORY;
elessair 0:f269e3021894 118 case MESH_ERROR_PARAM: return NSAPI_ERROR_UNSUPPORTED;
elessair 0:f269e3021894 119 case MESH_ERROR_STATE: return NSAPI_ERROR_DEVICE_ERROR;
elessair 0:f269e3021894 120 default: return NSAPI_ERROR_DEVICE_ERROR;
elessair 0:f269e3021894 121 }
elessair 0:f269e3021894 122 }
elessair 0:f269e3021894 123
elessair 0:f269e3021894 124 static void convert_mbed_addr_to_ns(ns_address_t *ns_addr,
elessair 0:f269e3021894 125 const SocketAddress *s_addr)
elessair 0:f269e3021894 126 {
elessair 0:f269e3021894 127 ns_addr->type = ADDRESS_IPV6;
elessair 0:f269e3021894 128 ns_addr->identifier = s_addr->get_port();
elessair 0:f269e3021894 129 const char *str = s_addr->get_ip_address();
elessair 0:f269e3021894 130 stoip6(str, strlen(str), ns_addr->address);
elessair 0:f269e3021894 131 }
elessair 0:f269e3021894 132
elessair 0:f269e3021894 133 static void convert_ns_addr_to_mbed(SocketAddress *s_addr, const ns_address_t *ns_addr)
elessair 0:f269e3021894 134 {
elessair 0:f269e3021894 135 char str[40];
elessair 0:f269e3021894 136 ip6tos(ns_addr->address, str);
elessair 0:f269e3021894 137 s_addr->set_port(ns_addr->identifier);
elessair 0:f269e3021894 138 s_addr->set_ip_address(str);
elessair 0:f269e3021894 139 }
elessair 0:f269e3021894 140
elessair 0:f269e3021894 141 void* NanostackSocket::operator new(std::size_t sz) {
elessair 0:f269e3021894 142 return MALLOC(sz);
elessair 0:f269e3021894 143 }
elessair 0:f269e3021894 144 void NanostackSocket::operator delete(void* ptr) {
elessair 0:f269e3021894 145 FREE(ptr);
elessair 0:f269e3021894 146 }
elessair 0:f269e3021894 147
elessair 0:f269e3021894 148 NanostackSocket::NanostackSocket(int8_t protocol)
elessair 0:f269e3021894 149 {
elessair 0:f269e3021894 150 nanostack_assert_locked();
elessair 0:f269e3021894 151
elessair 0:f269e3021894 152 callback = NULL;
elessair 0:f269e3021894 153 callback_data = NULL;
elessair 0:f269e3021894 154 socket_id = -1;
elessair 0:f269e3021894 155 rxBufChain = NULL;
elessair 0:f269e3021894 156 proto = protocol;
elessair 0:f269e3021894 157 addr_valid = false;
elessair 0:f269e3021894 158 memset(&ns_address, 0, sizeof(ns_address));
elessair 0:f269e3021894 159 mode = SOCKET_MODE_UNOPENED;
elessair 0:f269e3021894 160 }
elessair 0:f269e3021894 161
elessair 0:f269e3021894 162 NanostackSocket::~NanostackSocket()
elessair 0:f269e3021894 163 {
elessair 0:f269e3021894 164 nanostack_assert_locked();
elessair 0:f269e3021894 165
elessair 0:f269e3021894 166 if (mode != SOCKET_MODE_CLOSED) {
elessair 0:f269e3021894 167 close();
elessair 0:f269e3021894 168 }
elessair 0:f269e3021894 169 if (socket_id >= 0) {
elessair 0:f269e3021894 170 int ret = socket_free(socket_id);
elessair 0:f269e3021894 171 MBED_ASSERT(0 == ret);
elessair 0:f269e3021894 172 MBED_ASSERT(socket_tbl[socket_id] == this);
elessair 0:f269e3021894 173 socket_tbl[socket_id] = NULL;
elessair 0:f269e3021894 174 socket_id = -1;
elessair 0:f269e3021894 175 data_free_all();
elessair 0:f269e3021894 176 }
elessair 0:f269e3021894 177
elessair 0:f269e3021894 178 }
elessair 0:f269e3021894 179
elessair 0:f269e3021894 180 bool NanostackSocket::open(void)
elessair 0:f269e3021894 181 {
elessair 0:f269e3021894 182 nanostack_assert_locked();
elessair 0:f269e3021894 183 MBED_ASSERT(SOCKET_MODE_UNOPENED == mode);
elessair 0:f269e3021894 184
elessair 0:f269e3021894 185 int temp_socket = socket_open(proto, 0, socket_callback);
elessair 0:f269e3021894 186
elessair 0:f269e3021894 187 if (temp_socket < 0) {
elessair 0:f269e3021894 188 tr_error("NanostackSocket::open() failed");
elessair 0:f269e3021894 189 return false;
elessair 0:f269e3021894 190 }
elessair 0:f269e3021894 191 if (temp_socket >= NS_INTERFACE_SOCKETS_MAX) {
elessair 0:f269e3021894 192 MBED_ASSERT(false);
elessair 0:f269e3021894 193 return false;
elessair 0:f269e3021894 194 }
elessair 0:f269e3021894 195 if (socket_tbl[temp_socket] != NULL) {
elessair 0:f269e3021894 196 MBED_ASSERT(false);
elessair 0:f269e3021894 197 return false;
elessair 0:f269e3021894 198 }
elessair 0:f269e3021894 199 socket_id = temp_socket;
elessair 0:f269e3021894 200 socket_tbl[socket_id] = this;
elessair 0:f269e3021894 201 mode = SOCKET_MODE_OPENED;
elessair 0:f269e3021894 202 return true;
elessair 0:f269e3021894 203
elessair 0:f269e3021894 204 }
elessair 0:f269e3021894 205
elessair 0:f269e3021894 206 void NanostackSocket::close()
elessair 0:f269e3021894 207 {
elessair 0:f269e3021894 208 nanostack_assert_locked();
elessair 0:f269e3021894 209 MBED_ASSERT(mode != SOCKET_MODE_CLOSED);
elessair 0:f269e3021894 210
elessair 0:f269e3021894 211 if (socket_id >= 0) {
elessair 0:f269e3021894 212 int ret = socket_close(socket_id, (addr_valid ? &ns_address : NULL));
elessair 0:f269e3021894 213 MBED_ASSERT(0 == ret);
elessair 0:f269e3021894 214 } else {
elessair 0:f269e3021894 215 MBED_ASSERT(SOCKET_MODE_UNOPENED == mode);
elessair 0:f269e3021894 216 }
elessair 0:f269e3021894 217
elessair 0:f269e3021894 218 data_free_all();
elessair 0:f269e3021894 219
elessair 0:f269e3021894 220 mode = SOCKET_MODE_CLOSED;
elessair 0:f269e3021894 221 signal_event();
elessair 0:f269e3021894 222 }
elessair 0:f269e3021894 223
elessair 0:f269e3021894 224 bool NanostackSocket::is_bound()
elessair 0:f269e3021894 225 {
elessair 0:f269e3021894 226 return SOCKET_MODE_DATAGRAM == mode;
elessair 0:f269e3021894 227 }
elessair 0:f269e3021894 228
elessair 0:f269e3021894 229 void NanostackSocket::set_bound()
elessair 0:f269e3021894 230 {
elessair 0:f269e3021894 231 nanostack_assert_locked();
elessair 0:f269e3021894 232 MBED_ASSERT(SOCKET_MODE_OPENED == mode);
elessair 0:f269e3021894 233 if (SOCKET_UDP == proto) {
elessair 0:f269e3021894 234 mode = SOCKET_MODE_DATAGRAM;
elessair 0:f269e3021894 235 }
elessair 0:f269e3021894 236 }
elessair 0:f269e3021894 237
elessair 0:f269e3021894 238 bool NanostackSocket::is_connecting()
elessair 0:f269e3021894 239 {
elessair 0:f269e3021894 240 return SOCKET_MODE_CONNECTING == mode;
elessair 0:f269e3021894 241 }
elessair 0:f269e3021894 242
elessair 0:f269e3021894 243 void NanostackSocket::set_connecting(ns_address_t *addr)
elessair 0:f269e3021894 244 {
elessair 0:f269e3021894 245 nanostack_assert_locked();
elessair 0:f269e3021894 246 MBED_ASSERT(SOCKET_MODE_OPENED == mode);
elessair 0:f269e3021894 247
elessair 0:f269e3021894 248 memcpy(&ns_address, addr, sizeof(ns_address_t));
elessair 0:f269e3021894 249 mode = SOCKET_MODE_CONNECTING;
elessair 0:f269e3021894 250 }
elessair 0:f269e3021894 251
elessair 0:f269e3021894 252 void NanostackSocket::set_connected()
elessair 0:f269e3021894 253 {
elessair 0:f269e3021894 254 nanostack_assert_locked();
elessair 0:f269e3021894 255 MBED_ASSERT(SOCKET_MODE_CONNECTING == mode);
elessair 0:f269e3021894 256
elessair 0:f269e3021894 257 mode = SOCKET_MODE_STREAM;
elessair 0:f269e3021894 258 }
elessair 0:f269e3021894 259
elessair 0:f269e3021894 260 void NanostackSocket::signal_event()
elessair 0:f269e3021894 261 {
elessair 0:f269e3021894 262 nanostack_assert_locked();
elessair 0:f269e3021894 263
elessair 0:f269e3021894 264 if (callback != NULL) {
elessair 0:f269e3021894 265 callback(callback_data);
elessair 0:f269e3021894 266 }
elessair 0:f269e3021894 267 }
elessair 0:f269e3021894 268
elessair 0:f269e3021894 269 void NanostackSocket::socket_callback(void *cb) {
elessair 0:f269e3021894 270 nanostack_assert_locked();
elessair 0:f269e3021894 271
elessair 0:f269e3021894 272 socket_callback_t *sock_cb = (socket_callback_t *) cb;
elessair 0:f269e3021894 273 NanostackSocket *socket = socket_tbl[sock_cb->socket_id];
elessair 0:f269e3021894 274 MBED_ASSERT(socket != NULL);
elessair 0:f269e3021894 275
elessair 0:f269e3021894 276 tr_debug("socket_callback() sock=%d, event=%d, interface=%d, data len=%d",
elessair 0:f269e3021894 277 sock_cb->socket_id, sock_cb->event_type, sock_cb->interface_id, sock_cb->d_len);
elessair 0:f269e3021894 278
elessair 0:f269e3021894 279 switch (sock_cb->event_type) {
elessair 0:f269e3021894 280 case SOCKET_DATA:
elessair 0:f269e3021894 281 tr_debug("SOCKET_DATA, sock=%d, bytes=%d", sock_cb->socket_id, sock_cb->d_len);
elessair 0:f269e3021894 282 socket->event_data(sock_cb);
elessair 0:f269e3021894 283 break;
elessair 0:f269e3021894 284 case SOCKET_BIND_DONE:
elessair 0:f269e3021894 285 tr_debug("SOCKET_BIND_DONE");
elessair 0:f269e3021894 286 socket->event_bind_done(sock_cb);
elessair 0:f269e3021894 287 break;
elessair 0:f269e3021894 288 case SOCKET_BIND_FAIL: // Not used in NS
elessair 0:f269e3021894 289 tr_debug("SOCKET_BIND_FAIL");
elessair 0:f269e3021894 290 break;
elessair 0:f269e3021894 291 case SOCKET_BIND_AUTH_FAIL: // Not used in NS
elessair 0:f269e3021894 292 tr_debug("SOCKET_BIND_AUTH_FAIL");
elessair 0:f269e3021894 293 break;
elessair 0:f269e3021894 294 case SOCKET_SERVER_CONNECT_TO_CLIENT: // Not used in NS
elessair 0:f269e3021894 295 tr_debug("SOCKET_SERVER_CONNECT_TO_CLIENT");
elessair 0:f269e3021894 296 break;
elessair 0:f269e3021894 297 case SOCKET_TX_FAIL:
elessair 0:f269e3021894 298 tr_debug("SOCKET_TX_FAIL");
elessair 0:f269e3021894 299 break;
elessair 0:f269e3021894 300 case SOCKET_CONNECT_CLOSED:
elessair 0:f269e3021894 301 tr_debug("SOCKET_CONNECT_CLOSED");
elessair 0:f269e3021894 302 socket->event_connnect_closed(sock_cb);
elessair 0:f269e3021894 303 break;
elessair 0:f269e3021894 304 case SOCKET_CONNECT_FAIL_CLOSED: // Not used in NS
elessair 0:f269e3021894 305 tr_debug("SOCKET_CONNECT_FAIL_CLOSED");
elessair 0:f269e3021894 306 break;
elessair 0:f269e3021894 307 case SOCKET_NO_ROUTE:
elessair 0:f269e3021894 308 tr_debug("SOCKET_NO_ROUTE");
elessair 0:f269e3021894 309 break;
elessair 0:f269e3021894 310 case SOCKET_TX_DONE:
elessair 0:f269e3021894 311 tr_debug("SOCKET_TX_DONE, %d bytes sent", sock_cb->d_len);
elessair 0:f269e3021894 312 socket->event_tx_done(sock_cb);
elessair 0:f269e3021894 313 break;
elessair 0:f269e3021894 314 default:
elessair 0:f269e3021894 315 // SOCKET_NO_RAM, error case for SOCKET_TX_DONE
elessair 0:f269e3021894 316 break;
elessair 0:f269e3021894 317 }
elessair 0:f269e3021894 318 }
elessair 0:f269e3021894 319
elessair 0:f269e3021894 320
elessair 0:f269e3021894 321 bool NanostackSocket::data_available()
elessair 0:f269e3021894 322 {
elessair 0:f269e3021894 323 nanostack_assert_locked();
elessair 0:f269e3021894 324 MBED_ASSERT((SOCKET_MODE_DATAGRAM == mode) ||
elessair 0:f269e3021894 325 (SOCKET_MODE_CONNECTING == mode) ||
elessair 0:f269e3021894 326 (SOCKET_MODE_STREAM == mode));
elessair 0:f269e3021894 327
elessair 0:f269e3021894 328 return (NULL == rxBufChain) ? false : true;
elessair 0:f269e3021894 329 }
elessair 0:f269e3021894 330
elessair 0:f269e3021894 331 size_t NanostackSocket::data_copy_and_free(void *dest, size_t len,
elessair 0:f269e3021894 332 SocketAddress *address, bool stream)
elessair 0:f269e3021894 333 {
elessair 0:f269e3021894 334 nanostack_assert_locked();
elessair 0:f269e3021894 335 MBED_ASSERT((SOCKET_MODE_DATAGRAM == mode) ||
elessair 0:f269e3021894 336 (mode == SOCKET_MODE_STREAM));
elessair 0:f269e3021894 337
elessair 0:f269e3021894 338 NanostackBuffer *data_buf = rxBufChain;
elessair 0:f269e3021894 339 if (NULL == data_buf) {
elessair 0:f269e3021894 340 // No data
elessair 0:f269e3021894 341 return 0;
elessair 0:f269e3021894 342 }
elessair 0:f269e3021894 343
elessair 0:f269e3021894 344 if (address) {
elessair 0:f269e3021894 345 convert_ns_addr_to_mbed(address, &data_buf->ns_address);
elessair 0:f269e3021894 346 }
elessair 0:f269e3021894 347
elessair 0:f269e3021894 348 size_t copy_size = (len > data_buf->length) ? data_buf->length : len;
elessair 0:f269e3021894 349 memcpy(dest, data_buf->payload, copy_size);
elessair 0:f269e3021894 350
elessair 0:f269e3021894 351 if (stream && (copy_size < data_buf->length)) {
elessair 0:f269e3021894 352 // Update the size in the buffer
elessair 0:f269e3021894 353 size_t new_buf_size = data_buf->length - copy_size;
elessair 0:f269e3021894 354 memmove(data_buf->payload, data_buf->payload + copy_size, new_buf_size);
elessair 0:f269e3021894 355 data_buf->length = new_buf_size;
elessair 0:f269e3021894 356 } else {
elessair 0:f269e3021894 357 // Entire packet used so free it
elessair 0:f269e3021894 358 rxBufChain = data_buf->next;
elessair 0:f269e3021894 359 FREE(data_buf);
elessair 0:f269e3021894 360 }
elessair 0:f269e3021894 361
elessair 0:f269e3021894 362 return copy_size;
elessair 0:f269e3021894 363 }
elessair 0:f269e3021894 364
elessair 0:f269e3021894 365 void NanostackSocket::data_free_all(void)
elessair 0:f269e3021894 366 {
elessair 0:f269e3021894 367 nanostack_assert_locked();
elessair 0:f269e3021894 368 // No mode requirement
elessair 0:f269e3021894 369
elessair 0:f269e3021894 370 NanostackBuffer *buffer = rxBufChain;
elessair 0:f269e3021894 371 rxBufChain = NULL;
elessair 0:f269e3021894 372 while (buffer != NULL) {
elessair 0:f269e3021894 373 NanostackBuffer *next_buffer = buffer->next;
elessair 0:f269e3021894 374 FREE(buffer);
elessair 0:f269e3021894 375 buffer = next_buffer;
elessair 0:f269e3021894 376 }
elessair 0:f269e3021894 377 }
elessair 0:f269e3021894 378
elessair 0:f269e3021894 379 void NanostackSocket::data_attach(NanostackBuffer *data_buf)
elessair 0:f269e3021894 380 {
elessair 0:f269e3021894 381 nanostack_assert_locked();
elessair 0:f269e3021894 382 MBED_ASSERT((SOCKET_MODE_DATAGRAM == mode) ||
elessair 0:f269e3021894 383 (SOCKET_MODE_STREAM == mode));
elessair 0:f269e3021894 384
elessair 0:f269e3021894 385 // Add to linked list
elessair 0:f269e3021894 386 tr_debug("data_attach socket=%p", this);
elessair 0:f269e3021894 387 if (NULL == rxBufChain) {
elessair 0:f269e3021894 388 rxBufChain = data_buf;
elessair 0:f269e3021894 389 } else {
elessair 0:f269e3021894 390 NanostackBuffer *buf_tmp = rxBufChain;
elessair 0:f269e3021894 391 while (NULL != buf_tmp->next) {
elessair 0:f269e3021894 392 buf_tmp = buf_tmp->next;
elessair 0:f269e3021894 393 }
elessair 0:f269e3021894 394 buf_tmp->next = data_buf;
elessair 0:f269e3021894 395 }
elessair 0:f269e3021894 396 signal_event();
elessair 0:f269e3021894 397 }
elessair 0:f269e3021894 398
elessair 0:f269e3021894 399 void NanostackSocket::event_data(socket_callback_t *sock_cb)
elessair 0:f269e3021894 400 {
elessair 0:f269e3021894 401 nanostack_assert_locked();
elessair 0:f269e3021894 402 MBED_ASSERT((SOCKET_MODE_DATAGRAM == mode) ||
elessair 0:f269e3021894 403 (SOCKET_MODE_STREAM == mode));
elessair 0:f269e3021894 404
elessair 0:f269e3021894 405 // Allocate buffer
elessair 0:f269e3021894 406 NanostackBuffer *recv_buff = (NanostackBuffer *) MALLOC(
elessair 0:f269e3021894 407 sizeof(NanostackBuffer) + sock_cb->d_len);
elessair 0:f269e3021894 408 if (NULL == recv_buff) {
elessair 0:f269e3021894 409 tr_error("alloc failed!");
elessair 0:f269e3021894 410 return;
elessair 0:f269e3021894 411 }
elessair 0:f269e3021894 412 recv_buff->next = NULL;
elessair 0:f269e3021894 413
elessair 0:f269e3021894 414 // Write data to buffer
elessair 0:f269e3021894 415 int16_t length = socket_read(sock_cb->socket_id,
elessair 0:f269e3021894 416 &recv_buff->ns_address, recv_buff->payload,
elessair 0:f269e3021894 417 sock_cb->d_len);
elessair 0:f269e3021894 418 if (length < 0) {
elessair 0:f269e3021894 419 tr_error("socket_read failed!");
elessair 0:f269e3021894 420 FREE(recv_buff);
elessair 0:f269e3021894 421 return;
elessair 0:f269e3021894 422 }
elessair 0:f269e3021894 423 recv_buff->length = length;
elessair 0:f269e3021894 424
elessair 0:f269e3021894 425 data_attach(recv_buff);
elessair 0:f269e3021894 426 }
elessair 0:f269e3021894 427
elessair 0:f269e3021894 428 void NanostackSocket::event_tx_done(socket_callback_t *sock_cb)
elessair 0:f269e3021894 429 {
elessair 0:f269e3021894 430 nanostack_assert_locked();
elessair 0:f269e3021894 431 MBED_ASSERT((SOCKET_MODE_STREAM == mode) ||
elessair 0:f269e3021894 432 (SOCKET_MODE_DATAGRAM == mode));
elessair 0:f269e3021894 433
elessair 0:f269e3021894 434 signal_event();
elessair 0:f269e3021894 435 }
elessair 0:f269e3021894 436
elessair 0:f269e3021894 437 void NanostackSocket::event_bind_done(socket_callback_t *sock_cb)
elessair 0:f269e3021894 438 {
elessair 0:f269e3021894 439 nanostack_assert_locked();
elessair 0:f269e3021894 440 MBED_ASSERT(SOCKET_MODE_CONNECTING == mode);
elessair 0:f269e3021894 441
elessair 0:f269e3021894 442 set_connected();
elessair 0:f269e3021894 443 signal_event();
elessair 0:f269e3021894 444 }
elessair 0:f269e3021894 445
elessair 0:f269e3021894 446 void NanostackSocket::event_connnect_closed(socket_callback_t *sock_cb)
elessair 0:f269e3021894 447 {
elessair 0:f269e3021894 448 nanostack_assert_locked();
elessair 0:f269e3021894 449
elessair 0:f269e3021894 450 // Only TCP sockets can be closed by the remote end
elessair 0:f269e3021894 451 MBED_ASSERT((SOCKET_MODE_STREAM == mode) ||
elessair 0:f269e3021894 452 (SOCKET_MODE_CONNECTING == mode));
elessair 0:f269e3021894 453 close();
elessair 0:f269e3021894 454 }
elessair 0:f269e3021894 455
elessair 0:f269e3021894 456 MeshInterfaceNanostack::MeshInterfaceNanostack()
elessair 0:f269e3021894 457 : phy(NULL), mesh_api(NULL), rf_device_id(-1), eui64(),
elessair 0:f269e3021894 458 ip_addr_str(), mac_addr_str(), connect_semaphore(0)
elessair 0:f269e3021894 459 {
elessair 0:f269e3021894 460 // Nothing to do
elessair 0:f269e3021894 461 }
elessair 0:f269e3021894 462
elessair 0:f269e3021894 463 MeshInterfaceNanostack::MeshInterfaceNanostack(NanostackRfPhy *phy)
elessair 0:f269e3021894 464 : phy(phy), mesh_api(NULL), rf_device_id(-1), connect_semaphore(0)
elessair 0:f269e3021894 465 {
elessair 0:f269e3021894 466 // Nothing to do
elessair 0:f269e3021894 467 }
elessair 0:f269e3021894 468
elessair 0:f269e3021894 469 int MeshInterfaceNanostack::initialize(NanostackRfPhy *phy)
elessair 0:f269e3021894 470 {
elessair 0:f269e3021894 471 if (this->phy != NULL) {
elessair 0:f269e3021894 472 error("Phy already set");
elessair 0:f269e3021894 473 }
elessair 0:f269e3021894 474 this->phy = phy;
elessair 0:f269e3021894 475 return 0;
elessair 0:f269e3021894 476 }
elessair 0:f269e3021894 477
elessair 0:f269e3021894 478 void MeshInterfaceNanostack::mesh_network_handler(mesh_connection_status_t status)
elessair 0:f269e3021894 479 {
elessair 0:f269e3021894 480 nanostack_lock();
elessair 0:f269e3021894 481
elessair 0:f269e3021894 482 if (status == MESH_CONNECTED) {
elessair 0:f269e3021894 483 connect_semaphore.release();
elessair 0:f269e3021894 484 }
elessair 0:f269e3021894 485
elessair 0:f269e3021894 486 nanostack_unlock();
elessair 0:f269e3021894 487 }
elessair 0:f269e3021894 488
elessair 0:f269e3021894 489 int MeshInterfaceNanostack::register_rf()
elessair 0:f269e3021894 490 {
elessair 0:f269e3021894 491 nanostack_lock();
elessair 0:f269e3021894 492
elessair 0:f269e3021894 493 rf_device_id = phy->rf_register();
elessair 0:f269e3021894 494 if (rf_device_id < 0) {
elessair 0:f269e3021894 495 nanostack_unlock();
elessair 0:f269e3021894 496 return -1;
elessair 0:f269e3021894 497 }
elessair 0:f269e3021894 498 // Read mac address after registering the device.
elessair 0:f269e3021894 499 phy->get_mac_address(eui64);
elessair 0:f269e3021894 500 sprintf(mac_addr_str, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", eui64[0], eui64[1], eui64[2], eui64[3], eui64[4], eui64[5], eui64[6], eui64[7]);
elessair 0:f269e3021894 501
elessair 0:f269e3021894 502 nanostack_unlock();
elessair 0:f269e3021894 503
elessair 0:f269e3021894 504 return 0;
elessair 0:f269e3021894 505 }
elessair 0:f269e3021894 506
elessair 0:f269e3021894 507 int MeshInterfaceNanostack::actual_connect()
elessair 0:f269e3021894 508 {
elessair 0:f269e3021894 509 nanostack_assert_locked();
elessair 0:f269e3021894 510
elessair 0:f269e3021894 511 mesh_error_t status = mesh_api->connect();
elessair 0:f269e3021894 512 if (status != MESH_ERROR_NONE) {
elessair 0:f269e3021894 513 nanostack_unlock();
elessair 0:f269e3021894 514 return map_mesh_error(status);
elessair 0:f269e3021894 515 }
elessair 0:f269e3021894 516
elessair 0:f269e3021894 517 // Release mutex before blocking
elessair 0:f269e3021894 518 nanostack_unlock();
elessair 0:f269e3021894 519
elessair 0:f269e3021894 520 int32_t count = connect_semaphore.wait(30000);
elessair 0:f269e3021894 521
elessair 0:f269e3021894 522 nanostack_lock();
elessair 0:f269e3021894 523
elessair 0:f269e3021894 524 if (count <= 0) {
elessair 0:f269e3021894 525 return NSAPI_ERROR_DHCP_FAILURE; // sort of...
elessair 0:f269e3021894 526 }
elessair 0:f269e3021894 527 return 0;
elessair 0:f269e3021894 528 }
elessair 0:f269e3021894 529
elessair 0:f269e3021894 530 NetworkStack * MeshInterfaceNanostack::get_stack()
elessair 0:f269e3021894 531 {
elessair 0:f269e3021894 532 return NanostackInterface::get_stack();
elessair 0:f269e3021894 533 }
elessair 0:f269e3021894 534
elessair 0:f269e3021894 535 int MeshInterfaceNanostack::disconnect()
elessair 0:f269e3021894 536 {
elessair 0:f269e3021894 537 nanostack_lock();
elessair 0:f269e3021894 538
elessair 0:f269e3021894 539 mesh_error_t status = mesh_api->disconnect();
elessair 0:f269e3021894 540
elessair 0:f269e3021894 541 nanostack_unlock();
elessair 0:f269e3021894 542
elessair 0:f269e3021894 543 return map_mesh_error(status);
elessair 0:f269e3021894 544 }
elessair 0:f269e3021894 545
elessair 0:f269e3021894 546 const char *MeshInterfaceNanostack::get_ip_address()
elessair 0:f269e3021894 547 {
elessair 0:f269e3021894 548 nanostack_lock();
elessair 0:f269e3021894 549
elessair 0:f269e3021894 550 const char *ret = NULL;
elessair 0:f269e3021894 551 if (mesh_api && mesh_api->getOwnIpAddress(ip_addr_str, sizeof ip_addr_str)) {
elessair 0:f269e3021894 552 ret = ip_addr_str;
elessair 0:f269e3021894 553 }
elessair 0:f269e3021894 554
elessair 0:f269e3021894 555 nanostack_unlock();
elessair 0:f269e3021894 556
elessair 0:f269e3021894 557 return ret;
elessair 0:f269e3021894 558 }
elessair 0:f269e3021894 559
elessair 0:f269e3021894 560 const char *MeshInterfaceNanostack::get_mac_address()
elessair 0:f269e3021894 561 {
elessair 0:f269e3021894 562 return mac_addr_str;
elessair 0:f269e3021894 563 }
elessair 0:f269e3021894 564
elessair 0:f269e3021894 565 int ThreadInterface::connect()
elessair 0:f269e3021894 566 {
elessair 0:f269e3021894 567 // initialize mesh networking resources, memory, timers, etc...
elessair 0:f269e3021894 568 mesh_system_init();
elessair 0:f269e3021894 569 nanostack_lock();
elessair 0:f269e3021894 570
elessair 0:f269e3021894 571 mesh_api = MeshInterfaceFactory::createInterface(MESH_TYPE_THREAD);
elessair 0:f269e3021894 572 if (!mesh_api) {
elessair 0:f269e3021894 573 nanostack_unlock();
elessair 0:f269e3021894 574 return NSAPI_ERROR_NO_MEMORY;
elessair 0:f269e3021894 575 }
elessair 0:f269e3021894 576 if (register_rf() < 0) {
elessair 0:f269e3021894 577 nanostack_unlock();
elessair 0:f269e3021894 578 return NSAPI_ERROR_DEVICE_ERROR;
elessair 0:f269e3021894 579 }
elessair 0:f269e3021894 580
elessair 0:f269e3021894 581 // After the RF is up, we can seed the random from it.
elessair 0:f269e3021894 582 randLIB_seed_random();
elessair 0:f269e3021894 583
elessair 0:f269e3021894 584 mesh_error_t status = ((MeshThread *)mesh_api)->init(rf_device_id, AbstractMesh::mesh_network_handler_t(static_cast<MeshInterfaceNanostack *>(this), &ThreadInterface::mesh_network_handler), eui64, NULL);
elessair 0:f269e3021894 585 if (status != MESH_ERROR_NONE) {
elessair 0:f269e3021894 586 nanostack_unlock();
elessair 0:f269e3021894 587 return map_mesh_error(status);
elessair 0:f269e3021894 588 }
elessair 0:f269e3021894 589 int ret = this->actual_connect();
elessair 0:f269e3021894 590
elessair 0:f269e3021894 591 nanostack_unlock();
elessair 0:f269e3021894 592
elessair 0:f269e3021894 593 return ret;
elessair 0:f269e3021894 594 }
elessair 0:f269e3021894 595
elessair 0:f269e3021894 596 int LoWPANNDInterface::connect()
elessair 0:f269e3021894 597 {
elessair 0:f269e3021894 598 // initialize mesh networking resources, memory, timers, etc...
elessair 0:f269e3021894 599 mesh_system_init();
elessair 0:f269e3021894 600 nanostack_lock();
elessair 0:f269e3021894 601
elessair 0:f269e3021894 602 mesh_api = MeshInterfaceFactory::createInterface(MESH_TYPE_6LOWPAN_ND);
elessair 0:f269e3021894 603 if (!mesh_api) {
elessair 0:f269e3021894 604 nanostack_unlock();
elessair 0:f269e3021894 605 return NSAPI_ERROR_NO_MEMORY;
elessair 0:f269e3021894 606 }
elessair 0:f269e3021894 607 if (register_rf() < 0) {
elessair 0:f269e3021894 608 nanostack_unlock();
elessair 0:f269e3021894 609 return NSAPI_ERROR_DEVICE_ERROR;
elessair 0:f269e3021894 610 }
elessair 0:f269e3021894 611
elessair 0:f269e3021894 612 // After the RF is up, we can seed the random from it.
elessair 0:f269e3021894 613 randLIB_seed_random();
elessair 0:f269e3021894 614
elessair 0:f269e3021894 615 mesh_error_t status = ((Mesh6LoWPAN_ND *)mesh_api)->init(rf_device_id, AbstractMesh::mesh_network_handler_t(static_cast<MeshInterfaceNanostack *>(this), &LoWPANNDInterface::mesh_network_handler));
elessair 0:f269e3021894 616 if (status != MESH_ERROR_NONE) {
elessair 0:f269e3021894 617 nanostack_unlock();
elessair 0:f269e3021894 618 return map_mesh_error(status);
elessair 0:f269e3021894 619 }
elessair 0:f269e3021894 620 int ret = this->actual_connect();
elessair 0:f269e3021894 621
elessair 0:f269e3021894 622 nanostack_unlock();
elessair 0:f269e3021894 623
elessair 0:f269e3021894 624 return ret;
elessair 0:f269e3021894 625 }
elessair 0:f269e3021894 626
elessair 0:f269e3021894 627 NanostackInterface * NanostackInterface::_ns_interface;
elessair 0:f269e3021894 628
elessair 0:f269e3021894 629 NanostackInterface * NanostackInterface::get_stack()
elessair 0:f269e3021894 630 {
elessair 0:f269e3021894 631 nanostack_lock();
elessair 0:f269e3021894 632
elessair 0:f269e3021894 633 if (NULL == _ns_interface) {
elessair 0:f269e3021894 634 _ns_interface = new NanostackInterface();
elessair 0:f269e3021894 635 }
elessair 0:f269e3021894 636
elessair 0:f269e3021894 637 nanostack_unlock();
elessair 0:f269e3021894 638
elessair 0:f269e3021894 639 return _ns_interface;
elessair 0:f269e3021894 640 }
elessair 0:f269e3021894 641
elessair 0:f269e3021894 642
elessair 0:f269e3021894 643 const char * NanostackInterface::get_ip_address()
elessair 0:f269e3021894 644 {
elessair 0:f269e3021894 645 // Unsupported
elessair 0:f269e3021894 646 return NULL;
elessair 0:f269e3021894 647 }
elessair 0:f269e3021894 648
elessair 0:f269e3021894 649 int NanostackInterface::socket_open(void **handle, nsapi_protocol_t protocol)
elessair 0:f269e3021894 650 {
elessair 0:f269e3021894 651 // Validate parameters
elessair 0:f269e3021894 652 if (NULL == handle) {
elessair 0:f269e3021894 653 MBED_ASSERT(false);
elessair 0:f269e3021894 654 return NSAPI_ERROR_NO_SOCKET;
elessair 0:f269e3021894 655 }
elessair 0:f269e3021894 656 int8_t ns_proto;
elessair 0:f269e3021894 657 if (NSAPI_UDP == protocol) {
elessair 0:f269e3021894 658 ns_proto = SOCKET_UDP;
elessair 0:f269e3021894 659 } else if (NSAPI_TCP == protocol) {
elessair 0:f269e3021894 660 ns_proto = SOCKET_TCP;
elessair 0:f269e3021894 661 } else {
elessair 0:f269e3021894 662 MBED_ASSERT(false);
elessair 0:f269e3021894 663 return NSAPI_ERROR_UNSUPPORTED;
elessair 0:f269e3021894 664 }
elessair 0:f269e3021894 665 *handle = (void*)NULL;
elessair 0:f269e3021894 666
elessair 0:f269e3021894 667 nanostack_lock();
elessair 0:f269e3021894 668
elessair 0:f269e3021894 669 NanostackSocket * socket = new NanostackSocket(ns_proto);
elessair 0:f269e3021894 670 if (NULL == socket) {
elessair 0:f269e3021894 671 nanostack_unlock();
elessair 0:f269e3021894 672 tr_debug("socket_open() ret=%i", NSAPI_ERROR_NO_MEMORY);
elessair 0:f269e3021894 673 return NSAPI_ERROR_NO_MEMORY;
elessair 0:f269e3021894 674 }
elessair 0:f269e3021894 675 if (!socket->open()) {
elessair 0:f269e3021894 676 delete socket;
elessair 0:f269e3021894 677 nanostack_unlock();
elessair 0:f269e3021894 678 tr_debug("socket_open() ret=%i", NSAPI_ERROR_DEVICE_ERROR);
elessair 0:f269e3021894 679 return NSAPI_ERROR_DEVICE_ERROR;
elessair 0:f269e3021894 680 }
elessair 0:f269e3021894 681 *handle = (void*)socket;
elessair 0:f269e3021894 682
elessair 0:f269e3021894 683 nanostack_unlock();
elessair 0:f269e3021894 684
elessair 0:f269e3021894 685 tr_debug("socket_open() socket=%p, sock_id=%d, ret=0", socket, socket->socket_id);
elessair 0:f269e3021894 686
elessair 0:f269e3021894 687 return 0;
elessair 0:f269e3021894 688 }
elessair 0:f269e3021894 689
elessair 0:f269e3021894 690 int NanostackInterface::socket_close(void *handle)
elessair 0:f269e3021894 691 {
elessair 0:f269e3021894 692 // Validate parameters
elessair 0:f269e3021894 693 NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
elessair 0:f269e3021894 694 if (NULL == handle) {
elessair 0:f269e3021894 695 MBED_ASSERT(false);
elessair 0:f269e3021894 696 return NSAPI_ERROR_NO_SOCKET;
elessair 0:f269e3021894 697 }
elessair 0:f269e3021894 698 tr_debug("socket_close(socket=%p) sock_id=%d", socket, socket->socket_id);
elessair 0:f269e3021894 699
elessair 0:f269e3021894 700 nanostack_lock();
elessair 0:f269e3021894 701
elessair 0:f269e3021894 702 delete socket;
elessair 0:f269e3021894 703
elessair 0:f269e3021894 704 nanostack_unlock();
elessair 0:f269e3021894 705
elessair 0:f269e3021894 706 return 0;
elessair 0:f269e3021894 707
elessair 0:f269e3021894 708 }
elessair 0:f269e3021894 709
elessair 0:f269e3021894 710 int NanostackInterface::socket_sendto(void *handle, const SocketAddress &address, const void *data, unsigned int size)
elessair 0:f269e3021894 711 {
elessair 0:f269e3021894 712 // Validate parameters
elessair 0:f269e3021894 713 NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
elessair 0:f269e3021894 714 if (NULL == handle) {
elessair 0:f269e3021894 715 MBED_ASSERT(false);
elessair 0:f269e3021894 716 return NSAPI_ERROR_NO_SOCKET;
elessair 0:f269e3021894 717 }
elessair 0:f269e3021894 718
elessair 0:f269e3021894 719 nanostack_lock();
elessair 0:f269e3021894 720
elessair 0:f269e3021894 721 int ret;
elessair 0:f269e3021894 722 if (socket->closed()) {
elessair 0:f269e3021894 723 ret = NSAPI_ERROR_NO_CONNECTION;
elessair 0:f269e3021894 724 } else if (NANOSTACK_SOCKET_TCP == socket->proto) {
elessair 0:f269e3021894 725 tr_error("socket_sendto() not supported with SOCKET_STREAM!");
elessair 0:f269e3021894 726 ret = NSAPI_ERROR_UNSUPPORTED;
elessair 0:f269e3021894 727 } else {
elessair 0:f269e3021894 728 ns_address_t ns_address;
elessair 0:f269e3021894 729 convert_mbed_addr_to_ns(&ns_address, &address);
elessair 0:f269e3021894 730 if (!socket->is_bound()) {
elessair 0:f269e3021894 731 socket->set_bound();
elessair 0:f269e3021894 732 }
elessair 0:f269e3021894 733 int8_t send_to_status = ::socket_sendto(socket->socket_id, &ns_address,
elessair 0:f269e3021894 734 (uint8_t *)data, size);
elessair 0:f269e3021894 735 /*
elessair 0:f269e3021894 736 * \return 0 on success.
elessair 0:f269e3021894 737 * \return -1 invalid socket id.
elessair 0:f269e3021894 738 * \return -2 Socket memory allocation fail.
elessair 0:f269e3021894 739 * \return -3 TCP state not established.
elessair 0:f269e3021894 740 * \return -4 Socket tx process busy.
elessair 0:f269e3021894 741 * \return -5 TLS authentication not ready.
elessair 0:f269e3021894 742 * \return -6 Packet too short.
elessair 0:f269e3021894 743 * */
elessair 0:f269e3021894 744 if (-4 == send_to_status) {
elessair 0:f269e3021894 745 ret = NSAPI_ERROR_WOULD_BLOCK;
elessair 0:f269e3021894 746 } else if (0 != send_to_status) {
elessair 0:f269e3021894 747 tr_error("socket_sendto: error=%d", send_to_status);
elessair 0:f269e3021894 748 ret = NSAPI_ERROR_DEVICE_ERROR;
elessair 0:f269e3021894 749 } else {
elessair 0:f269e3021894 750 ret = size;
elessair 0:f269e3021894 751 }
elessair 0:f269e3021894 752 }
elessair 0:f269e3021894 753
elessair 0:f269e3021894 754 nanostack_unlock();
elessair 0:f269e3021894 755
elessair 0:f269e3021894 756 tr_debug("socket_sendto(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);
elessair 0:f269e3021894 757
elessair 0:f269e3021894 758 return ret;
elessair 0:f269e3021894 759 }
elessair 0:f269e3021894 760
elessair 0:f269e3021894 761 int NanostackInterface::socket_recvfrom(void *handle, SocketAddress *address, void *buffer, unsigned size)
elessair 0:f269e3021894 762 {
elessair 0:f269e3021894 763 // Validate parameters
elessair 0:f269e3021894 764 NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
elessair 0:f269e3021894 765 if (NULL == handle) {
elessair 0:f269e3021894 766 MBED_ASSERT(false);
elessair 0:f269e3021894 767 return NSAPI_ERROR_NO_SOCKET;
elessair 0:f269e3021894 768 }
elessair 0:f269e3021894 769 if (NULL == buffer) {
elessair 0:f269e3021894 770 MBED_ASSERT(false);
elessair 0:f269e3021894 771 return NSAPI_ERROR_PARAMETER;
elessair 0:f269e3021894 772 }
elessair 0:f269e3021894 773 if (0 == size) {
elessair 0:f269e3021894 774 MBED_ASSERT(false);
elessair 0:f269e3021894 775 return NSAPI_ERROR_PARAMETER;
elessair 0:f269e3021894 776 }
elessair 0:f269e3021894 777
elessair 0:f269e3021894 778 nanostack_lock();
elessair 0:f269e3021894 779
elessair 0:f269e3021894 780 int ret;
elessair 0:f269e3021894 781 if (socket->closed()) {
elessair 0:f269e3021894 782 ret = NSAPI_ERROR_NO_CONNECTION;
elessair 0:f269e3021894 783 } else if (NANOSTACK_SOCKET_TCP == socket->proto) {
elessair 0:f269e3021894 784 tr_error("recv_from() not supported with SOCKET_STREAM!");
elessair 0:f269e3021894 785 ret = NSAPI_ERROR_UNSUPPORTED;
elessair 0:f269e3021894 786 } else if (!socket->data_available()) {
elessair 0:f269e3021894 787 ret = NSAPI_ERROR_WOULD_BLOCK;
elessair 0:f269e3021894 788 } else {
elessair 0:f269e3021894 789 ret = socket->data_copy_and_free(buffer, size, address, false);
elessair 0:f269e3021894 790 }
elessair 0:f269e3021894 791
elessair 0:f269e3021894 792 nanostack_unlock();
elessair 0:f269e3021894 793
elessair 0:f269e3021894 794 tr_debug("socket_recvfrom(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);
elessair 0:f269e3021894 795
elessair 0:f269e3021894 796 return ret;
elessair 0:f269e3021894 797 }
elessair 0:f269e3021894 798
elessair 0:f269e3021894 799 int NanostackInterface::socket_bind(void *handle, const SocketAddress &address)
elessair 0:f269e3021894 800 {
elessair 0:f269e3021894 801 // Validate parameters
elessair 0:f269e3021894 802 NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
elessair 0:f269e3021894 803 if (NULL == handle) {
elessair 0:f269e3021894 804 MBED_ASSERT(false);
elessair 0:f269e3021894 805 return NSAPI_ERROR_NO_SOCKET;
elessair 0:f269e3021894 806 }
elessair 0:f269e3021894 807
elessair 0:f269e3021894 808
elessair 0:f269e3021894 809 nanostack_lock();
elessair 0:f269e3021894 810
elessair 0:f269e3021894 811 ns_address_t ns_address;
elessair 0:f269e3021894 812 ns_address.type = ADDRESS_IPV6;
elessair 0:f269e3021894 813 memset(ns_address.address, 0, sizeof ns_address.address);
elessair 0:f269e3021894 814 ns_address.identifier = address.get_port();
elessair 0:f269e3021894 815 int ret = NSAPI_ERROR_DEVICE_ERROR;
elessair 0:f269e3021894 816 if (0 == ::socket_bind(socket->socket_id, &ns_address)) {
elessair 0:f269e3021894 817 socket->set_bound();
elessair 0:f269e3021894 818 ret = 0;
elessair 0:f269e3021894 819 }
elessair 0:f269e3021894 820
elessair 0:f269e3021894 821 nanostack_unlock();
elessair 0:f269e3021894 822
elessair 0:f269e3021894 823 tr_debug("socket_bind(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);
elessair 0:f269e3021894 824
elessair 0:f269e3021894 825 return ret;
elessair 0:f269e3021894 826 }
elessair 0:f269e3021894 827
elessair 0:f269e3021894 828 int NanostackInterface::setsockopt(void *handle, int level, int optname, const void *optval, unsigned optlen)
elessair 0:f269e3021894 829 {
elessair 0:f269e3021894 830 return NSAPI_ERROR_UNSUPPORTED;
elessair 0:f269e3021894 831 }
elessair 0:f269e3021894 832
elessair 0:f269e3021894 833 int NanostackInterface::getsockopt(void *handle, int level, int optname, void *optval, unsigned *optlen)
elessair 0:f269e3021894 834 {
elessair 0:f269e3021894 835 return NSAPI_ERROR_UNSUPPORTED;
elessair 0:f269e3021894 836 }
elessair 0:f269e3021894 837
elessair 0:f269e3021894 838 int NanostackInterface::socket_listen(void *handle, int backlog)
elessair 0:f269e3021894 839 {
elessair 0:f269e3021894 840 return NSAPI_ERROR_UNSUPPORTED;
elessair 0:f269e3021894 841 }
elessair 0:f269e3021894 842
elessair 0:f269e3021894 843 int NanostackInterface::socket_connect(void *handle, const SocketAddress &addr)
elessair 0:f269e3021894 844 {
elessair 0:f269e3021894 845 // Validate parameters
elessair 0:f269e3021894 846 NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
elessair 0:f269e3021894 847 if (NULL == handle) {
elessair 0:f269e3021894 848 MBED_ASSERT(false);
elessair 0:f269e3021894 849 return NSAPI_ERROR_NO_SOCKET;
elessair 0:f269e3021894 850 }
elessair 0:f269e3021894 851
elessair 0:f269e3021894 852 nanostack_lock();
elessair 0:f269e3021894 853
elessair 0:f269e3021894 854 int ret;
elessair 0:f269e3021894 855 ns_address_t ns_addr;
elessair 0:f269e3021894 856 int random_port = socket->is_bound() ? 0 : 1;
elessair 0:f269e3021894 857 convert_mbed_addr_to_ns(&ns_addr, &addr);
elessair 0:f269e3021894 858 if (0 == ::socket_connect(socket->socket_id, &ns_addr, random_port)) {
elessair 0:f269e3021894 859 socket->set_connecting(&ns_addr);
elessair 0:f269e3021894 860 ret = 0;
elessair 0:f269e3021894 861 } else {
elessair 0:f269e3021894 862 ret = NSAPI_ERROR_DEVICE_ERROR;
elessair 0:f269e3021894 863 }
elessair 0:f269e3021894 864
elessair 0:f269e3021894 865 nanostack_unlock();
elessair 0:f269e3021894 866
elessair 0:f269e3021894 867 tr_debug("socket_connect(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);
elessair 0:f269e3021894 868
elessair 0:f269e3021894 869 return ret;
elessair 0:f269e3021894 870 }
elessair 0:f269e3021894 871
elessair 0:f269e3021894 872 int NanostackInterface::socket_accept(void *server, void **handle, SocketAddress *address)
elessair 0:f269e3021894 873 {
elessair 0:f269e3021894 874 return NSAPI_ERROR_UNSUPPORTED;
elessair 0:f269e3021894 875 }
elessair 0:f269e3021894 876
elessair 0:f269e3021894 877 int NanostackInterface::socket_send(void *handle, const void *p, unsigned size)
elessair 0:f269e3021894 878 {
elessair 0:f269e3021894 879 // Validate parameters
elessair 0:f269e3021894 880 NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
elessair 0:f269e3021894 881 if (NULL == handle) {
elessair 0:f269e3021894 882 MBED_ASSERT(false);
elessair 0:f269e3021894 883 return NSAPI_ERROR_NO_SOCKET;
elessair 0:f269e3021894 884 }
elessair 0:f269e3021894 885
elessair 0:f269e3021894 886 nanostack_lock();
elessair 0:f269e3021894 887
elessair 0:f269e3021894 888 int ret;
elessair 0:f269e3021894 889 if (socket->closed()) {
elessair 0:f269e3021894 890 ret = NSAPI_ERROR_NO_CONNECTION;
elessair 0:f269e3021894 891 } else if (socket->is_connecting()) {
elessair 0:f269e3021894 892 ret = NSAPI_ERROR_WOULD_BLOCK;
elessair 0:f269e3021894 893 } else {
elessair 0:f269e3021894 894 ret = ::socket_sendto(socket->socket_id, &socket->ns_address, (uint8_t*)p, size);
elessair 0:f269e3021894 895 /*
elessair 0:f269e3021894 896 * \return 0 on success.
elessair 0:f269e3021894 897 * \return -1 invalid socket id.
elessair 0:f269e3021894 898 * \return -2 Socket memory allocation fail.
elessair 0:f269e3021894 899 * \return -3 TCP state not established.
elessair 0:f269e3021894 900 * \return -4 Socket tx process busy.
elessair 0:f269e3021894 901 * \return -5 TLS authentication not ready.
elessair 0:f269e3021894 902 * \return -6 Packet too short.
elessair 0:f269e3021894 903 * */
elessair 0:f269e3021894 904 if (-4 == ret) {
elessair 0:f269e3021894 905 ret = NSAPI_ERROR_WOULD_BLOCK;
elessair 0:f269e3021894 906 } else if (ret != 0) {
elessair 0:f269e3021894 907 tr_warning("socket_sendto ret %i, socket_id %i", ret, socket->socket_id);
elessair 0:f269e3021894 908 ret = NSAPI_ERROR_DEVICE_ERROR;
elessair 0:f269e3021894 909 } else {
elessair 0:f269e3021894 910 ret = size;
elessair 0:f269e3021894 911 }
elessair 0:f269e3021894 912 }
elessair 0:f269e3021894 913
elessair 0:f269e3021894 914 nanostack_unlock();
elessair 0:f269e3021894 915
elessair 0:f269e3021894 916 tr_debug("socket_send(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);
elessair 0:f269e3021894 917
elessair 0:f269e3021894 918 return ret;
elessair 0:f269e3021894 919 }
elessair 0:f269e3021894 920
elessair 0:f269e3021894 921 int NanostackInterface::socket_recv(void *handle, void *data, unsigned size)
elessair 0:f269e3021894 922 {
elessair 0:f269e3021894 923 // Validate parameters
elessair 0:f269e3021894 924 NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
elessair 0:f269e3021894 925 if (NULL == handle) {
elessair 0:f269e3021894 926 MBED_ASSERT(false);
elessair 0:f269e3021894 927 return NSAPI_ERROR_NO_SOCKET;
elessair 0:f269e3021894 928 }
elessair 0:f269e3021894 929
elessair 0:f269e3021894 930 nanostack_lock();
elessair 0:f269e3021894 931
elessair 0:f269e3021894 932 int ret;
elessair 0:f269e3021894 933 if (socket->closed()) {
elessair 0:f269e3021894 934 ret = NSAPI_ERROR_NO_CONNECTION;
elessair 0:f269e3021894 935 } else if (socket->data_available()) {
elessair 0:f269e3021894 936 ret = socket->data_copy_and_free(data, size, NULL, true);
elessair 0:f269e3021894 937 } else {
elessair 0:f269e3021894 938 ret = NSAPI_ERROR_WOULD_BLOCK;
elessair 0:f269e3021894 939 }
elessair 0:f269e3021894 940
elessair 0:f269e3021894 941 nanostack_unlock();
elessair 0:f269e3021894 942
elessair 0:f269e3021894 943 tr_debug("socket_recv(socket=%p) sock_id=%d, ret=%i", socket, socket->socket_id, ret);
elessair 0:f269e3021894 944
elessair 0:f269e3021894 945 return ret;
elessair 0:f269e3021894 946 }
elessair 0:f269e3021894 947
elessair 0:f269e3021894 948 void NanostackInterface::socket_attach(void *handle, void (*callback)(void *), void *id)
elessair 0:f269e3021894 949 {
elessair 0:f269e3021894 950 // Validate parameters
elessair 0:f269e3021894 951 NanostackSocket * socket = static_cast<NanostackSocket *>(handle);
elessair 0:f269e3021894 952 if (NULL == handle) {
elessair 0:f269e3021894 953 MBED_ASSERT(false);
elessair 0:f269e3021894 954 return;
elessair 0:f269e3021894 955 }
elessair 0:f269e3021894 956
elessair 0:f269e3021894 957 nanostack_lock();
elessair 0:f269e3021894 958
elessair 0:f269e3021894 959 socket->callback = callback;
elessair 0:f269e3021894 960 socket->callback_data = id;
elessair 0:f269e3021894 961
elessair 0:f269e3021894 962 nanostack_unlock();
elessair 0:f269e3021894 963
elessair 0:f269e3021894 964 tr_debug("socket_attach(socket=%p) sock_id=%d", socket, socket->socket_id);
elessair 0:f269e3021894 965 }