accepting Uri between 2 numbers - https

I'm working on the ESP-idf via Visual Studio Code. Currently I'm working on a Webserver implementation and i would like to accept the following url:
IPADDRESS/command/on/5(number between 1 and 32)
The easiest(but not very efficient) solution would be, to initialize every single uri like this
static const httpd_uri_t postCommandOn = {
.uri = "/command/on/1",
.method = HTTP_POST,
.handler = on_command_handler
};
static const httpd_uri_t postCommandOn = {
.uri = "/command/on/2",
.method = HTTP_POST,
.handler = on_command_handler
};
etc..
But shouldn't there be an easier method?
Thanks in advance!
greetings
Edit:
Well I don't know how it happened but my complete project is gone now.
I try to redo my steps but facing a new problem which I'm pretty sure didn't exist the last time.
When i try to add this line:
conf.uri_match_fn = httpd_uri_match_wildcard;
i get the following Error message:
error: 'httpd_ssl_config_t' {aka 'struct httpd_ssl_config'} has no member named 'uri_to_match'
conf.uri_to_match = httpd_uri_match_wildcard;
I dont know why it appears all of the sudden, but I don't really know what i did different to the last time i inserted this line.
my main.c file now looks like this:
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <esp_wifi.h>
#include <esp_event.h>
#include <esp_log.h>
#include <esp_system.h>
#include <nvs_flash.h>
#include <sys/param.h>
#include "esp_netif.h"
#include "esp_eth.h"
#include "protocol_examples_common.h"
#include <esp_https_server.h>
/* A simple example that demonstrates how to create GET and POST
* handlers and start an HTTPS server.
*/
static const char *TAG = "example";
/* An HTTP GET handler */
static esp_err_t root_get_handler(httpd_req_t *req)
{
httpd_resp_set_type(req, "text/html");
httpd_resp_send(req, "<h1>Hello Secure World!</h1>", HTTPD_RESP_USE_STRLEN);
return ESP_OK;
}
static esp_err_t status_get_handler(httpd_req_t *req)
{
httpd_resp_set_type(req, "text/html");
httpd_resp_send(req, "<h1>Hello Secure World!</h1>", HTTPD_RESP_USE_STRLEN);
return ESP_OK;
}
static esp_err_t command_on_post_handler(httpd_req_t *req)
{
httpd_resp_set_type(req, "text/html");
httpd_resp_send(req, "<h1>Hello Secure World!</h1>", HTTPD_RESP_USE_STRLEN);
return ESP_OK;
}
static esp_err_t command_off_post_handler(httpd_req_t *req)
{
httpd_resp_set_type(req, "text/html");
httpd_resp_send(req, "<h1>Hello Secure World!</h1>", HTTPD_RESP_USE_STRLEN);
return ESP_OK;
}
static const httpd_uri_t getStatus = {
.uri = "/status",
.method = HTTP_GET,
.handler = status_get_handler
};
static const httpd_uri_t postCommandOn = {
.uri = "/command/on/*",
.method = HTTP_POST,
.handler = command_on_post_handler
};
static const httpd_uri_t postCommandOff = {
.uri = "/command/off/*",
.method = HTTP_POST,
.handler = command_off_post_handler
};
static const httpd_uri_t root = {
.uri = "/",
.method = HTTP_GET,
.handler = root_get_handler
};
static httpd_handle_t start_webserver(void)
{
httpd_handle_t server = NULL;
// Start the httpd server
ESP_LOGI(TAG, "Starting server");
httpd_ssl_config_t conf = HTTPD_SSL_CONFIG_DEFAULT();
extern const unsigned char cacert_pem_start[] asm("_binary_cacert_pem_start");
extern const unsigned char cacert_pem_end[] asm("_binary_cacert_pem_end");
conf.cacert_pem = cacert_pem_start;
conf.cacert_len = cacert_pem_end - cacert_pem_start;
extern const unsigned char prvtkey_pem_start[] asm("_binary_prvtkey_pem_start");
extern const unsigned char prvtkey_pem_end[] asm("_binary_prvtkey_pem_end");
conf.prvtkey_pem = prvtkey_pem_start;
conf.prvtkey_len = prvtkey_pem_end - prvtkey_pem_start;
//////////////////////////////////////////////////////////
//////////this line causes the problem///////////////////
conf.uri_match_fn = httpd_uri_match_wildcard;
esp_err_t ret = httpd_ssl_start(&server, &conf);
if (ESP_OK != ret) {
ESP_LOGI(TAG, "Error starting server!");
return NULL;
}
// Set URI handlers
ESP_LOGI(TAG, "Registering URI handlers");
httpd_register_uri_handler(server, &root);
httpd_register_uri_handler(server, &getStatus);
httpd_register_uri_handler(server, &postCommandOff);
httpd_register_uri_handler(server, &postCommandOn);
return server;
}
static void stop_webserver(httpd_handle_t server)
{
// Stop the httpd server
httpd_ssl_stop(server);
}
static void disconnect_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
httpd_handle_t* server = (httpd_handle_t*) arg;
if (*server) {
stop_webserver(*server);
*server = NULL;
}
}
static void connect_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
httpd_handle_t* server = (httpd_handle_t*) arg;
if (*server == NULL) {
*server = start_webserver();
}
}
void app_main(void)
{
static httpd_handle_t server = NULL;
ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
/* Register event handlers to start server when Wi-Fi or Ethernet is connected,
* and stop server when disconnection happens.
*/
#ifdef CONFIG_EXAMPLE_CONNECT_WIFI
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &connect_handler, &server));
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &disconnect_handler, &server));
#endif // CONFIG_EXAMPLE_CONNECT_WIFI
#ifdef CONFIG_EXAMPLE_CONNECT_ETHERNET
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &connect_handler, &server));
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_DISCONNECTED, &disconnect_handler, &server));
#endif // CONFIG_EXAMPLE_CONNECT_ETHERNET
/* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
* Read "Establishing Wi-Fi or Ethernet Connection" section in
* examples/protocols/README.md for more information about this function.
*/
ESP_ERROR_CHECK(example_connect());
}
EDIT2:
I tried the following:
in the header esp_https_server.h conf is defined as the following =
.httpd = { \
.task_priority = tskIDLE_PRIORITY+5, \
.stack_size = 10240, \
.core_id = tskNO_AFFINITY, \
.server_port = 0, \
.ctrl_port = 32768, \
.max_open_sockets = 4, \
.max_uri_handlers = 8, \
.max_resp_headers = 8, \
.backlog_conn = 5, \
.lru_purge_enable = true, \
.recv_wait_timeout = 5, \
.send_wait_timeout = 5, \
.global_user_ctx = NULL, \
.global_user_ctx_free_fn = NULL, \
.global_transport_ctx = NULL, \
.global_transport_ctx_free_fn = NULL, \
.open_fn = NULL, \
.close_fn = NULL, \
.uri_match_fn = NULL \ //this is the part which is "no member"
}, \
.cacert_pem = NULL, \
.cacert_len = 0, \
.client_verify_cert_pem = NULL, \
.client_verify_cert_len = 0, \
.prvtkey_pem = NULL, \
.prvtkey_len = 0, \
.transport_mode = HTTPD_SSL_TRANSPORT_SECURE, \
.port_secure = 443, \
.port_insecure = 80, \
}
you can clearly see, that .uri_match_fn is set NULL(so it is a Member of that struct). If I set .uri_match_fn = httpd_uri_match_wildcard \ within the header it does work, but i dont want to change the default setting function. I could add another function which implement a uri wildcard, but i think the problem is somewhere else.
someone might have an Idea why it is like that?

