void NanostackSocket::event_data(socket_callback_t *sock_cb) { nanostack_assert_locked(); MBED_ASSERT((SOCKET_MODE_DATAGRAM == mode) || (SOCKET_MODE_STREAM == mode)); // Allocate buffer NanostackBuffer *recv_buff = (NanostackBuffer *) MALLOC( sizeof(NanostackBuffer) + sock_cb->d_len); if (NULL == recv_buff) { tr_error("alloc failed!"); return; } recv_buff->next = NULL; // Write data to buffer int16_t length = socket_read(sock_cb->socket_id, &recv_buff->ns_address, recv_buff->payload, sock_cb->d_len); if (length < 0) { tr_error("socket_read failed!"); FREE(recv_buff); return; } recv_buff->length = length; data_attach(recv_buff); }
void NanostackSocket::set_connected() { nanostack_assert_locked(); MBED_ASSERT(SOCKET_MODE_CONNECTING == mode); mode = SOCKET_MODE_STREAM; }
bool NanostackSocket::open(void) { nanostack_assert_locked(); MBED_ASSERT(SOCKET_MODE_UNOPENED == mode); int temp_socket = socket_open(proto, 0, socket_callback); if (temp_socket < 0) { tr_error("NanostackSocket::open() failed"); return false; } if (temp_socket >= NS_INTERFACE_SOCKETS_MAX) { MBED_ASSERT(false); return false; } if (socket_tbl[temp_socket] != NULL) { MBED_ASSERT(false); return false; } socket_id = temp_socket; socket_tbl[socket_id] = this; mode = SOCKET_MODE_OPENED; return true; }
void NanostackSocket::set_listening() { nanostack_assert_locked(); MBED_ASSERT(SOCKET_MODE_OPENED == mode); mode = SOCKET_MODE_LISTENING; }
size_t NanostackSocket::data_copy_and_free(void *dest, size_t len, SocketAddress *address, bool stream) { nanostack_assert_locked(); MBED_ASSERT((SOCKET_MODE_DATAGRAM == mode) || (mode == SOCKET_MODE_STREAM)); NanostackBuffer *data_buf = rxBufChain; if (NULL == data_buf) { // No data return 0; } if (address) { convert_ns_addr_to_mbed(address, &data_buf->ns_address); } size_t copy_size = (len > data_buf->length) ? data_buf->length : len; memcpy(dest, data_buf->payload, copy_size); if (stream && (copy_size < data_buf->length)) { // Update the size in the buffer size_t new_buf_size = data_buf->length - copy_size; memmove(data_buf->payload, data_buf->payload + copy_size, new_buf_size); data_buf->length = new_buf_size; } else { // Entire packet used so free it rxBufChain = data_buf->next; FREE(data_buf); } return copy_size; }
void NanostackSocket::socket_callback(void *cb) { nanostack_assert_locked(); socket_callback_t *sock_cb = (socket_callback_t *) cb; NanostackSocket *socket = socket_tbl[sock_cb->socket_id]; MBED_ASSERT(socket != NULL); tr_debug("socket_callback() sock=%d, event=%d, interface=%d, data len=%d", sock_cb->socket_id, sock_cb->event_type, sock_cb->interface_id, sock_cb->d_len); switch (sock_cb->event_type) { case SOCKET_DATA: tr_debug("SOCKET_DATA, sock=%d, bytes=%d", sock_cb->socket_id, sock_cb->d_len); socket->event_data(sock_cb); break; case SOCKET_CONNECT_DONE: tr_debug("SOCKET_CONNECT_DONE"); socket->event_connect_done(sock_cb); break; case SOCKET_CONNECT_FAIL: tr_debug("SOCKET_CONNECT_FAIL"); socket->event_connect_fail(sock_cb); break; case SOCKET_CONNECT_AUTH_FAIL: tr_debug("SOCKET_CONNECT_AUTH_FAIL"); break; case SOCKET_INCOMING_CONNECTION: tr_debug("SOCKET_INCOMING_CONNECTION"); socket->event_incoming_connection(sock_cb); break; case SOCKET_TX_FAIL: tr_debug("SOCKET_TX_FAIL"); socket->event_tx_fail(sock_cb); break; case SOCKET_CONNECT_CLOSED: tr_debug("SOCKET_CONNECT_CLOSED"); socket->event_connect_closed(sock_cb); break; case SOCKET_CONNECTION_RESET: tr_debug("SOCKET_CONNECTION_RESET"); socket->event_connection_reset(sock_cb); break; case SOCKET_NO_ROUTE: tr_debug("SOCKET_NO_ROUTE"); socket->event_tx_fail(sock_cb); break; case SOCKET_TX_DONE: socket->event_tx_done(sock_cb); break; case SOCKET_NO_RAM: tr_debug("SOCKET_NO_RAM"); socket->event_tx_fail(sock_cb); break; case SOCKET_CONNECTION_PROBLEM: tr_debug("SOCKET_CONNECTION_PROBLEM"); break; default: break; } }
void NanostackSocket::event_data(socket_callback_t *sock_cb) { nanostack_assert_locked(); MBED_ASSERT((SOCKET_MODE_STREAM == mode) || (SOCKET_MODE_DATAGRAM == mode)); signal_event(); }
NanostackSocket::~NanostackSocket() { nanostack_assert_locked(); if (mode != SOCKET_MODE_CLOSED) { close(); } }
void NanostackSocket::set_bound() { nanostack_assert_locked(); MBED_ASSERT(SOCKET_MODE_OPENED == mode); if (SOCKET_UDP == proto) { mode = SOCKET_MODE_DATAGRAM; } }
void NanostackSocket::event_connect_done(socket_callback_t *sock_cb) { nanostack_assert_locked(); MBED_ASSERT(SOCKET_MODE_CONNECTING == mode); set_connected(); signal_event(); }
void NanostackSocket::signal_event() { nanostack_assert_locked(); if (callback != NULL) { callback(callback_data); } }
void NanostackSocket::set_connecting(ns_address_t *addr) { nanostack_assert_locked(); MBED_ASSERT(SOCKET_MODE_OPENED == mode); memcpy(&ns_address, addr, sizeof(ns_address_t)); mode = SOCKET_MODE_CONNECTING; }
bool NanostackSocket::data_available() { nanostack_assert_locked(); MBED_ASSERT((SOCKET_MODE_DATAGRAM == mode) || (SOCKET_MODE_CONNECTING == mode) || (SOCKET_MODE_STREAM == mode)); return (NULL == rxBufChain) ? false : true; }
void NanostackSocket::event_connection_reset(socket_callback_t *sock_cb) { nanostack_assert_locked(); // Only TCP sockets can be closed by the remote end MBED_ASSERT((SOCKET_MODE_STREAM == mode) || (SOCKET_MODE_CONNECTING == mode)); close(); }
void NanostackSocket::event_connect_closed(socket_callback_t *sock_cb) { nanostack_assert_locked(); // Can happen if we have an orderly close() // Might never happen as we have not implemented shutdown() in abstraction layer. MBED_ASSERT(mode == SOCKET_MODE_STREAM); close(); }
NanostackSocket::NanostackSocket(int8_t protocol) { nanostack_assert_locked(); callback = NULL; callback_data = NULL; socket_id = -1; proto = protocol; addr_valid = false; memset(&ns_address, 0, sizeof(ns_address)); mode = SOCKET_MODE_UNOPENED; }
void NanostackSocket::data_free_all(void) { nanostack_assert_locked(); // No mode requirement NanostackBuffer *buffer = rxBufChain; rxBufChain = NULL; while (buffer != NULL) { NanostackBuffer *next_buffer = buffer->next; FREE(buffer); buffer = next_buffer; } }
void NanostackSocket::event_tx_done(socket_callback_t *sock_cb) { nanostack_assert_locked(); MBED_ASSERT((SOCKET_MODE_STREAM == mode) || (SOCKET_MODE_DATAGRAM == mode)); if (mode == SOCKET_MODE_DATAGRAM) { tr_debug("SOCKET_TX_DONE, %d bytes sent", sock_cb->d_len); } else if (mode == SOCKET_MODE_STREAM) { tr_debug("SOCKET_TX_DONE, %d bytes remaining", sock_cb->d_len); } signal_event(); }
void NanostackSocket::socket_callback(void *cb) { nanostack_assert_locked(); socket_callback_t *sock_cb = (socket_callback_t *) cb; NanostackSocket *socket = socket_tbl[sock_cb->socket_id]; MBED_ASSERT(socket != NULL); tr_debug("socket_callback() sock=%d, event=%d, interface=%d, data len=%d", sock_cb->socket_id, sock_cb->event_type, sock_cb->interface_id, sock_cb->d_len); switch (sock_cb->event_type) { case SOCKET_DATA: tr_debug("SOCKET_DATA, sock=%d, bytes=%d", sock_cb->socket_id, sock_cb->d_len); socket->event_data(sock_cb); break; case SOCKET_BIND_DONE: tr_debug("SOCKET_BIND_DONE"); socket->event_bind_done(sock_cb); break; case SOCKET_BIND_FAIL: // Not used in NS tr_debug("SOCKET_BIND_FAIL"); break; case SOCKET_BIND_AUTH_FAIL: // Not used in NS tr_debug("SOCKET_BIND_AUTH_FAIL"); break; case SOCKET_SERVER_CONNECT_TO_CLIENT: // Not used in NS tr_debug("SOCKET_SERVER_CONNECT_TO_CLIENT"); break; case SOCKET_TX_FAIL: tr_debug("SOCKET_TX_FAIL"); break; case SOCKET_CONNECT_CLOSED: tr_debug("SOCKET_CONNECT_CLOSED"); socket->event_connnect_closed(sock_cb); break; case SOCKET_CONNECT_FAIL_CLOSED: // Not used in NS tr_debug("SOCKET_CONNECT_FAIL_CLOSED"); break; case SOCKET_NO_ROUTE: tr_debug("SOCKET_NO_ROUTE"); break; case SOCKET_TX_DONE: tr_debug("SOCKET_TX_DONE, %d bytes sent", sock_cb->d_len); socket->event_tx_done(sock_cb); break; default: // SOCKET_NO_RAM, error case for SOCKET_TX_DONE break; } }
bool NanostackSocket::attach(int8_t temp_socket) { nanostack_assert_locked(); if (temp_socket >= NS_INTERFACE_SOCKETS_MAX) { MBED_ASSERT(false); return false; } if (socket_tbl[temp_socket] != NULL) { MBED_ASSERT(false); return false; } socket_id = temp_socket; socket_tbl[socket_id] = this; return true; }
NanostackSocket::~NanostackSocket() { nanostack_assert_locked(); if (mode != SOCKET_MODE_CLOSED) { close(); } if (socket_id >= 0) { int ret = socket_free(socket_id); MBED_ASSERT(0 == ret); MBED_ASSERT(socket_tbl[socket_id] == this); socket_id = -1; data_free_all(); } }
int NanostackSocket::accept(NanostackSocket *accepted_socket, ns_address_t *addr) { nanostack_assert_locked(); MBED_ASSERT(SOCKET_MODE_LISTENING == mode && SOCKET_MODE_UNOPENED == accepted_socket->mode); int temp_socket = socket_accept(socket_id, addr, socket_callback); if (temp_socket < 0) { tr_error("NanostackSocket::accept() failed"); return temp_socket; } if (!accepted_socket->attach(temp_socket)) { return -1; } accepted_socket->mode = SOCKET_MODE_STREAM; return temp_socket; }
void NanostackSocket::close() { nanostack_assert_locked(); MBED_ASSERT(mode != SOCKET_MODE_CLOSED); if (socket_id >= 0) { int ret = socket_close(socket_id, (addr_valid ? &ns_address : NULL)); MBED_ASSERT(0 == ret); } else { MBED_ASSERT(SOCKET_MODE_UNOPENED == mode); } data_free_all(); mode = SOCKET_MODE_CLOSED; signal_event(); }
void NanostackSocket::event_tx_fail(socket_callback_t *sock_cb) { nanostack_assert_locked(); switch (mode) { case SOCKET_MODE_CONNECTING: case SOCKET_MODE_STREAM: // TX_FAIL is fatal for stream sockets close(); break; case SOCKET_MODE_DATAGRAM: // TX_FAIL is non-fatal for datagram sockets break; default: MBED_ASSERT(false); break; } }
void NanostackSocket::close() { nanostack_assert_locked(); MBED_ASSERT(mode != SOCKET_MODE_CLOSED); if (socket_id >= 0) { nsapi_error_t ret = socket_close(socket_id); MBED_ASSERT(0 == ret); MBED_ASSERT(socket_tbl[socket_id] == this); socket_tbl[socket_id] = NULL; socket_id = -1; } else { MBED_ASSERT(SOCKET_MODE_UNOPENED == mode); } mode = SOCKET_MODE_CLOSED; signal_event(); }
void NanostackSocket::data_attach(NanostackBuffer *data_buf) { nanostack_assert_locked(); MBED_ASSERT((SOCKET_MODE_DATAGRAM == mode) || (SOCKET_MODE_STREAM == mode)); // Add to linked list tr_debug("data_attach socket=%p", this); if (NULL == rxBufChain) { rxBufChain = data_buf; } else { NanostackBuffer *buf_tmp = rxBufChain; while (NULL != buf_tmp->next) { buf_tmp = buf_tmp->next; } buf_tmp->next = data_buf; } signal_event(); }
int MeshInterfaceNanostack::actual_connect() { nanostack_assert_locked(); mesh_error_t status = mesh_api->connect(); if (status != MESH_ERROR_NONE) { nanostack_unlock(); return map_mesh_error(status); } // Release mutex before blocking nanostack_unlock(); int32_t count = connect_semaphore.wait(30000); nanostack_lock(); if (count <= 0) { return NSAPI_ERROR_DHCP_FAILURE; // sort of... } return 0; }
bool NanostackSocket::open(void) { nanostack_assert_locked(); MBED_ASSERT(SOCKET_MODE_UNOPENED == mode); int temp_socket = socket_open(proto, 0, socket_callback); if (temp_socket < 0) { tr_error("NanostackSocket::open() failed"); return false; } if (proto == SOCKET_TCP) { /* Receive and send buffers enabled by default */ mode = SOCKET_MODE_OPENED; } else { static const int32_t rcvbuf_size = 2048; socket_setsockopt(temp_socket, SOCKET_SOL_SOCKET, SOCKET_SO_RCVBUF, &rcvbuf_size, sizeof rcvbuf_size); mode = SOCKET_MODE_DATAGRAM; } return attach(temp_socket); }
void NanostackSocket::event_incoming_connection(socket_callback_t *sock_cb) { nanostack_assert_locked(); MBED_ASSERT(mode == SOCKET_MODE_LISTENING); signal_event(); }
void NanostackSocket::event_connect_fail(socket_callback_t *sock_cb) { nanostack_assert_locked(); MBED_ASSERT(mode == SOCKET_MODE_CONNECTING); close(); }