Pinned to some recent date

Committer:
Simon Cooksey
Date:
Thu Nov 17 16:43:53 2016 +0000
Revision:
0:fb7af294d5d9
Initial commit

Who changed what in which revision?

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