After a search I found an example that shows how it is used:
You have to set the URI matcher to a wild card match.
config.uri_match_fn = httpd_uri_match_wildcard;
static esp_err_t on_command_handler(httpd_req_t *req)
{
// req->uri is character array with request uri
// find the number after /on/ and validate
// and call httpd_resp_send_404(req)
return ESP_OK;
}
static const httpd_uri_t postCommandOn = {
.uri = "/command/on/*",
.method = HTTP_POST,
.handler = on_command_handler
};
httpd_register_uri_handler(server_handle, &postCommandOn);

The ISP IDF HTTP server supports custom URI matchers, where you can create your own logic for matching the incoming request URIs or use basic wildcard expressions. I don't have time to dig into the API documentation for producing sample code, but it looks fairly simple.

Related

ESP32-C3-DevKitC-02 Getting Junk Data on UART for AT commands

I am interfacing A7672S 4G module with ESP32-C3-DevKitC-02 over Uart0
The problem i am facing is for any AT command published,i am getting lot of junk data
I have tried publising AT to the same 4G module using arduino ,i am able to get the correct response only with this ESP module i am seeing such issues
void uart_init(void)
{
const uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_DEFAULT,
};
// We won't use a buffer for sending data.
uart_driver_install(UART_NUM_0, RX_BUF_SIZE * 2, 0, 0, NULL, 0);
uart_param_config(UART_NUM_0, &uart_config);
uart_set_pin(UART_NUM_0, TXD_PIN, RXD_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
}
#define RX_BUF_SIZE 1024
int sendData( const char *data)
{
static const char *TX_TASK_TAG = "TX_TASK";
esp_log_level_set(TX_TASK_TAG, ESP_LOG_VERBOSE);
const int len = strlen(data);
const int txBytes = uart_write_bytes(UART_NUM_0, data, len);
ESP_LOGI(TX_TASK_TAG, "Wrote %d bytes", txBytes);
return txBytes;
}
static uint8_t receiveData(uint8_t *data,unsigned int delay_ms)
{
uint8_t rxBytes = 0;
static const char *RX_TASK_TAG = "RX_TASK";
esp_log_level_set(RX_TASK_TAG, ESP_LOG_VERBOSE);
rxBytes = uart_read_bytes(UART_NUM_0, data,RX_BUF_SIZE, delay_ms / portTICK_PERIOD_MS);
data[rxBytes]='\0';
ESP_LOGI(RX_TASK_TAG, "Received %d bytes:\nRxData:%s\n", rxBytes,data);
return rxBytes;
}
uint8_t *data = (uint8_t *)malloc(RX_BUF_SIZE + 1);
uint8_t len=0;
static const char *MAIN_TAG = "MAIN_FUNCTION";
esp_log_level_set(MAIN_TAG, ESP_LOG_VERBOSE);
memset(data, 0, RX_BUF_SIZE + 1);
uart_init();
vTaskDelay(20);
uart_flush(UART_NUM_0);
sendData("AT+CGMI\r\n");
len = receiveData(data,2000);
if(OK == check_response(data,(unsigned char*)"OK"))
{
ESP_LOGI(MAIN_TAG,"Incorporated AT Response Received");
}
else
{
ESP_LOGI(MAIN_TAG,"AT Response Not Received");
}

