Ejemplo n.º 1
0
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
	}
}
Ejemplo n.º 2
0
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);
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
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;
}