bool EasyCellularConnection::cellular_status(int state, int next_state) { tr_info("cellular_status: %s ==> %s", _cellularConnectionFSM->get_state_string((CellularConnectionFSM::CellularState)state), _cellularConnectionFSM->get_state_string((CellularConnectionFSM::CellularState)next_state)); if (_target_state == state) { tr_info("Target state reached: %s", _cellularConnectionFSM->get_state_string(_target_state)); (void)_cellularSemaphore.release(); return false; // return false -> state machine is halted } return true; }
nsapi_error_t EasyCellularConnection::connect() { nsapi_error_t err = check_connect(); if (err) { return err; } #if USE_APN_LOOKUP if (!_credentials_set) { _target_state = CellularConnectionFSM::STATE_SIM_PIN; err = _cellularConnectionFSM->continue_to_state(_target_state); if (err == NSAPI_ERROR_OK) { int sim_wait = _cellularSemaphore.wait(60 * 1000); // reserve 60 seconds to access to SIM if (sim_wait != 1) { tr_error("NO SIM ACCESS"); err = NSAPI_ERROR_NO_CONNECTION; } else { char imsi[MAX_IMSI_LENGTH + 1]; wait(1); // need to wait to access SIM in some modems err = _cellularConnectionFSM->get_sim()->get_imsi(imsi); if (err == NSAPI_ERROR_OK) { const char *apn_config = apnconfig(imsi); if (apn_config) { const char* apn = _APN_GET(apn_config); const char* uname = _APN_GET(apn_config); const char* pwd = _APN_GET(apn_config); tr_info("Looked up APN %s", apn); err = _cellularConnectionFSM->get_network()->set_credentials(apn, uname, pwd); } } } } if (err) { tr_error("APN lookup failed"); return err; } } #endif // USE_APN_LOOKUP _target_state = CellularConnectionFSM::STATE_CONNECTED; err = _cellularConnectionFSM->continue_to_state(_target_state); if (err == NSAPI_ERROR_OK) { int ret_wait = _cellularSemaphore.wait(10 * 60 * 1000); // cellular network searching may take several minutes if (ret_wait != 1) { tr_info("No cellular connection"); err = NSAPI_ERROR_NO_CONNECTION; } } return err; }
void app_start(int, char**) { srand(time(NULL)); mbed_trace_init(); tr_info("Application start"); tr_info("Set I2C frequency"); i2c.frequency(400000); tr_info("Initialize user interface module"); oled = new Adafruit_SSD1306_I2c(i2c, YOTTA_CFG_HARDWARE_PINS_D2); mcp_keys = new MCP23008(i2c); for(uint8_t i = 0; i < 4; ++i) { mcp_keys->setup(i, MCP23008::IN); mcp_keys->pullup(i, true); } tr_info("Initialize state object"); state = new State(i2c); tr_info("First screen out"); state->startup_phase = State::STARTUP_CONF; scr = new SplashScreen(*oled, *state); scr->render(); tr_info("Load config"); state->config.load(); state->startup_phase = State::STARTUP_NM; scr->render(); tr_info("Start NetworkManager"); wait_ms(100); nm = new NetworkManager(PIN_ESP_TX, PIN_ESP_RX, 9600); state->nm = nm; state->startup_phase = State::STARTUP_FIN; scr->render(); tr_info("Start ultrasonic measuring"); ultrasonic.start_measure(); tr_info("Hook up routine functions"); minar::Scheduler::postCallback(leave_splash).delay(minar::milliseconds(500)); minar::Scheduler::postCallback(poll_key).period(minar::milliseconds(50)); minar::Scheduler::postCallback(screen_render).period(minar::milliseconds(100)); minar::Scheduler::postCallback(read_distance).period(minar::milliseconds(300)); tr_info("Start process completed"); }
int8_t thread_management_set_link_timeout(int8_t interface_id, uint32_t link_timeout) { #ifdef HAVE_THREAD protocol_interface_info_entry_t *cur; cur = protocol_stack_interface_info_get_by_id(interface_id); if (!cur) { tr_warn("Invalid interface id"); return -1; } thread_info_t *thread = cur->thread_info; if (!thread) { tr_warn("Thread not active"); return -2; } tr_info("set new link timeout %"PRIu32" , old value %"PRIu32"", link_timeout, thread->host_link_timeout); thread->host_link_timeout = link_timeout; thread_bootstrap_child_update_trig(cur); return 0; #else (void) interface_id; (void) link_timeout; return -1; #endif }
int fhss_tx_handle_cb(const fhss_api_t *api, bool is_broadcast_addr, uint8_t *destination_address, int frame_type, uint8_t *synch_info, uint16_t frame_length, uint8_t phy_header_length, uint8_t phy_tail_length) { fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); if (!fhss_structure) { return -2; } // TODO: needs some more logic to push buffer back to queue if (frame_type == FHSS_DATA_FRAME) { if (is_broadcast_addr == true) { if (fhss_is_current_channel_broadcast(fhss_structure) == false) { tr_info("Broadcast on UC channel -> Back to queue"); return -3; } } } if (frame_type == FHSS_SYNCH_FRAME) { if (!synch_info) { return -4; } fhss_beacon_build(fhss_structure, synch_info); } else if (fhss_check_tx_allowed(fhss_structure, is_broadcast_addr, frame_length, frame_type, phy_header_length, phy_tail_length) == false) { return -1; } // If sending Beacon request on parents Unicast channel if (frame_type == FHSS_SYNCH_REQUEST_FRAME && fhss_structure->fhss_state == FHSS_SYNCHRONIZED) { fhss_change_to_parent_channel(fhss_structure); } else if (frame_type == FHSS_DATA_FRAME) { fhss_change_to_tx_channel(fhss_structure, destination_address); } return 0; }
void app_start(int, char **) { // set the baud rate for output printing get_stdio_serial().baud(YOTTA_CFG_K64F_BORDER_ROUTER_BAUD); // set heap size and memory error handler for this application ns_dyn_mem_init(app_stack_heap, APP_DEFINED_HEAP_SIZE, app_heap_error_handler, 0); trace_init(); // set up the tracing library set_trace_print_function(trace_printer); set_trace_config(TRACE_MODE_COLOR | TRACE_ACTIVE_LEVEL_DEBUG | TRACE_CARRIAGE_RETURN); const char *mac_src = STR(YOTTA_CFG_K64F_BORDER_ROUTER_BACKHAUL_MAC_SRC); if (strcmp(mac_src, "BOARD") == 0) { /* Setting the MAC Address from UID (A yotta function) * Takes UID Mid low and UID low and shuffles them around. */ mbed_mac_address((char *)mac); } else if (strcmp(mac_src, "CONFIG") == 0) { /* MAC is defined by the user through yotta configuration */ const uint8_t mac48[] = YOTTA_CFG_K64F_BORDER_ROUTER_BACKHAUL_MAC; for (uint32_t i = 0; i < sizeof(mac); ++i) { mac[i] = mac48[i]; } } // run LED toggler in the Minar scheduler minar::Scheduler::postCallback(mbed::util::FunctionPointer0<void> (toggle_led1).bind()).period(minar::milliseconds(500)); tr_info("Starting K64F border router..."); border_router_start(); }
extern "C" void connection_event_handler(arm_event_s *event) { if(!connection_handler){ return; } switch(event->event_type){ case M2MConnectionHandlerPimpl::ESocketReadytoRead: connection_handler->receive_handler(); break; case M2MConnectionHandlerPimpl::ESocketSend: connection_handler->send_socket_data((uint8_t*)event->data_ptr, event->event_data); free(event->data_ptr); break; case M2MConnectionHandlerPimpl::ESocketDnsHandler: connection_handler->dns_handler(); break; default: tr_info("connection_event_handler: default type: %d", (int)event->event_type); break; } }
int fhss_change_to_parent_channel(fhss_structure_t *fhss_structure) { uint8_t uc_index; uint8_t destination_channel; uint8_t destination_offset; if (fhss_structure) { if (fhss_structure->number_of_channels != fhss_structure->bs->synch_configuration.fhss_number_of_bc_channels) { uint8_t parent_address[8]; if (fhss_get_parent_address(fhss_structure, parent_address)) { return -1; } destination_offset = fhss_get_offset(fhss_structure, parent_address); uc_index = fhss_calculate_uc_index(fhss_structure->bs->current_channel_index, fhss_structure->number_of_channels, fhss_structure->bs->synch_configuration.fhss_number_of_bc_channels) + destination_offset; if (uc_index >= (fhss_structure->number_of_channels - fhss_structure->bs->synch_configuration.fhss_number_of_bc_channels)) { uc_index -= (fhss_structure->number_of_channels - fhss_structure->bs->synch_configuration.fhss_number_of_bc_channels); } uc_index = fhss_calc_channel_shuffle(uc_index, fhss_structure->number_of_channels, fhss_structure->bs->synch_configuration.fhss_number_of_bc_channels); uc_index = fhss_add_channel_list_counter(uc_index, fhss_structure->number_of_channels, fhss_structure->bs->channel_list_counter, fhss_structure->bs->fhss_scramble_table); destination_channel = channel_list_get_channel(fhss_structure->bs->fhss_configuration.channel_mask, uc_index); fhss_structure->callbacks.change_channel(fhss_structure->fhss_api, destination_channel); #ifdef FHSS_CHANNEL_DEBUG tr_info("Parent channel: %u", destination_channel); #endif /*FHSS_CHANNEL_DEBUG*/ } } return 0; }
static void CMTI_URC(ATCmdParser *at) { // our CMGF = 1, i.e., text mode. So we expect response in this format: //+CMTI: <mem>,<index>, at->recv(": %*u,%*u"); tr_info("New SMS received"); }
/** * \brief Initializes the SLIP MAC backhaul driver. * This function is called by the border router module. */ void backhaul_driver_init(void (*backhaul_driver_status_cb)(uint8_t, int8_t)) { const char *driver; #ifndef MBED_CONF_RTOS_PRESENT driver = STR(YOTTA_CFG_K64F_BORDER_ROUTER_BACKHAUL_DRIVER); #else driver = STR(MBED_CONF_APP_BACKHAUL_DRIVER); #endif if (strcmp(driver, "SLIP") == 0) { int8_t slipdrv_id; #if defined(MBED_CONF_APP_SLIP_HW_FLOW_CONTROL) || defined(YOTTA_CFG_K64F_BORDER_ROUTER_SLIP_HW_FLOW_CONTROL) pslipmacdriver = new SlipMACDriver(SERIAL_TX, SERIAL_RX, SERIAL_RTS, SERIAL_CTS); #else pslipmacdriver = new SlipMACDriver(SERIAL_TX, SERIAL_RX); #endif if (pslipmacdriver == NULL) { tr_error("Unable to create SLIP driver"); return; } tr_info("Using SLIP backhaul driver..."); #ifndef MBED_CONF_RTOS_PRESENT slipdrv_id = pslipmacdriver->Slip_Init(mac, YOTTA_CFG_K64F_BORDER_ROUTER_BACKHAUL_SERIAL_BAUD); #else slipdrv_id = pslipmacdriver->Slip_Init(mac, MBED_CONF_APP_SLIP_SERIAL_BAUD_RATE); #endif if (slipdrv_id >= 0) { backhaul_driver_status_cb(1, slipdrv_id); return; } tr_error("Backhaul driver init failed, retval = %d", slipdrv_id); } else if (strcmp(driver, "ETH") == 0) { tr_info("Using ETH backhaul driver..."); arm_eth_phy_device_register(mac, backhaul_driver_status_cb); return; } tr_error("Unsupported backhaul driver: %s", driver); }
/* * \brief Configure mesh network * */ void thread_tasklet_configure_and_connect_to_network(void) { int8_t status; link_configuration_s* temp_link_config=NULL; if (MBED_CONF_MBED_MESH_API_THREAD_DEVICE_TYPE == MESH_DEVICE_TYPE_THREAD_MINIMAL_END_DEVICE) { thread_tasklet_data_ptr->operating_mode = NET_6LOWPAN_HOST; } else if (MBED_CONF_MBED_MESH_API_THREAD_DEVICE_TYPE == MESH_DEVICE_TYPE_THREAD_SLEEPY_END_DEVICE) { thread_tasklet_data_ptr->operating_mode = NET_6LOWPAN_SLEEPY_HOST; } else { thread_tasklet_data_ptr->operating_mode = NET_6LOWPAN_ROUTER; } arm_nwk_interface_configure_6lowpan_bootstrap_set( thread_tasklet_data_ptr->nwk_if_id, thread_tasklet_data_ptr->operating_mode, NET_6LOWPAN_THREAD); thread_tasklet_data_ptr->channel_list.channel_page = (channel_page_e)MBED_CONF_MBED_MESH_API_THREAD_CONFIG_CHANNEL_PAGE; thread_tasklet_data_ptr->channel_list.channel_mask[0] = MBED_CONF_MBED_MESH_API_THREAD_CONFIG_CHANNEL_MASK; TRACE_DETAIL("channel page: %d", thread_tasklet_data_ptr->channel_list.channel_page); TRACE_DETAIL("channel mask: 0x%.8lx", thread_tasklet_data_ptr->channel_list.channel_mask[0]); // PSKd const char PSKd[] = MBED_CONF_MBED_MESH_API_THREAD_PSKD; MBED_ASSERT(sizeof(PSKd) > 5 && sizeof(PSKd) < 33); char *dyn_buf = ns_dyn_mem_alloc(sizeof(PSKd)); strcpy(dyn_buf, PSKd); ns_dyn_mem_free(device_configuration.PSKd_ptr); device_configuration.PSKd_ptr = (uint8_t*)dyn_buf; device_configuration.PSKd_len = sizeof(PSKd) - 1; if (true == MBED_CONF_MBED_MESH_API_THREAD_USE_STATIC_LINK_CONFIG) { read_link_configuration(); temp_link_config = &thread_tasklet_data_ptr->link_config; } thread_management_node_init(thread_tasklet_data_ptr->nwk_if_id, &thread_tasklet_data_ptr->channel_list, &device_configuration, temp_link_config); status = arm_nwk_interface_up(thread_tasklet_data_ptr->nwk_if_id); if (status >= 0) { thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_STARTED; tr_info("Start Thread bootstrap (%s mode)", thread_tasklet_data_ptr->operating_mode == NET_6LOWPAN_SLEEPY_HOST ? "SED" : "Router"); } else { thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; tr_err("Bootstrap start failed, %d", status); thread_tasklet_network_state_changed(MESH_BOOTSTRAP_START_FAILED); } }
/* Process tids requests forever. Should not return except on error. */ int tids_start(TIDS_INSTANCE *tids, TIDS_REQ_FUNC *req_handler, tids_auth_func *auth_handler, const char *hostname, int port, void *cookie) { int fd[TR_MAX_SOCKETS]={0}; nfds_t n_fd=0; struct pollfd poll_fd[TR_MAX_SOCKETS]={{0}}; int ii=0; n_fd = tids_get_listener(tids, req_handler, auth_handler, hostname, port, cookie, fd, TR_MAX_SOCKETS); if (n_fd <= 0) { perror ("Error from tids_listen()"); return 1; } tr_info("Trust Path Query Server starting on host %s:%d.", hostname, port); /* set up the poll structs */ for (ii=0; ii<n_fd; ii++) { poll_fd[ii].fd=fd[ii]; poll_fd[ii].events=POLLIN; } while(1) { /* accept incoming conns until we are stopped */ /* clear out events from previous iteration */ for (ii=0; ii<n_fd; ii++) poll_fd[ii].revents=0; /* wait indefinitely for a connection */ if (poll(poll_fd, n_fd, -1) < 0) { perror("Error from poll()"); return 1; } /* fork handlers for any sockets that have data */ for (ii=0; ii<n_fd; ii++) { if (poll_fd[ii].revents == 0) continue; if ((poll_fd[ii].revents & POLLERR) || (poll_fd[ii].revents & POLLNVAL)) { perror("Error polling fd"); continue; } if (poll_fd[ii].revents & POLLIN) { if (tids_accept(tids, poll_fd[ii].fd)) tr_debug("tids_start: error in tids_accept()."); } } } return 1; /* should never get here, loops "forever" */ }
/** * \brief Network state event handler. * \param event show network start response or current network state. * * - ARM_NWK_BOOTSTRAP_READY: Save NVK persistent data to NVM and Net role * - ARM_NWK_NWK_SCAN_FAIL: Link Layer Active Scan Fail, Stack is Already at Idle state * - ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL: No ND Router at current Channel Stack is Already at Idle state * - ARM_NWK_NWK_CONNECTION_DOWN: Connection to Access point is lost wait for Scan Result * - ARM_NWK_NWK_PARENT_POLL_FAIL: Host should run net start without any PAN-id filter and all channels * - ARM_NWK_AUHTENTICATION_FAIL: Pana Authentication fail, Stack is Already at Idle state */ void nd_tasklet_parse_network_event(arm_event_s *event) { arm_nwk_interface_status_type_e status = (arm_nwk_interface_status_type_e) event->event_data; tr_debug("app_parse_network_event() %d", status); switch (status) { case ARM_NWK_BOOTSTRAP_READY: /* Network is ready and node is connected to Access Point */ if (tasklet_data_ptr->tasklet_state != TASKLET_STATE_BOOTSTRAP_READY) { tr_info("6LoWPAN ND bootstrap ready"); tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_READY; nd_tasklet_trace_bootstrap_info(); nd_tasklet_network_state_changed(MESH_CONNECTED); } break; case ARM_NWK_NWK_SCAN_FAIL: /* Link Layer Active Scan Fail, Stack is Already at Idle state */ tr_debug("Link Layer Scan Fail: No Beacons"); tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; nd_tasklet_network_state_changed(MESH_DISCONNECTED); break; case ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL: /* No ND Router at current Channel Stack is Already at Idle state */ tr_debug("ND Scan/ GP REG fail"); tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; nd_tasklet_network_state_changed(MESH_DISCONNECTED); break; case ARM_NWK_NWK_CONNECTION_DOWN: /* Connection to Access point is lost wait for Scan Result */ tr_debug("ND/RPL scan new network"); tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; nd_tasklet_network_state_changed(MESH_DISCONNECTED); break; case ARM_NWK_NWK_PARENT_POLL_FAIL: tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; nd_tasklet_network_state_changed(MESH_DISCONNECTED); break; case ARM_NWK_AUHTENTICATION_FAIL: tr_debug("Network authentication fail"); tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; nd_tasklet_network_state_changed(MESH_DISCONNECTED); break; default: tr_warn("Unknown event %d", status); break; } if (tasklet_data_ptr->tasklet_state != TASKLET_STATE_BOOTSTRAP_READY && tasklet_data_ptr->network_interface_id != INVALID_INTERFACE_ID) { // Set 5s timer for new network scan eventOS_event_timer_request(TIMER_EVENT_START_BOOTSTRAP, ARM_LIB_SYSTEM_TIMER_EVENT, tasklet_data_ptr->tasklet, 5000); } }
/** * Update channel * * This function is called by superframe handler on first(0) superframe * of every channel to resolve and change new channel. * * @param cur network interface to work on * @return true if changed to broadcast channel, false otherwise */ bool fhss_change_to_next_channel(fhss_structure_t *fhss_structure) { int next_channel; bool broadcast_channel = false; uint16_t number_of_channels = fhss_structure->number_of_channels; uint8_t number_of_broadcast_channels = fhss_structure->bs->synch_configuration.fhss_number_of_bc_channels; uint8_t unicast_channel_index = fhss_structure->bs->uc_channel_index; uint8_t channel_index_tmp; /* Get the channel number using channel index. Latter (number_of_broadcast_channels) indexes in channel table are broadcast channels and * first (number_of_channels - number_of_broadcast_channels) are unicast channels. * In channel hopping sequence, every (number_of_channels / number_of_broadcast_channels) channel is broadcast channel and * channel hopping sequence is e.g. |uc0|uc1|uc2|bc0|uc3|uc4|uc5|bc1|uc6|... */ /* Get broadcast channel */ if (fhss_is_current_channel_broadcast(fhss_structure) == true) { channel_index_tmp = fhss_calc_channel_shuffle((number_of_channels - number_of_broadcast_channels) + fhss_get_bc_index(fhss_structure), fhss_structure->number_of_channels, fhss_structure->bs->synch_configuration.fhss_number_of_bc_channels); fhss_generate_broadcast_start_superframe(fhss_structure); broadcast_channel = true; } else { /* Get unicast channel */ channel_index_tmp = fhss_calc_channel_shuffle(unicast_channel_index, fhss_structure->number_of_channels, fhss_structure->bs->synch_configuration.fhss_number_of_bc_channels); if (++fhss_structure->bs->uc_channel_index >= number_of_channels - number_of_broadcast_channels) { fhss_structure->bs->uc_channel_index = 0; } } // Reset Beacon received flag when channel has changed fhss_structure->bs->beacon_received_on_this_bc_channel = false; channel_index_tmp = fhss_add_channel_list_counter(channel_index_tmp, fhss_structure->number_of_channels, fhss_structure->bs->channel_list_counter, fhss_structure->bs->fhss_scramble_table); next_channel = channel_list_get_channel(fhss_structure->bs->fhss_configuration.channel_mask, channel_index_tmp); fhss_structure->rx_channel = next_channel; #ifdef FHSS_CHANNEL_DEBUG if (fhss_is_current_channel_broadcast(fhss_structure) == true) { tr_info("%"PRIu32" BC %u", fhss_structure->platform_functions.fhss_get_timestamp(fhss_structure->fhss_api), next_channel); } else { tr_info("%"PRIu32" UC %u", fhss_structure->platform_functions.fhss_get_timestamp(fhss_structure->fhss_api), next_channel); } #endif /*FHSS_CHANNEL_DEBUG*/ fhss_structure->callbacks.change_channel(fhss_structure->fhss_api, next_channel); return broadcast_channel; }
EasyCellularConnection::EasyCellularConnection(bool debug) : _is_connected(false), _is_initialized(false), _target_state(CellularConnectionFSM::STATE_POWER_ON), _cellularSerial( MDMTXD, MDMRXD, MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE), _cellularSemaphore(0), _cellularConnectionFSM(0), _credentials_err( NSAPI_ERROR_OK), _status_cb(0) { tr_info("EasyCellularConnection()"); #if USE_APN_LOOKUP _credentials_set = false; #endif // #if USE_APN_LOOKUP modem_debug_on(debug); }
/* * \brief Configure and establish network connection * */ void nd_tasklet_configure_and_connect_to_network(void) { int8_t status; char *sec_mode; // configure bootstrap arm_nwk_interface_configure_6lowpan_bootstrap_set( tasklet_data_ptr->network_interface_id, tasklet_data_ptr->mode, NET_6LOWPAN_ND_WITH_MLE); sec_mode = STR(MBED_MESH_API_6LOWPAN_ND_SECURITY_MODE); if (strcmp(sec_mode, "PSK") == 0) { tr_debug("Using PSK security mode."); tasklet_data_ptr->sec_mode = NET_SEC_MODE_PSK_LINK_SECURITY; tasklet_data_ptr->psk_sec_info.key_id = MBED_MESH_API_6LOWPAN_ND_PSK_KEY_ID; memcpy(tasklet_data_ptr->psk_sec_info.security_key, (const uint8_t[16])MBED_MESH_API_6LOWPAN_ND_PSK_KEY, 16); } else { tr_debug("Link-layer security NOT enabled."); tasklet_data_ptr->sec_mode = NET_SEC_MODE_NO_LINK_SECURITY; } // configure link layer security arm_nwk_link_layer_security_mode( tasklet_data_ptr->network_interface_id, tasklet_data_ptr->sec_mode, MBED_MESH_API_6LOWPAN_ND_SEC_LEVEL, &tasklet_data_ptr->psk_sec_info); // configure scan parameters arm_nwk_6lowpan_link_scan_parameter_set(tasklet_data_ptr->network_interface_id, 5); // configure scan channels initialize_channel_list(); // Configure scan options (NULL disables filter) arm_nwk_6lowpan_link_nwk_id_filter_for_nwk_scan( tasklet_data_ptr->network_interface_id, NULL); arm_nwk_6lowpan_link_panid_filter_for_nwk_scan( tasklet_data_ptr->network_interface_id, MBED_MESH_API_6LOWPAN_ND_PANID_FILTER); status = arm_nwk_interface_up(tasklet_data_ptr->network_interface_id); if (status >= 0) { tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_STARTED; tr_info("Start 6LoWPAN ND Bootstrap"); } else { tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; tr_err("Bootstrap start failed, %d", status); nd_tasklet_network_state_changed(MESH_BOOTSTRAP_START_FAILED); } }
/** * Powers up the modem * * Enables the GPIO lines to the modem and then wriggles the power line in short pulses. */ bool PPPCellularInterface::power_up() { /* Initialize GPIO lines */ modem_init(); /* Give modem a little time to settle down */ wait(0.25); bool success = false; int retry_count = 0; while (true) { modem_power_up(); /* Modem tends to spit out noise during power up - don't confuse the parser */ _at->flush(); /* It is mandatory to avoid sending data to the serial port during the first 200 ms * of the module startup. Telit_xE910 Global form factor App note. * Not necessary for all types of modems however. Let's wait just to be on the safe side */ wait_ms(200); _at->set_timeout(1000); if (_at->send("AT") && _at->recv("OK")) { tr_info("Modem Ready."); break; } if (++retry_count > 10) { goto failure; } } _at->set_timeout(8000); /*For more details regarding DCD and DTR circuitry, please refer to Modem AT manual */ success = _at->send("AT" "E0;" //turn off modem echoing "+CMEE=2;"//turn on verbose responses "&K0"//turn off RTC/CTS handshaking "+IPR=115200;"//setup baud rate "&C1;"//set DCD circuit(109), changes in accordance with the carrier detect status "&D0")//set DTR circuit, we ignore the state change of DTR && _at->recv("OK"); if (!success) { goto failure; } /* If everything alright, return from here with success*/ return success; failure: tr_error("Preliminary modem setup failed."); return false; }
/* * \brief A function which will be eventually called by NanoStack OS when ever the OS has an event to deliver. * @param event, describes the sender, receiver and event type. * * NOTE: Interrupts requested by HW are possible during this function! */ void thread_tasklet_main(arm_event_s *event) { arm_library_event_type_e event_type; event_type = (arm_library_event_type_e) event->event_type; switch (event_type) { case ARM_LIB_NWK_INTERFACE_EVENT: /* This event is delivered every and each time when there is new * information of network connectivity. */ thread_tasklet_parse_network_event(event); break; case ARM_LIB_TASKLET_INIT_EVENT: /* Event with type EV_INIT is an initializer event of NanoStack OS. * The event is delivered when the NanoStack OS is running fine. * This event should be delivered ONLY ONCE. */ mesh_system_send_connect_event(thread_tasklet_data_ptr->tasklet); break; case ARM_LIB_SYSTEM_TIMER_EVENT: eventOS_event_timer_cancel(event->event_id, thread_tasklet_data_ptr->tasklet); if (event->event_id == TIMER_EVENT_START_BOOTSTRAP) { int8_t status; tr_debug("Restart bootstrap"); status = arm_nwk_interface_up(thread_tasklet_data_ptr->nwk_if_id); if (status >= 0) { thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_STARTED; tr_info("Start Thread bootstrap (%s mode)", thread_tasklet_data_ptr->operating_mode == NET_6LOWPAN_SLEEPY_HOST ? "SED" : "Router"); thread_tasklet_network_state_changed(MESH_BOOTSTRAP_STARTED); } else { thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; tr_err("Bootstrap start failed, %d", status); thread_tasklet_network_state_changed(MESH_BOOTSTRAP_START_FAILED); } } break; case APPLICATION_EVENT: if (event->event_id == APPL_EVENT_CONNECT) { thread_tasklet_configure_and_connect_to_network(); } break; default: break; } // switch(event_type) }
int fhss_change_to_tx_channel(fhss_structure_t *fhss_structure, uint8_t *destination_address) { if (fhss_structure) { if (fhss_structure->fhss_state != FHSS_UNSYNCHRONIZED) { uint8_t destination_channel = fhss_get_destination_channel(fhss_structure, destination_address); fhss_structure->callbacks.change_channel(fhss_structure->fhss_api, destination_channel); #ifdef FHSS_CHANNEL_DEBUG tr_info("TX channel: %u", destination_channel); #endif /*FHSS_CHANNEL_DEBUG*/ } } return 0; }
static void CMT_URC(ATCmdParser *at) { // our CMGF = 1, i.e., text mode. So we expect response in this format: //+CMT: <oa>,[<alpha>],<scts>[,<tooa>, //<fo>,<pid>,<dcs>,<sca>,<tosca>, //<length>]<CR><LF><data> // By default detailed SMS header CSDH=0 , so we are not expecting [,<tooa>, //<fo>,<pid>,<dcs>,<sca>,<tosca> char sms[50]; char service_timestamp[15]; at->recv(": %49[^\"]\",,%14[^\"]\"\n", sms, service_timestamp); tr_info("SMS:%s, %s", service_timestamp, sms); }
static void thread_parse_annoucement(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg) { uint64_t timestamp; uint16_t panid; uint8_t *ptr; uint8_t channel_page; uint16_t channel; link_configuration_s *linkConfiguration = thread_joiner_application_get_config(cur->id); tr_info("Recv Dataset Announce"); if (8 > thread_tmfcop_tlv_data_get_uint64(mle_msg->data_ptr, mle_msg->data_length,MLE_TYPE_ACTIVE_TIMESTAMP,×tamp)) { tr_error("Missing timestamp TLV"); return; } if (2 > thread_tmfcop_tlv_data_get_uint16(mle_msg->data_ptr, mle_msg->data_length,MLE_TYPE_PANID,&panid)) { tr_error("Missing Panid TLV"); return; } if (3 > thread_tmfcop_tlv_find(mle_msg->data_ptr, mle_msg->data_length,MLE_TYPE_CHANNEL,&ptr)) { tr_error("Missing Channel TLV"); return; } channel_page = ptr[0]; channel = common_read_16_bit(&ptr[1]); if (linkConfiguration->timestamp == timestamp) { // We received same timestamp tr_debug("Same timestamp"); return; } if (cur->thread_info->announcement_info && cur->thread_info->announcement_info->timestamp == timestamp){ // We received same timestamp again tr_debug("Processing announce with same timestamp"); return; } if (linkConfiguration->timestamp > timestamp) { // We received older time stamp we just announce back to originator channel thread_bootstrap_announce_send(cur, linkConfiguration->channel_page, linkConfiguration->rfChannel, linkConfiguration->panId, linkConfiguration->timestamp, channel); return; } tr_debug("New configuration received"); thread_bootstrap_temporary_attach(cur,channel_page, channel, panid, timestamp); }
/* Get a listener for tids requests, returns its socket fd. Accept * connections with tids_accept() */ nfds_t tids_get_listener(TIDS_INSTANCE *tids, TIDS_REQ_FUNC *req_handler, tids_auth_func *auth_handler, const char *hostname, int port, void *cookie, int *fd_out, size_t max_fd) { nfds_t n_fd = 0; nfds_t ii = 0; tids->tids_port = port; n_fd = tr_sock_listen_all(port, fd_out, max_fd); if (n_fd == 0) tr_err("tids_get_listener: Error opening port %d", port); else { /* opening port succeeded */ tr_info("tids_get_listener: Opened port %d.", port); /* make this socket non-blocking */ for (ii=0; ii<n_fd; ii++) { if (0 != fcntl(fd_out[ii], F_SETFL, O_NONBLOCK)) { tr_err("tids_get_listener: Error setting O_NONBLOCK."); for (ii=0; ii<n_fd; ii++) { close(fd_out[ii]); fd_out[ii]=-1; } n_fd = 0; break; } } } if (n_fd > 0) { /* store the caller's request handler & cookie */ tids->req_handler = req_handler; tids->auth_handler = auth_handler; tids->hostname = hostname; tids->cookie = cookie; } return (int)n_fd; }
/* Accept and process a connection on a port opened with tids_get_listener() */ int tids_accept(TIDS_INSTANCE *tids, int listen) { int conn=-1; int pid=-1; int pipe_fd[2]; struct tid_process tp = {0}; if (0 > (conn = tr_sock_accept(listen))) { tr_debug("tids_accept: Error accepting connection"); return 1; } if (0 > pipe(pipe_fd)) { perror("Error on pipe()"); return 1; } /* pipe_fd[0] is for reading, pipe_fd[1] is for writing */ if (0 > (pid = fork())) { perror("Error on fork()"); return 1; } if (pid == 0) { /* Only the child process gets here */ close(pipe_fd[0]); /* close the read end of the pipe, the child only writes */ close(listen); /* close the child process's handle on the listen port */ tids_handle_proc(tids, conn, pipe_fd[1]); /* never returns */ } /* Only the parent process gets here */ close(pipe_fd[1]); /* close the write end of the pipe, the parent only listens */ close(conn); /* connection belongs to the child, so close parent's handle */ /* remember the PID of our child process */ tr_info("tids_accept: Spawned TID process %d to handle incoming connection.", pid); tp.pid = pid; tp.read_fd = pipe_fd[0]; g_array_append_val(tids->pids, tp); /* clean up any processes that have completed */ tids_sweep_procs(tids); return 0; }
void mesh_network_callback(mesh_connection_status_t mesh_state) { tr_info("Network established"); mesh_network_state = mesh_state; }
nsapi_error_t PPPCellularInterface::connect() { nsapi_error_t retcode; bool success; bool did_init = false; const char *apn_config = NULL; if (dev_info.ppp_connection_up) { return NSAPI_ERROR_IS_CONNECTED; } do { retry_init: /* setup AT parser */ setup_at_parser(); if (!initialized) { /* If we have hangup (eg DCD) detection, we don't want it active * as long as we are using ATCmdParser. * As soon as we get into data mode, we will turn it back on. */ enable_hup(false); if (!power_up()) { return NSAPI_ERROR_DEVICE_ERROR; } retcode = initialize_sim_card(); if (retcode != NSAPI_ERROR_OK) { return retcode; } success = nwk_registration(PACKET_SWITCHED) //perform network registration && get_CCID(_at)//get integrated circuit ID of the SIM && get_IMSI(_at)//get international mobile subscriber information && get_IMEI(_at)//get international mobile equipment identifier && get_MEID(_at)//its same as IMEI && set_CMGF(_at)//set message format for SMS && set_CNMI(_at);//set new SMS indication if (!success) { return NSAPI_ERROR_NO_CONNECTION; } #if MBED_CONF_PPP_CELL_IFACE_APN_LOOKUP if (!apn_config) { apn_config = apnconfig(dev_info.imsi); } #endif /* Check if user want skip SIM pin checking on boot up */ if (set_sim_pin_check_request) { retcode = do_sim_pin_check(_at, _pin); if (retcode != NSAPI_ERROR_OK) { return retcode; } /* set this request to false, as it is unnecessary to repeat in case of retry */ set_sim_pin_check_request = false; } /* check if the user requested a sim pin change */ if (change_pin) { retcode = do_change_sim_pin(_at, _pin, _new_pin); if (retcode != NSAPI_ERROR_OK) { return retcode; } /* set this request to false, as it is unnecessary to repeat in case of retry */ change_pin = false; } #if MBED_CONF_PPP_CELL_IFACE_APN_LOOKUP if (apn_config) { _apn = _APN_GET(apn_config); _uname = _APN_GET(apn_config); _pwd = _APN_GET(apn_config); tr_info("Looked up APN %s.", _apn); } #endif //sets up APN and IP protocol for external PDP context retcode = setup_context_and_credentials(); if (retcode != NSAPI_ERROR_OK) { return retcode; } if (!success) { shutdown_at_parser(); return NSAPI_ERROR_NO_CONNECTION; } initialized = true; did_init = true; } else { /* If we were already initialized, we expect to receive NO_CARRIER response * from the modem as we were kicked out of Data mode */ _at->recv("NO CARRIER"); success = _at->send("AT") && _at->recv("OK"); } /* Attempt to enter data mode */ success = set_atd(_at); //enter into Data mode with the modem if (!success) { power_down(); initialized = false; /* if we were previously initialized , i.e., not in this particular attempt, * we want to re-initialize */ if (!did_init) { goto retry_init; } /* shutdown AT parser before notifying application of the failure */ shutdown_at_parser(); return NSAPI_ERROR_NO_CONNECTION; } /* This is the success case. * Save RAM, discard AT Parser as we have entered Data mode. */ shutdown_at_parser(); /* We now want hangup (e.g., DCD) detection if available */ enable_hup(true); /* Initialize PPP * mbed_ppp_init() is a blocking call, it will block until * connected, or timeout after 30 seconds*/ retcode = nsapi_ppp_connect(_fh, _connection_status_cb, _uname, _pwd, _stack); if (retcode == NSAPI_ERROR_OK) { dev_info.ppp_connection_up = true; } }while(!dev_info.ppp_connection_up && apn_config && *apn_config); return retcode; }
/* * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Option Type | Opt Data Len | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |O|R|F|0|0|0|0|0| RPLInstanceID | SenderRank | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | (sub-TLVs) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * Figure 1: RPL Option */ static buffer_t *rpl_data_exthdr_provider_hbh_2(buffer_t *buf, rpl_instance_t *instance, rpl_neighbour_t *neighbour, ipv6_exthdr_stage_t stage, int16_t *result) { ipv6_route_info_t *route_info = &buf->route->route_info; /* This can be called both for routes which only use HbH headers (eg DIO) * as well as one-hop DAO_SR routes which would normally use source routing * headers, if there was more than one hop. For DAO_SR, neighbour will be * NULL. */ rpl_dodag_t *dodag = rpl_instance_current_dodag(instance); if (!dodag) { *result = -1; return buf; } bool destination_in_instance = false; uint16_t ext_size = 0; if (addr_ipv6_equal(route_info->next_hop_addr, buf->dst_sa.address) || addr_ipv6_equal(buf->dst_sa.address, dodag->id)) { destination_in_instance = true; if (buf->rpl_option) { /* Forwarding an existing option - preserve it */ uint8_t opt_size = buf->rpl_option[0]; ext_size = 2 + opt_size; ext_size = (ext_size + 7) &~ 7; } else { /* Generating our own option - fixed size, no TLVs */ ext_size = 8; } } switch (stage) { case IPV6_EXTHDR_SIZE: *result = ext_size; return buf; case IPV6_EXTHDR_INSERT: { if (!destination_in_instance) { /* We don't add a header - we'll do it on the tunnel */ *result = 0; return buf; } buf = buffer_headroom(buf, ext_size); if (!buf) { return NULL; } uint8_t *ext = buffer_data_reserve_header(buf, ext_size); ext[0] = buf->options.type; buf->options.type = IPV6_NH_HOP_BY_HOP; ext[1] = ext_size / 8 - 1; uint8_t *opt = ext + 2; opt[0] = IPV6_OPTION_RPL; if (buf->rpl_option) { /* Get back the RPL option we stripped off an outer IP header */ memcpy(opt + 1, buf->rpl_option, 1 + buf->rpl_option[0]); ns_dyn_mem_free(buf->rpl_option); buf->rpl_option = NULL; } else { opt[1] = 4; // option length opt[2] = 0; // placeholder opt[3] = instance->id; /* For upwards routes we can deduce that DODAGID must be * the destination, so set the D flag. */ if (rpl_instance_id_is_local(instance->id) && !rpl_data_is_rpl_downward_route(route_info->source)) { opt[3] |= RPL_INSTANCE_DEST; } common_write_16_bit(RPL_RANK_INFINITE, opt + 4); // SenderRank (placeholder) } /* Pad HbH header if necessary. */ uint8_t pad_len = ext + ext_size - (opt + 2 + opt[1]); if (pad_len == 1) { opt[0] = IPV6_OPTION_PAD1; } else if (pad_len > 1) { opt[0] = IPV6_OPTION_PADN; opt[1] = pad_len - 2; memset(opt + 2, 0, pad_len - 2); } // don't forget to set the "RPL option present" marker buf->options.ip_extflags |= IPEXT_HBH_RPL; *result = 0; return buf; } case IPV6_EXTHDR_MODIFY: { uint8_t *opt; uint16_t sender_rank; rpl_data_locate_info(buf, &opt, NULL); if (!opt) { *result = IPV6_EXTHDR_MODIFY_TUNNEL; // Tunnel to next hop in general case, but if going to DODAGID, // it can tunnel all the way (and it HAS to if it is a local // DODAG). if (!addr_ipv6_equal(buf->dst_sa.address, dodag->id)) { memcpy(buf->dst_sa.address, route_info->next_hop_addr, 16); } buf->src_sa.addr_type = ADDR_NONE; // force auto-selection return buf; } if (buf->ip_routed_up) { /* Check for rank errors - RFC 6550 11.2.2.2. */ /* Note that RPL spec does not say that packets from nodes of * equal rank are errors, but we treat them as such to get * reliable sibling loop detection - we require sender rank to be * strictly less for Down packets and strictly greater for Up. */ sender_rank = common_read_16_bit(opt + 4); rpl_cmp_t cmp = rpl_rank_compare_dagrank_rank(dodag, sender_rank, instance->current_rank); rpl_cmp_t expected_cmp = (opt[2] & RPL_OPT_DOWN) ? RPL_CMP_LESS : RPL_CMP_GREATER; if (cmp != expected_cmp) { /* Set the Rank-Error bit; if already set, drop */ if (opt[2] & RPL_OPT_RANK_ERROR) { protocol_stats_update(STATS_RPL_ROUTELOOP, 1); tr_info("Forwarding inconsistency R"); rpl_instance_inconsistency(instance); *result = -1; return buf; } else { opt[2] |= RPL_OPT_RANK_ERROR; } } } if (buf->rpl_flag_error & RPL_OPT_FWD_ERROR) { opt[2] |= RPL_OPT_FWD_ERROR; } else if (rpl_data_is_rpl_downward_route(route_info->source)) { opt[2] |= RPL_OPT_DOWN; } else { opt[2] &= ~RPL_OPT_DOWN; } /* Set the D flag for local instances */ if (rpl_instance_id_is_local(instance->id)) { if (addr_ipv6_equal(dodag->id, buf->dst_sa.address)) { opt[3] |= RPL_INSTANCE_DEST; } else if (addr_ipv6_equal(dodag->id, buf->src_sa.address)) { opt[3] &=~ RPL_INSTANCE_DEST; } else { tr_error("Local instance invalid %s[%d]: %s -> %s", trace_ipv6(dodag->id), instance->id, trace_ipv6(buf->src_sa.address), trace_ipv6(buf->dst_sa.address)); *result = -1; return buf; } } /* RPL 11.2.2.2. says we set SenderRank to infinite when forwarding * across a version discontinuity. (Must be up - we don't know versions * of downward routes). */ if ((buf->rpl_flag_error & RPL_OPT_FWD_ERROR) || rpl_data_is_rpl_downward_route(route_info->source) || !neighbour || neighbour->dodag_version == instance->current_dodag_version) { sender_rank = nrpl_dag_rank(dodag, instance->current_rank); } else { sender_rank = RPL_RANK_INFINITE; } common_write_16_bit(sender_rank, opt + 4); *result = 0; return buf; } default: return buffer_free(buf); } }
/** * Clean up any finished TID request processes * * This is called by the main process after forking each TID request. If you want to be * sure finished processes are cleaned up promptly even during a lull in TID requests, * this can be called from the main thread of the main process. It is not thread-safe, * so should not be used from sub-threads. It should not be called by child processes - * this would probably be harmless but ineffective. * * @param tids */ void tids_sweep_procs(TIDS_INSTANCE *tids) { guint ii; struct tid_process tp = {0}; char result[TIDS_MAX_MESSAGE_LEN] = {0}; ssize_t result_len; int status; int wait_rc; /* loop backwards over the array so we can remove elements as we go */ for (ii=tids->pids->len; ii > 0; ii--) { /* ii-1 is the current index - get our own copy, we may destroy the list's copy */ tp = g_array_index(tids->pids, struct tid_process, ii-1); wait_rc = waitpid(tp.pid, &status, WNOHANG); if (wait_rc == 0) continue; /* process still running */ if (wait_rc < 0) { /* invalid options will probably keep being invalid, report that condition */ if(errno == EINVAL) tr_crit("tids_sweep_procs: waitpid called with invalid options"); /* If we got ECHILD, that means the PID was invalid; we'll assume the process was * terminated and we missed it. For all other errors, move on * to the next PID to check. */ if (errno != ECHILD) continue; tr_warning("tid_sweep_procs: TID process %d disappeared", tp.pid); } /* remove the item (we still have a copy of the data) */ g_array_remove_index_fast(tids->pids, ii-1); /* disturbs only indices >= ii-1 which we've already handled */ /* Report exit status unless we got ECHILD above or somehow waitpid returned the wrong pid */ if (wait_rc == tp.pid) { if (WIFEXITED(status)) { tr_debug("tids_sweep_procs: TID process %d exited with status %d.", tp.pid, WTERMSIG(status)); } else if (WIFSIGNALED(status)) { tr_debug("tids_sweep_procs: TID process %d terminated by signal %d.", tp.pid, WTERMSIG(status)); } } else if (wait_rc > 0) { tr_err("tids_sweep_procs: waitpid returned pid %d, expected %d", wait_rc, tp.pid); } /* read the pipe - if the TID request worked, it will have written status before terminating */ result_len = read(tp.read_fd, result, TIDS_MAX_MESSAGE_LEN); close(tp.read_fd); if ((result_len > 0) && (strcmp(result, TIDS_SUCCESS_MESSAGE) == 0)) { tids->req_count++; tr_info("tids_sweep_procs: TID process %d exited after successful request.", tp.pid); } else if ((result_len > 0) && (strcmp(result, TIDS_ERROR_MESSAGE) == 0)) { tids->req_error_count++; tr_info("tids_sweep_procs: TID process %d exited after unsuccessful request.", tp.pid); } else { tids->error_count++; tr_info("tids_sweep_procs: TID process %d exited with an error.", tp.pid); } } }
void M2MConnectionHandlerPimpl::dns_handler() { palStatus_t status; palSocketLength_t _socket_address_len; tr_debug("M2MConnectionHandlerPimpl::dns_handler - _socket_state = %d", _socket_state); switch (_socket_state) { case ESocketStateConnectBeingCalled: case ESocketStateCloseBeingCalled: // Ignore these events break; case ESocketStateDisconnected: // Initialize the socket to stable state close_socket(); status = pal_getAddressInfo(_server_address.c_str(), &_socket_address, &_socket_address_len); if (PAL_SUCCESS != status) { tr_error("addrInfo, err: %d", (int)status); _observer.socket_error(M2MConnectionHandler::DNS_RESOLVING_ERROR); return; } status = pal_setSockAddrPort(&_socket_address, _server_port); if (PAL_SUCCESS != status) { tr_error("setSockAddrPort err: %d", (int)status); } else { tr_debug("address family: %d", (int)_socket_address.addressType); } if (_socket_address.addressType == PAL_AF_INET) { status = pal_getSockAddrIPV4Addr(&_socket_address,_ipV4Addr); if (PAL_SUCCESS != status) { tr_error("sockAddr4, err: %d", (int)status); _observer.socket_error(M2MConnectionHandler::DNS_RESOLVING_ERROR); return; } tr_debug("IPv4 Address %s", tr_array(_ipV4Addr, 4)); _address._address = (void*)_ipV4Addr; _address._length = PAL_IPV4_ADDRESS_SIZE; _address._port = _server_port; } else if (_socket_address.addressType == PAL_AF_INET6) { status = pal_getSockAddrIPV6Addr(&_socket_address,_ipV6Addr); if (PAL_SUCCESS != status) { tr_error("sockAddr6, err: %d", (int)status); _observer.socket_error(M2MConnectionHandler::DNS_RESOLVING_ERROR); return; } tr_debug("IPv6 Address %s", tr_array(_ipV6Addr,sizeof(_ipV6Addr))); _address._address = (void*)_ipV6Addr; _address._length = PAL_IPV6_ADDRESS_SIZE; _address._port = _server_port; } else { tr_error("socket config error, stack: %d", (int)_socket_address.addressType); _observer.socket_error(M2MConnectionHandler::SOCKET_ABORT); return; } if(!init_socket()) { tr_error("socket init error"); // The init_socket() calls the socket_error() -callback directly, so it must not be // done here too. return; } if(is_tcp_connection()) { #ifdef PAL_NET_TCP_AND_TLS_SUPPORT tr_debug("resolve_server_address - Using TCP"); // At least on mbed-os the pal_connect() will perform callbacks even during it // is called, which we will ignore when this state is set. _socket_state = ESocketStateConnectBeingCalled; status = pal_connect(_socket, &_socket_address, sizeof(_socket_address)); if (status == PAL_ERR_SOCKET_IN_PROGRES) { // In this case the connect is done asynchronously, and the pal_socketMiniSelect() // will be used to detect the end of connect. // XXX: the mbed-os version of PAL has a bug (IOTPAL-228) open that the select // does not necessarily work correctly. So, should we actually handle // the PAL_ERR_SOCKET_IN_PROGRESS as a error here if code is compiled for mbed-os? tr_debug("pal_connect(): %d, async connect started", (int)status); // we need to wait for the event _socket_state = ESocketStateConnecting; break; } else if (status == PAL_SUCCESS) { tr_info("pal_connect(): success"); _running = true; _socket_state = ESocketStateConnected; } else { tr_error("pal_connect(): failed: %d", (int)status); close_socket(); _observer.socket_error(M2MConnectionHandler::SOCKET_ABORT); return; } #else tr_error("dns_handler() - TCP not configured" #endif //PAL_NET_TCP_AND_TLS_SUPPORT } else { tr_debug("resolve_server_address - Using UDP"); _socket_state = ESocketStateConnected; _running = true; } // fall through is a normal flow in case the UDP was used or pal_connect() happened to return immediately with PAL_SUCCESS case ESocketStateConnected: if (_security) { if (_security->resource_value_int(M2MSecurity::SecurityMode) == M2MSecurity::Certificate || _security->resource_value_int(M2MSecurity::SecurityMode) == M2MSecurity::Psk) { if( _security_impl != NULL ){ _security_impl->reset(); if (_security_impl->init(_security) == 0) { _is_handshaking = true; tr_debug("resolve_server_address - connect DTLS"); if(_security_impl->start_connecting_non_blocking(_base) < 0 ){ tr_debug("dns_handler - handshake failed"); _is_handshaking = false; close_socket(); _observer.socket_error(M2MConnectionHandler::SSL_CONNECTION_ERROR); return; } } else { tr_error("resolve_server_address - init failed"); close_socket(); _observer.socket_error(M2MConnectionHandler::SSL_CONNECTION_ERROR, false); return; } } else { tr_error("dns_handler - sec is null"); close_socket(); _observer.socket_error(M2MConnectionHandler::SSL_CONNECTION_ERROR, false); return; } } } if(!_is_handshaking) { enable_keepalive(); _observer.address_ready(_address, _server_type, _address._port); } break; // This case is a continuation of a nonblocking connect() and is skipped // completely on UDP. case ESocketStateConnecting: // there is only one socket which we are interested uint8_t socketStatus[1]; pal_timeVal_t zeroTime = {0, 0}; uint32_t socketsSet = 0; status = pal_socketMiniSelect(&_socket, 1, &zeroTime, socketStatus, &socketsSet); if (status != PAL_SUCCESS) { // XXX: how could this fail? What to do? tr_error("dns_handler() - read select fail, err: %d", (int)status); close_socket(); // this will also set the socket state to disconnect // XXX: should we inform the observer here too? return; } if (socketsSet > 0) { if (PAL_NET_SELECT_IS_TX(socketStatus, 0)) { // Socket is connected, signal the dns_handler() again to run rest of the steps tr_debug("dns_handler() - connect+select succeeded"); _socket_state = ESocketStateConnected; send_dns_event(); } else if (PAL_NET_SELECT_IS_ERR(socketStatus, 0)) { tr_error("dns_handler() - connect+select failed"); close_socket(); // this will also set the socket state to disconnect // XXX: should we inform the observer here too? } else { tr_debug("dns_handler() - connect+select not ready yet, continue waiting"); } } break; }
static void thread_parse_accept(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, mle_security_header_t *security_headers, uint8_t linkMargin) { uint32_t llFrameCounter; uint32_t mleFrameCounter; uint16_t version, shortAddress; uint16_t messageId; uint8_t linkMarginfronNeigh; mle_neigh_table_entry_t *entry_temp; bool createNew; tr_info("MLE LINK ACCEPT"); messageId = mle_tlv_validate_response(mle_msg->data_ptr, mle_msg->data_length); if (messageId == 0) { tr_debug("Not for me"); return; } if (!addr_is_ipv6_multicast(mle_service_get_msg_destination_address_pointer(messageId))) { //Free Response only if it is unicast mle_service_msg_free(messageId); } // TODO: Check missing TLV's if ((!mle_tlv_read_16_bit_tlv(MLE_TYPE_VERSION, mle_msg->data_ptr, mle_msg->data_length, &version)) || (!mle_tlv_read_32_bit_tlv(MLE_TYPE_LL_FRAME_COUNTER, mle_msg->data_ptr, mle_msg->data_length, &llFrameCounter)) || (!mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, mle_msg->data_ptr, mle_msg->data_length, &shortAddress))) { return; } /* Call to determine whether or not we should create a new link */ createNew = thread_bootstrap_link_create_check(cur, shortAddress); entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, createNew); if (!entry_temp) { thread_link_reject_send(cur, mle_msg->packet_src_address); return; } if (security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) { thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource)); } //If MLE MLE_TYPE_MLE_FRAME_COUNTER TLV is present then use it for validating further messages else use link layer frame counter if ((!mle_tlv_read_32_bit_tlv(MLE_TYPE_MLE_FRAME_COUNTER, mle_msg->data_ptr, mle_msg->data_length, &mleFrameCounter))) { mleFrameCounter = llFrameCounter; } entry_temp->threadNeighbor = true; entry_temp->short_adr = shortAddress; entry_temp->mle_frame_counter = mleFrameCounter; // Set full data as REED needs full data and SED will not make links entry_temp->mode |= MLE_THREAD_REQ_FULL_DATA_SET; mac_helper_devicetable_set(entry_temp, cur, llFrameCounter, security_headers->KeyIndex); if (entry_temp->timeout_rx) { mle_entry_timeout_refresh(entry_temp); } else { mle_entry_timeout_update(entry_temp, THREAD_DEFAULT_LINK_LIFETIME); } if (thread_i_am_router(cur) && thread_is_router_addr(entry_temp->short_adr)) { // If we both are routers, mark the link as 2-way entry_temp->handshakeReady = 1; tr_debug("Marked link as 2-way, handshakeReady=%d", entry_temp->handshakeReady); } else { tr_debug("Marked link as 1-way, handshakeReady=%d", entry_temp->handshakeReady); } blacklist_update(mle_msg->packet_src_address, true); if (mle_tlv_read_8_bit_tlv(MLE_TYPE_RSSI, mle_msg->data_ptr, mle_msg->data_length, &linkMarginfronNeigh)) { thread_routing_update_link_margin(cur, entry_temp->short_adr, linkMargin, linkMarginfronNeigh); } }
TestMeshApi() : testId(0), tests_pass(1), loopCount(0) { tr_info("TestMeshApi"); }