void wifi_data_next_handle_wait_for_data(char ndata) { #ifdef WIFI_DEBUG_PRINT_DATA #if LOGGING_LEVEL == LOGGING_DEBUG if(wifi_buffer_size_counter == 0) { logwohd("{"); } #endif logwohd("%x, ", ndata); #endif wifi_buffer_recv[wifi_buffer_size_counter] = ndata; wifi_buffer_size_counter++; if(wifi_buffer_size_counter > 4) { uint16_t length = wifi_buffer_recv[MESSAGE_HEADER_LENGTH_POSITION]; if(length > 80) { logwifie("Got length > 80: %d (1), desired: %d\n\r", length, wifi_data_recv_length_desired); } if(wifi_buffer_size_counter == length) { if(!wifi_data_cid_present[wifi_data_current_cid]) { wifi_data_cid_present[wifi_data_current_cid] = true; led_on(LED_EXT_BLUE_3); } if(brickd_check_auth((MessageHeader*)wifi_buffer_recv, wifi_data_current_cid)) { wifi_buffer_size_recv = wifi_buffer_size_counter; brickd_route_from(wifi_buffer_recv, wifi_data_current_cid); } wifi_buffer_size_counter = 0; // We will force an ACK in 10ms wifi_force_ack_counter[wifi_data_current_cid] = 10; #ifdef WIFI_DEBUG_PRINT_DATA logwohd("}\n\r"); #endif } } wifi_data_recv_length++; if(wifi_data_recv_length == wifi_data_recv_length_desired) { wifi_data_recv_length_desired = 0; wifi_data_recv_length = 0; wifi_data_state = WIFI_DATA_WAIT_FOR_ESC; #ifdef WIFI_DEBUG_PRINT_DATA logwohd("]\n\r"); #endif } }
void wifi_data_send_escape(const char *data, const uint16_t length) { EnumerateCallback *data_enum = (EnumerateCallback*)data; int8_t cid = -1; if(wifi_new_cid != -1 && data_enum->header.fid == FID_ENUMERATE_CALLBACK && data_enum->enumeration_type == ENUMERATE_TYPE_ADDED) { // Handle initial enumeration (only send to new socket) cid = wifi_new_cid; } else { cid = brickd_route_to((const uint8_t*)data); } if(cid == -1) { for(uint8_t i = 1; i < WIFI_DATA_MAX_CID; i++) { if(wifi_data_cid_present[i]) { if(!brickd_check_auth((MessageHeader*)data, i)) { return; } wifi_data_send_escape_cid(data, length, i); } } return; } else { if(!wifi_data_cid_present[cid]) { return; } } if(!brickd_check_auth((MessageHeader*)data, cid)) { return; } wifi_data_send_escape_cid(data, length, cid); }
bool ICACHE_FLASH_ATTR com_handle_message(const uint8_t *data, const uint8_t length, const int8_t cid) { const MessageHeader *header = (const MessageHeader*)data; if(!brickd_check_auth(header, cid)) { return true; } if(header->uid == 1) { switch(header->fid) { case BRICKD_FID_GET_AUTHENTICATION_NONCE: brickd_get_authentication_nonce(cid, (GetAuthenticationNonce*)data); return true; case BRICKD_FID_AUTHENTICATE: brickd_authenticate(cid, (Authenticate*)data); return true; } } switch(header->fid) { case FID_SET_WIFI2_AUTHENTICATION_SECRET: set_wifi2_authentication_secret(cid, (SetWifi2AuthenticationSecret*)data); return true; case FID_GET_WIFI2_AUTHENTICATION_SECRET: get_wifi2_authentication_secret(cid, (GetWifi2AuthenticationSecret*)data); return true; case FID_SET_WIFI2_CONFIGURATION: set_wifi2_configuration(cid, (SetWifi2Configuration*)data); return true; case FID_GET_WIFI2_CONFIGURATION: get_wifi2_configuration(cid, (GetWifi2Configuration*)data); return true; case FID_GET_WIFI2_STATUS: get_wifi2_status(cid, (GetWifi2Status*)data); return true; case FID_SET_WIFI2_CLIENT_CONFIGURATION: set_wifi2_client_configuration(cid, (SetWifi2ClientConfiguration*)data); return true; case FID_GET_WIFI2_CLIENT_CONFIGURATION: get_wifi2_client_configuration(cid, (GetWifi2ClientConfiguration*)data); return true; case FID_SET_WIFI2_CLIENT_HOSTNAME: set_wifi2_client_hostname(cid, (SetWifi2ClientHostname*)data); return true; case FID_GET_WIFI2_CLIENT_HOSTNAME: get_wifi2_client_hostname(cid, (GetWifi2ClientHostname*)data); return true; case FID_SET_WIFI2_CLIENT_PASSWORD: set_wifi2_client_password(cid, (SetWifi2ClientPassword*)data); return true; case FID_GET_WIFI2_CLIENT_PASSWORD: get_wifi2_client_password(cid, (GetWifi2ClientPassword*)data); return true; case FID_SET_WIFI2_AP_CONFIGURATION: set_wifi2_ap_configuration(cid, (SetWifi2APConfiguration*)data); return true; case FID_GET_WIFI2_AP_CONFIGURATION: get_wifi2_ap_configuration(cid, (GetWifi2APConfiguration*)data); return true; case FID_SET_WIFI2_AP_PASSWORD: set_wifi2_ap_password(cid, (SetWifi2APPassword*)data); return true; case FID_GET_WIFI2_AP_PASSWORD: get_wifi2_ap_password(cid, (GetWifi2APPassword*)data); return true; case FID_SAVE_WIFI2_CONFIGURATION: save_wifi2_configuration(cid, (SaveWifi2Configuration*)data); return true; case FID_GET_WIFI2_FIRMWARE_VERSION: get_wifi2_firmware_version(cid, (GetWifi2FirmwareVersion*)data); return true; case FID_ENABLE_WIFI2_STATUS_LED: enable_wifi2_status_led(cid, (EnableWifi2StatusLED*)data); return true; case FID_DISABLE_WIFI2_STATUS_LED: disable_wifi2_status_led(cid, (DisableWifi2StatusLED*)data); return true; case FID_IS_WIFI2_STATUS_LED_ENABLED: is_wifi2_status_led_enabled(cid, (IsWifi2StatusLEDEnabled*)data); return true; case FID_SET_WIFI2_MESH_CONFIGURATION: set_wifi2_mesh_configuration(cid, (SetWifi2MeshConfiguration*)data); return true; case FID_GET_WIFI2_MESH_CONFIGURATION: get_wifi2_mesh_configuration(cid, (GetWifi2MeshConfiguration*)data); return true; case FID_SET_WIFI2_MESH_ROUTER_SSID: set_wifi2_mesh_router_ssid(cid, (SetWifi2MeshRouterSSID*)data); return true; case FID_GET_WIFI2_MESH_ROUTER_SSID: get_wifi2_mesh_router_ssid(cid, (GetWifi2MeshRouterSSID*)data); return true; case FID_SET_WIFI2_MESH_ROUTER_PASSWORD: set_wifi2_mesh_router_password(cid, (SetWifi2MeshRouterPassword*)data); return true; case FID_GET_WIFI2_MESH_ROUTER_PASSWORD: get_wifi2_mesh_router_password(cid, (GetWifi2MeshRouterPassword*)data); return true; case FID_GET_WIFI2_MESH_COMMON_STATUS: get_wifi2_mesh_common_status(cid, (GetWifi2MeshCommonStatus*)data); return true; case FID_GET_WIFI2_MESH_STATION_STATUS: get_wifi2_mesh_station_status(cid, (GetWifi2MeshStationStatus*)data); return true; case FID_GET_WIFI2_MESH_AP_STATUS: get_wifi2_mesh_ap_status(cid, (GetWifi2MeshAPStatus*)data); return true; } return false; }
bool ICACHE_FLASH_ATTR tfp_send(const uint8_t *data, const uint8_t length) { uint8_t i = 0; // TODO: Sanity check length again? // TODO: Are we sure that data is always a full TFP packet? // cid == -2 => send back via UART if(com_handle_message(data, length, -2)) { return true; } // We only peak at the routing table here (and delete the route manually if // we can fit the data in our buffer). It would be very expensive to first // peak and then discover the route again. BrickdRouting *match = NULL; int8_t cid = brickd_route_to_peak(data, &match); if(!brickd_check_auth((const MessageHeader*)data, cid)) { return true; } /* * First let's check if everything fits in the buffers. This is only done if * mesh isn't enabled. When mesh is enabled, dedicated buffer is used for * sending. */ if(!configuration_current.mesh_enable) { if(!tfp_send_check_buffer(cid)) { return false; } } // Add websocket header if necessary uint8_t data_with_websocket_header[TFP_SEND_BUFFER_SIZE + sizeof(WebsocketFrameClientToServer)]; int16_t length_with_websocket_header = tfpw_insert_websocket_header(cid, data_with_websocket_header, data, length); if(length_with_websocket_header == -1) { // -1 = We use websocket but state is not OK for sending return false; } // Remove match from brickd routing table only if we now that we can fit // the data in the buffer if(match != NULL) { match->uid = 0; match->func_id = 0; match->sequence_number = 0; match->cid = -1; } /* * FIXME: Shouldn't the buffering while sending mechanism be also used for * non-mesh case? As it is documented that packets should be sent from the * sent callback of the previous packet. */ // Broadcast. if(cid == -1) { /* * Broadcast is handled differently when mesh is enabled as then there is * only one socket connection invovled. */ if (!configuration_current.mesh_enable) { for(uint8_t i = 0; i < TFP_MAX_CONNECTIONS; i++) { if(tfp_cons[i].state == TFP_CON_STATE_OPEN) { // TODO: sent data (return value) tfp_cons[i].state = TFP_CON_STATE_SENDING; uint8_t length_to_send = length; if(tfp_cons[i].websocket_state == WEBSOCKET_STATE_NO_WEBSOCKET) { os_memcpy(tfp_cons[i].send_buffer, data, length); } else { os_memcpy(tfp_cons[i].send_buffer, data_with_websocket_header, length_with_websocket_header); length_to_send = length_with_websocket_header; } espconn_send(tfp_cons[i].con, tfp_cons[i].send_buffer, length_to_send); } } } else { os_memcpy(tfp_cons[0].send_buffer, data, length); // Check if the socket is in a state to be able to send. if(tfp_cons[0].state == TFP_CON_STATE_OPEN) { tfp_mesh_send(tfp_cons[0].con, tfp_cons[0].send_buffer, length); } /* * If the socket can't send at the moment buffer the packet in TFP mesh * send buffer for sending in future. */ else { if(tfp_mesh_send_check_buffer(length)) { for(i = 0; i < length; i++) { if(!ringbuffer_add(&tfp_mesh_send_rb, data[i])) { return false; } } } else { return false; } } } } // Unicast. else { uint8_t length_to_send = length; if(!configuration_current.mesh_enable) { // When mesh mode is enabled this socket state is updated from tfp_mesh_send(). tfp_cons[cid].state = TFP_CON_STATE_SENDING; } if(tfp_cons[cid].websocket_state == WEBSOCKET_STATE_NO_WEBSOCKET) { os_memcpy(tfp_cons[cid].send_buffer, data, length); } else { os_memcpy(tfp_cons[cid].send_buffer, data_with_websocket_header, length_with_websocket_header); length_to_send = length_with_websocket_header; } if(configuration_current.mesh_enable) { // Check if the socket is in a state to be able to send. if(tfp_cons[0].state == TFP_CON_STATE_OPEN) { tfp_mesh_send(tfp_cons[0].con, tfp_cons[0].send_buffer, length_to_send); } /* * If the socket can't send at the moment buffer the packet in TFP mesh * send buffer for sending in future. */ else { if(tfp_mesh_send_check_buffer(length_to_send)) { for(i = 0; i < length_to_send; i++) { if(!ringbuffer_add(&tfp_mesh_send_rb, data[i])) { return false; } } } else { return false; } } } else { espconn_send(tfp_cons[cid].con, tfp_cons[cid].send_buffer, length_to_send); } } if(ringbuffer_get_free(&tfp_rb) > (6*MTU_LENGTH + 2)) { tfp_recv_unhold(); } return true; }