Electric UI example ESP32 websockets example code issue

This is the example code given for Electric UI's ESP32 websockets intergration.
// This example was written with the ESP8266 and ESP32 as the target hardware.
// Connects to a wifi access point and runs a websockets server as a transport for eUI.
// The ws path is hinted to the UI over the serial connection which ruggedises connection discovery.
// Base wifi libraries from the ESP library pack
#include "WiFi.h"
#include "WiFiMulti.h"
#include "WiFiClientSecure.h"
// Websockets library https://github.com/Links2004/arduinoWebSockets
#include "WebSocketsServer.h"
#include "electricui.h"
#define LED_PIN LED_BUILTIN
// Define default network credentials
char * wifi_ssid = "ssid";
char * wifi_pass = "password";
uint8_t ws_connected = 0; //state indication
uint8_t ws_port = 80;
char ws_path[] = "ws(s)://255.255.255.255:81";
// Simple variables to modify the LED behaviour
uint8_t blink_enable = 1; //if the blinker should be running
uint8_t led_state = 0; //track if the LED is illuminated
uint16_t glow_time = 200; //in milliseconds
// Keep track of when the light turns on or off
uint32_t led_timer = 0;
//example variables
uint8_t example_uint8 = 21;
uint16_t example_uint16 = 321;
uint32_t example_uint32 = 654321;
float example_float = 3.141592;
char demo_string[] = "ESP32 Test Board";
eui_message_t dev_msg_store[] = {
EUI_UINT8( "wsc", ws_connected),
EUI_CHAR_ARRAY( "ws", ws_path ),
EUI_UINT8( "led_blink", blink_enable ),
EUI_UINT8( "led_state", led_state ),
EUI_UINT16( "lit_time", glow_time ),
EUI_UINT8( "ui8", example_uint8 ),
EUI_UINT16( "i16", example_uint16 ),
EUI_UINT32( "i32", example_uint32 ),
EUI_FLOAT( "fPI", example_float ),
EUI_CHAR_ARRAY_RO( "name", demo_string ),
};
WiFiMulti WiFiMulti;
WebSocketsServer webSocket = WebSocketsServer(ws_port);
void tx_putc(uint8_t *data, uint16_t len);
void ws_tx_putc(uint8_t *data, uint16_t len);
eui_interface_t comm_links[] = {
EUI_INTERFACE(&tx_putc),
EUI_INTERFACE(&ws_tx_putc),
};
void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length)
{
uint8_t * iter = payload;
uint8_t * end = payload + length;
switch(type)
{
case WStype_DISCONNECTED:
ws_connected = 2;
break;
case WStype_CONNECTED:
ws_connected = 3;
break;
case WStype_TEXT:
// send data to all connected clients
// webSocket.broadcastTXT("message here");
break;
case WStype_BIN:
while( iter < end )
{
eui_parse(*iter++, &comm_links[1]);
}
break;
case WStype_ERROR:
case WStype_FRAGMENT_TEXT_START:
case WStype_FRAGMENT_BIN_START:
case WStype_FRAGMENT:
case WStype_FRAGMENT_FIN:
ws_connected = 4;
break;
}
}
void wifi_handle()
{
if( WiFiMulti.run() == WL_CONNECTED )
{
//we have a wifi connection
if(!ws_connected)
{
webSocket.begin();
webSocket.onEvent(webSocketEvent);
ws_connected = 1;
// The hint is formatted like ws://255.255.255.255:81
memset( ws_path, 0, sizeof(ws_path) ); //clear the string first
snprintf(ws_path, sizeof(ws_path), "ws://%s:%d", WiFi.localIP().toString().c_str(), ws_port);
glow_time = 200;
// Using Arduino Strings
// String ws_path_string = "ws://" + WiFi.localIP().toString().c_str() + ":" + String(ws_port);
// ws_path_string.toCharArray(ws_path, sizeof(ws_path));
}
else
{
webSocket.loop();
}
}
else
{
//no connection, try again later
ws_connected = 0;
}
}
void eui_callback( uint8_t message )
{
switch(message)
{
case EUI_CB_TRACKED:
// UI recieved a tracked message ID and has completed processing
break;
case EUI_CB_UNTRACKED:
{
// UI passed in an untracked message ID
// Grab parts of the inbound packet which are are useful
eui_header_t header = comm_links[0].packet.header;
uint8_t *name_rx = comm_links[0].packet.id_in;
void *payload = comm_links[0].packet.data_in;
// See if the inbound packet name matches our intended variable
if( strcmp( (char *)name_rx, "talk" ) == 0 )
{
webSocket.broadcastTXT("hello over websockets");
glow_time = 50;
}
}
break;
case EUI_CB_PARSE_FAIL:
break;
}
}
void setup()
{
Serial.begin(115200);
pinMode( LED_BUILTIN, OUTPUT );
//eUI setup
comm_links[0].interface_cb = &eui_callback;
eui_setup_interfaces(comm_links, 2);
EUI_TRACK(dev_msg_store);
eui_setup_identifier("esp32", 5);
WiFiMulti.addAP(wifi_ssid, wifi_pass);
led_timer = millis();
}
void loop()
{
wifi_handle();
while(Serial.available() > 0)
{
eui_parse(Serial.read(), &comm_links[0]);
}
if( blink_enable )
{
// Check if the LED has been on for the configured duration
if( millis() - led_timer >= glow_time )
{
led_state = !led_state; //invert led state
led_timer = millis();
}
}
digitalWrite( LED_PIN, led_state ); //update the LED to match the intended state
}
void tx_putc( uint8_t *data, uint16_t len )
{
Serial.write( data, len );
}
void ws_tx_putc( uint8_t *data, uint16_t len )
{
webSocket.broadcastBIN( data, len);
}
When I enter my SSID and Password the serial monitor just displays:
E (2462) wifi:Association refused temporarily, comeback time 200 mSec
However the LED is blinking as it should.... The Electric UI shows no devices found....

