takashi kadono / Mbed OS Nucleo446_SSD1331

Dependencies:   ssd1331

Committer:
kadonotakashi
Date:
Wed Oct 10 00:33:53 2018 +0000
Revision:
0:8fdf9a60065b
how to make mbed librry

Who changed what in which revision?

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