Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
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");
}
Пример #4
0
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
}
Пример #5
0
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;
    }
}
Пример #8
0
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;
}
Пример #9
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");

}
Пример #10
0
/**
 * \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);
}
Пример #11
0
/*
 * \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);
    }
}
Пример #12
0
/* 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" */
}
Пример #13
0
/**
 * \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);

    }
}
Пример #14
0
/**
 * 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;
}
Пример #15
0
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);
}
Пример #16
0
/*
 * \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);
    }
}
Пример #17
0
/**
 * 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;
}
Пример #18
0
/*
 * \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)
}
Пример #19
0
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;
}
Пример #20
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);

}
Пример #21
0
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,&timestamp)) {
        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);
}
Пример #22
0
/* 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;
}
Пример #23
0
/* 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;
}
Пример #24
0
void mesh_network_callback(mesh_connection_status_t mesh_state)
{
    tr_info("Network established");
    mesh_network_state = mesh_state;
}
Пример #25
0
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;
}
Пример #26
0
/*
 *   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);
    }
}
Пример #27
0
/**
 * 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;
    }
Пример #29
0
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);
    }
}
Пример #30
0
 TestMeshApi() : testId(0), tests_pass(1), loopCount(0) {
     tr_info("TestMeshApi");
 }