How do I make an HTTPS request with SIM900 (Arduino)

I try to make an HTTPS GET request and make an HTTPS POST request with the data recieved... I am using an arduino UNO with the library GSM_GPRS_GPS_Shield_GSMSHIELD and the GSM GPRS shield SIM900. Here is my current code below:
//include libs
#include "SIM900.h"
#include "inetGSM.h"
#include <SoftwareSerial.h>
InetGSM inet;
//data holder
int par1 = -1;
int par2 = -1;
void setup() {
Serial.begin(9600);
Serial.println("BEGIN");
boolean started = false;
SIM900power();
//initialize the SIM900
if (gsm.begin(2400)){
Serial.println("READY");
started=true;
}else Serial.println("IDLE");
//connect it to the network
if(started){
if (inet.attachGPRS("free", "", ""))
Serial.println("ATTACHED");
else Serial.println("ERROR");
delay(1000);
gsm.SimpleWriteln("AT+CIFSR");
delay(3000);
gsm.WhileSimpleRead();
//GET request
char * json = "";
while(strlen(json) < 4){
delay(2000);
char msg[200] = "";
Serial.println(inet.httpGET("my.site.com", 80, "/somethingToGet?param=1", msg, 200));
//interpret Json
char * msg_tmp = msg;
json = strstr (msg_tmp, "[{");
}
if(json != ""){
const byte posPar1 = (int)(strstr(json, "par1") - json) + 7;
const byte posPar2 = (int)(strstr(json, "par2") - json) + 7;
if(json[posPar1] != 'u')
par1 = extractNum(json, posPar1);
if(json[posPar2] != 'u')
par2 = extractNum(json, posPar2);
}
if(json == "" || par1 == -1 || par2 == -1){
SIM900power();
Serial.println("A JSON ERROR OCCURED");
while(1){}}
}
};
void loop() {
aPostRequest();
while(1){}
};
void SIM900power()
{
digitalWrite(9, HIGH);
delay(1000);
digitalWrite(9, LOW);
delay(8000);
}
//extract the data from the Json string
int extractPar(char * json, byte pos){
int num = 0;
while (json[pos] != '"'){
num = json[pos]-'0' + num * 10;
pos++;
}
return num;
}
//POST request
void aPostRequest(){
if( par1 != -1 && par2 != -1){
boolean dataFound = true;
while(dataFound){
delay(2000);
char params[100];
snprintf(params, 100, "par1=%d&par2=%d", par1,par2);
char msg[200] = "";
dataFound = (inet.httpPOST("my.site.com ", 80, "/something", params , msg, 200) == 0);
}
}
}
I have two web sites, an HTTP one for my tests and the other one in HTTPS. As you can imagine, it's working on my HTTP one.
I don't know how to solve this problem but I think I need to do some tricky things with certificates in the library... can somebody help?
PS: if you want to test the code, you need to uncomment the HTTPPOST() function in the file inetGSM.h of the library. You can edit the functions httpGET() and HTTPPOST() in the file inetGSM.cpp.
UPDATE
There is the library code for the GET function below (httpPOST() works the same) :
int InetGSM::httpGET(const char* server, int port, const char* path, char* result, int resultlength)
{
boolean connected=false;
int n_of_at=0;
int length_write;
char end_c[2];
end_c[0]=0x1a;
end_c[1]='\0';
/*
Status = ATTACHED.
if(gsm.getStatus()!=GSM::ATTACHED)
return 0;
*/
while(n_of_at<3) {
if(!connectTCP(server, port)) {
#ifdef DEBUG_ON
Serial.println("DB:NOT CONN");
#endif
n_of_at++;
} else {
connected=true;
n_of_at=3;
}
}
if(!connected) return 0;
gsm.SimpleWrite("GET ");
gsm.SimpleWrite(path);
gsm.SimpleWrite(" HTTP/1.0\r\nHost: ");
gsm.SimpleWrite(server);
gsm.SimpleWrite("\r\n");
gsm.SimpleWrite("User-Agent: Arduino");
gsm.SimpleWrite("\r\n\r\n");
gsm.SimpleWrite(end_c);
switch(gsm.WaitResp(10000, 10, "SEND OK")) {
case RX_TMOUT_ERR:
return 0;
break;
case RX_FINISHED_STR_NOT_RECV:
return 0;
break;
}
delay(50);
#ifdef DEBUG_ON
Serial.println("DB:SENT");
#endif
int res = gsm.read(result, resultlength);
//gsm.disconnectTCP();
//int res=1;
return res;
}
I have already tried to change the HTTP/1.0 for HTTPS/1.0, but nothing appends.
UPDATE 2
I redirected my request through my HTTP server because I still have not found an answer, if someone could answer for those who could be blocked!
I was trying to make a HTTPS request to a Lambda function that i coded in AWS. The function had to send a json body from a WEMOS D1 mini via a POST to AWS. TBH, I don't know, if this will solve your Issue on your Controller, but it might be worth trying :)
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#ifndef STASSID
#define STASSID "<yourWiFiSSID>"
#define STAPSK "<yourWifiPW>"
#endif
const char* ssid = STASSID;
const char* password = STAPSK;
const char* host = "<the host link here (has to look like **google.com** important, dont add the route here) >";
const int httpsPort = 443;
const String data = "<Json Object here e.g -> **{\"temperature\": 20.5, \"humidity\": 60}**>";
// Use web browser to view and copy
// SHA1 fingerprint of the certificate
const char fingerprint[] PROGMEM = "5F F1 60 31 09 04 3E F2 90 D2 B0 8A 50 38 04 E8 37 9F BC 76";
void setup() {
Serial.begin(115200);
Serial.println();
Serial.print("connecting to ");
Serial.println(ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
// Use WiFiClientSecure class to create TLS connection
WiFiClientSecure client;
Serial.print("connecting to ");
Serial.println(host);
Serial.printf("Using fingerprint '%s'\n", fingerprint);
client.setFingerprint(fingerprint);
client.setInsecure();
if (!client.connect(host, httpsPort)) {
Serial.println("connection failed");
return;
}
String url = "<your route here e.g **/photos/test**> ";
Serial.print("requesting URL: ");
Serial.println(url);
client.print(String("POST ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Connection: close\r\n"+
"Content-Length: " + data.length() + "\r\n" +
"Content-Type: application/json;charset=UTF-8\r\n\r\n"+
data +"\r\n");
Serial.println("request sent");
//READ INCOMING HTML
uint8_t * _buffer = new uint8_t[128];
String line = "";
if (client.connected()) {
int actualLength = client.read(_buffer, 128);
// If it fails for whatever reason
if(actualLength <= 0)
{
return;
}
// Concatenate the buffer content to the final response string
// I used an arduino String for convenience
// but you can use strcat or whatever you see fit
//TRANSFORM EVERY CHAR FROM INCOMING HTML
line += String((char*)_buffer).substring(0, actualLength);
if (line == "\r") {
Serial.println("headers received");
}
}
Serial.print("Line: ");
Serial.println(line);
if (line.startsWith("{\"state\":\"success\"")) {
Serial.println("esp8266/Arduino CI successfull!");
} else {
Serial.println("esp8266/Arduino CI has failed");
}
Serial.println("reply was:");
Serial.println("==========");
Serial.println(line);
Serial.println("==========");
Serial.println("closing connection");
}
void loop() {
}
I really hope this might have helped someone.

v8: How to ensure that weak callback runs at exit?

I am having some trouble making the following code work. It is a slight extension of the material found at https://github.com/v8/v8/wiki/Embedders-Guide#accessing-dynamic-variables. It differs in that it has a constructor for the object, in addition to just the object. The code will run successfully, however will leak the native |PointAndPersistent| allocated in |PointConstructor|. I have attempted to provide a callback to clean it up with |SetWeak|, based on some code I found in d8 (https://cs.chromium.org/chromium/src/v8/src/d8.cc?q=DataAndPersistent&sq=package:chromium&l=215), however it is never executed. Does anyone know what the proper way to accomplish this is?
#include <cstdio>
#include "v8/include/libplatform/libplatform.h"
#include "v8/include/v8.h"
using namespace v8;
struct PointAndPersistent {
int x;
int y;
Global<Object> wrapper;
};
void PointAndPersistentCallback(
const WeakCallbackInfo<PointAndPersistent>& data) {
data.GetParameter()->wrapper.Reset();
delete data.GetParameter();
}
void PointConstructor(const FunctionCallbackInfo<Value>& args) {
PointAndPersistent* point_and_persistent = new PointAndPersistent();
if (args.Length() > 0) {
point_and_persistent->x = args[0]->Int32Value();
}
if (args.Length() > 1) {
point_and_persistent->y = args[1]->Int32Value();
}
point_and_persistent->wrapper.Reset(args.GetIsolate(), args.This());
point_and_persistent->wrapper.SetWeak(point_and_persistent,
PointAndPersistentCallback,
v8::WeakCallbackType::kParameter);
point_and_persistent->wrapper.MarkIndependent();
args.This()->SetInternalField(0,
External::New(args.GetIsolate(), point_and_persistent));
args.GetReturnValue().Set(args.This());
}
void GetPointX(Local<String> property,
const PropertyCallbackInfo<Value>& info) {
Local<Object> self = info.Holder();
Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
void* ptr = wrap->Value();
int value = static_cast<PointAndPersistent*>(ptr)->x;
info.GetReturnValue().Set(value);
}
void SetPointX(Local<String> property, Local<Value> value,
const PropertyCallbackInfo<void>& info) {
Local<Object> self = info.Holder();
Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
void* ptr = wrap->Value();
static_cast<PointAndPersistent*>(ptr)->x = value->Int32Value();
}
void GetPointY(Local<String> property,
const PropertyCallbackInfo<Value>& info) {
Local<Object> self = info.Holder();
Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
void* ptr = wrap->Value();
int value = static_cast<PointAndPersistent*>(ptr)->y;
info.GetReturnValue().Set(value);
}
void SetPointY(Local<String> property, Local<Value> value,
const PropertyCallbackInfo<void>& info) {
Local<Object> self = info.Holder();
Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
void* ptr = wrap->Value();
static_cast<PointAndPersistent*>(ptr)->y = value->Int32Value();
}
int main() {
Platform* platform = platform::CreateDefaultPlatform();
V8::InitializePlatform(platform);
V8::Initialize();
Isolate::CreateParams params;
params.array_buffer_allocator = ArrayBuffer::Allocator::NewDefaultAllocator();
Isolate* isolate = Isolate::New(params);
{
Isolate::Scope isolate_scope(isolate);
HandleScope handle_scope(isolate);
Local<FunctionTemplate> point_constructor_template =
FunctionTemplate::New(isolate, PointConstructor);
point_constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
point_constructor_template->InstanceTemplate()->SetAccessor(
String::NewFromUtf8(isolate, "x"), GetPointX, SetPointX);
point_constructor_template->InstanceTemplate()->SetAccessor(
String::NewFromUtf8(isolate, "y"), GetPointY, SetPointY);
Local<ObjectTemplate> point_template =
ObjectTemplate::New(isolate, point_constructor_template);
Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
Local<String> name =
String::NewFromUtf8(isolate, "Point", NewStringType::kNormal)
.ToLocalChecked();
global_template->Set(name, point_constructor_template);
Local<Context> context = Context::New(isolate, nullptr, global_template);
Context::Scope context_scope(context);
Local<String> source = String::NewFromUtf8(isolate, "new Point(1, 2).x;",
NewStringType::kNormal)
.ToLocalChecked();
Local<Script> script = Script::Compile(context, source).ToLocalChecked();
Local<Value> result = script->Run(context).ToLocalChecked();
String::Utf8Value utf8(isolate, result);
printf("%s\n", *utf8);
}
isolate->Dispose();
V8::Dispose();
V8::ShutdownPlatform();
delete platform;
delete params.array_buffer_allocator;
}
Thanks!
Weak callbacks are invoked when the garbage collector determines that the object can be freed. A short-running program like your example has no need to ever run the garbage collector.
You can try to force a GC cycle before shutting down your app. Of course that will make your shutdown slower.
For the record, the documentation of SetWeak says:
NOTE: There is no guarantee as to when or even if the callback is
invoked. The invocation is performed solely on a best effort basis.
As always, GC-based finalization should not be relied upon for any
critical form of resource management!

C++/CLI HTTP Proxy problems

I'm trying(very hard) to make a small HTTP Proxy server which I can use to save all communications to a file. Seeing as I dont really have any experience in the area, I used a class from codeproject.com and some associated code to get started (It was made in the old CLI syntax, so I converted it). I couldn't get it working, so I added lots more code to make it work (threads etc), and now it sort of works. Basically, it recieves something from a client (I just configured Mozilla Firefox to route its connections through this proxy) and then routes it to google.com. After it sends Firefox's data to google, recieves a responce, and sends that to Firefox. This works fine, but then the proxy fails to recieve any data from Firefox. It just loops in the Sleep(50) section. Anyway, heres the code:
ProxyTest.cpp:
#include "stdafx.h"
#include "windows.h"
#include "CHTTPProxy.h"
public ref class ClientThread {
public:
System::Net::Sockets::TcpClient ^ pClient;
CHttpProxy ^ pProxy;
System::Int32 ^ pRecieveBufferSize;
System::Threading::Thread ^ Thread;
ClientThread(System::Net::Sockets::TcpClient ^ sClient,
CHttpProxy ^ sProxy,
System::Int32 ^ sRecieveBufferSize) {
pClient = sClient;
pProxy = sProxy;
pRecieveBufferSize = sRecieveBufferSize;
};
void StartReading() {
Thread = gcnew System::Threading::Thread(gcnew System::Threading::ThreadStart(this,&ClientThread::ThreadEntryPoint));
Thread->Start();
};
void ThreadEntryPoint() {
char * bytess;
bytess = new char[(int)pRecieveBufferSize];
memset(bytess, 0, (int)pRecieveBufferSize);
array<unsigned char> ^ bytes = gcnew array<unsigned char>((int)pRecieveBufferSize);
array<unsigned char> ^ sendbytes;
do {
if (pClient->GetStream()->DataAvailable) {
try {
do {
Sleep(100); //Lets wait for whole packet to get cached (If it even does...)
unsigned int k = pClient->GetStream()->Read(bytes, 0, (int)pRecieveBufferSize); //Read it
for (unsigned int i=0; i<(int)pRecieveBufferSize; i++) bytess[i] = bytes[i];
Console::WriteLine("Packet Received:\n"+gcnew System::String(bytess));
pProxy->SendToServer(bytes,pClient->GetStream()); //Now send it to google!
} while (pClient->GetStream()->DataAvailable);
} catch (Exception ^ e) {
break;
}
} else {
Sleep(50);
if (!(pClient->Connected)) break;
};
} while (pClient->GetStream()->CanRead);
delete [] bytess;
pClient->Close();
};
};
int main(array<System::String ^> ^args)
{
System::Collections::Generic::Stack<ClientThread ^> ^ Clients =
gcnew System::Collections::Generic::Stack<ClientThread ^>();
System::Net::Sockets::TcpListener ^ pTcpListener = gcnew System::Net::Sockets::TcpListener(8080);
pTcpListener->Start();
System::Net::Sockets::TcpClient ^ pTcpClient;
while (1) {
pTcpClient = pTcpListener->AcceptTcpClient(); //Wait for client
ClientThread ^ Client = gcnew ClientThread(pTcpClient,
gcnew CHttpProxy("www.google.com.au", 80),
pTcpClient->ReceiveBufferSize); //Make a new object for this client
Client->StartReading(); //Start the thread
Clients->Push(Client); //Add it to the list
};
pTcpListener->Stop();
return 0;
}
CHTTPProxy.h, from http://www.codeproject.com/KB/IP/howtoproxy.aspx with a lot of modifications:
#using <mscorlib.dll>
#using <SYSTEM.DLL>
using namespace System;
using System::Net::Sockets::TcpClient;
using System::String;
using System::Exception;
using System::Net::Sockets::NetworkStream;
#include <stdio.h>
ref class CHttpProxy
{
public:
CHttpProxy(System::String ^ szHost, int port);
System::String ^ m_host;
int m_port;
void SendToServer(array<unsigned char> ^ Packet, System::Net::Sockets::NetworkStream ^ sendstr);
};
CHttpProxy::CHttpProxy(System::String ^ szHost, int port)
{
m_host = gcnew System::String(szHost);
m_port = port;
}
void CHttpProxy::SendToServer(array<unsigned char> ^ Packet, System::Net::Sockets::NetworkStream ^ sendstr)
{
TcpClient ^ tcpclnt = gcnew TcpClient();
try
{
tcpclnt->Connect(m_host,m_port);
}
catch (Exception ^ e )
{
Console::WriteLine(e->ToString());
return;
}
// Send it
if ( tcpclnt )
{
NetworkStream ^ networkStream;
networkStream = tcpclnt->GetStream();
int size = Packet->Length;
networkStream->Write(Packet, 0, size);
array<unsigned char> ^ bytes = gcnew array<unsigned char>(tcpclnt->ReceiveBufferSize);
char * bytess = new char[tcpclnt->ReceiveBufferSize];
Sleep(500); //Wait for responce
do {
unsigned int k = networkStream->Read(bytes, 0, (int)tcpclnt->ReceiveBufferSize); //Read from google
for(unsigned int i=0; i<k; i++) {
bytess[i] = bytes[i];
if (bytess[i] == 0) bytess[i] = ' '; //Dont terminate the string
if (bytess[i] < 8) bytess[i] = ' '; //Somethings making the computer beep, and its not 7?!?!
};
Console::WriteLine("\n\nAbove packet sent to google. Google Packet Received:\n"+gcnew System::String(bytess));
sendstr->Write(bytes,0,k); //Send it to mozilla
Console::WriteLine("\n\nAbove packet sent to client...");
//Sleep(1000);
} while(networkStream->DataAvailable);
delete [] bytess;
}
return;
}
Any help would be much appreciated, I've tried for hours. (Sorry about the indents nobugz, its fixed now)

Resources