ESP-CAM Webserver reboots when using ArduinoOTA - webserver

I´m trying to add OTA capability to this program from https://randomnerdtutorials.com/esp32-cam-video-streaming-web-server-camera-home-assistant/ using the code below (sorry for the huge code). The problem is when I add the line to enable OTA in the setup function, the ESP-CAM reboots after starting the stream in less than 10 seconds. Can you help me, please?
#include "esp_camera.h"
#include <WiFi.h>
#include <ESPmDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include "esp_timer.h"
#include "img_converters.h"
#include "Arduino.h"
#include "fb_gfx.h"
#include "soc/soc.h" // disable brownout problems
#include "soc/rtc_cntl_reg.h" // disable brownout problems
#include "esp_http_server.h"
// My WiFi credentials
#include <credentials.h>
const char* ssid = MY_SSID;
const char* password = MY_PASSWORD;
#define PART_BOUNDARY "123456789000000000000987654321"
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 0
#define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27
#define Y9_GPIO_NUM 35
#define Y8_GPIO_NUM 34
#define Y7_GPIO_NUM 39
#define Y6_GPIO_NUM 36
#define Y5_GPIO_NUM 21
#define Y4_GPIO_NUM 19
#define Y3_GPIO_NUM 18
#define Y2_GPIO_NUM 5
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
static const char* _STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY;
static const char* _STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n";
static const char* _STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n";
httpd_handle_t camera_httpd = NULL;
httpd_handle_t stream_httpd = NULL;
static const char PROGMEM INDEX_HTML[] = R"rawliteral(
<html>
<head>
<title>ESP32-CAM Robot</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
img { width: auto ;
max-width: 100% ;
height: auto ;
}
</style>
</head>
<body>
<img src="" id="photo" >
<script>
document.getElementById("photo").src = window.location.href.slice(0, -1) + ":81/stream";
console.log(window.location.href.slice(0, -1) + ":81/stream")
</script>
</body>
</html>
)rawliteral";
void setup() {
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector
Serial.begin(115200);
Serial.println("Booting");
Serial.setDebugOutput(false);
camera_config_t config;
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
config.pin_d0 = Y2_GPIO_NUM;
config.pin_d1 = Y3_GPIO_NUM;
config.pin_d2 = Y4_GPIO_NUM;
config.pin_d3 = Y5_GPIO_NUM;
config.pin_d4 = Y6_GPIO_NUM;
config.pin_d5 = Y7_GPIO_NUM;
config.pin_d6 = Y8_GPIO_NUM;
config.pin_d7 = Y9_GPIO_NUM;
config.pin_xclk = XCLK_GPIO_NUM;
config.pin_pclk = PCLK_GPIO_NUM;
config.pin_vsync = VSYNC_GPIO_NUM;
config.pin_href = HREF_GPIO_NUM;
config.pin_sscb_sda = SIOD_GPIO_NUM;
config.pin_sscb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;
config.pixel_format = PIXFORMAT_JPEG;
if(psramFound()){
config.frame_size = FRAMESIZE_VGA;
config.jpeg_quality = 10;
config.fb_count = 2;
} else {
config.frame_size = FRAMESIZE_SVGA;
config.jpeg_quality = 12;
config.fb_count = 1;
}
// Camera init
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
return;
}
// Wi-Fi connection
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("Connection Failed! Rebooting...");
delay(5000);
ESP.restart();
}
Serial.println("");
Serial.println("WiFi connected");
Serial.print("Camera Stream Ready! Go to: http://");
Serial.println(WiFi.localIP());
// Start streaming web server
startCameraServer();
// Arduino OTA
ArduinoOTA.setHostname("CameraWideOTA");
ArduinoOTA
.onStart([]() {
String type;
if (ArduinoOTA.getCommand() == U_FLASH)
type = "sketch";
else // U_SPIFFS
type = "filesystem";
// NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
Serial.println("Start updating " + type);
})
.onEnd([]() {
Serial.println("\nEnd");
})
.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
})
.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
else if (error == OTA_END_ERROR) Serial.println("End Failed");
});
ArduinoOTA.begin();
}
void loop() {
ArduinoOTA.handle();
}
static esp_err_t index_handler(httpd_req_t *req){
Serial.println("***index_handler");
httpd_resp_set_type(req, "text/html");
return httpd_resp_send(req, (const char *)INDEX_HTML, strlen(INDEX_HTML));
}
static esp_err_t stream_handler(httpd_req_t *req){
Serial.println("***stream_handler");
camera_fb_t * fb = NULL;
esp_err_t res = ESP_OK;
size_t _jpg_buf_len = 0;
uint8_t * _jpg_buf = NULL;
char * part_buf[64];
res = httpd_resp_set_type(req, _STREAM_CONTENT_TYPE);
if(res != ESP_OK){
return res;
}
while(true){
ArduinoOTA.handle();
fb = esp_camera_fb_get();
if (!fb) {
Serial.println("Camera capture failed");
res = ESP_FAIL;
} else {
if(fb->width > 400){
if(fb->format != PIXFORMAT_JPEG){
bool jpeg_converted = frame2jpg(fb, 80, &_jpg_buf, &_jpg_buf_len);
esp_camera_fb_return(fb);
fb = NULL;
if(!jpeg_converted){
Serial.println("JPEG compression failed");
res = ESP_FAIL;
}
} else {
_jpg_buf_len = fb->len;
_jpg_buf = fb->buf;
}
}
}
if(res == ESP_OK){
size_t hlen = snprintf((char *)part_buf, 64, _STREAM_PART, _jpg_buf_len);
res = httpd_resp_send_chunk(req, (const char *)part_buf, hlen);
}
if(res == ESP_OK){
res = httpd_resp_send_chunk(req, (const char *)_jpg_buf, _jpg_buf_len);
}
if(res == ESP_OK){
res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY));
}
if(fb){
esp_camera_fb_return(fb);
fb = NULL;
_jpg_buf = NULL;
} else if(_jpg_buf){
free(_jpg_buf);
_jpg_buf = NULL;
}
if(res != ESP_OK){
break;
}
//Serial.printf("MJPG: %uB\n",(uint32_t)(_jpg_buf_len));
}
return res;
}
static esp_err_t cmd_handler(httpd_req_t *req){
Serial.println("***cmd_handler");
char* buf;
size_t buf_len;
char variable[32] = {0,};
buf_len = httpd_req_get_url_query_len(req) + 1;
if (buf_len > 1) {
buf = (char*)malloc(buf_len);
if(!buf){
httpd_resp_send_500(req);
return ESP_FAIL;
}
if (httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK) {
if (httpd_query_key_value(buf, "go", variable, sizeof(variable)) == ESP_OK) {
} else {
free(buf);
httpd_resp_send_404(req);
return ESP_FAIL;
}
} else {
free(buf);
httpd_resp_send_404(req);
return ESP_FAIL;
}
free(buf);
} else {
httpd_resp_send_404(req);
return ESP_FAIL;
}
sensor_t * s = esp_camera_sensor_get();
int res = 0;
if(res){
return httpd_resp_send_500(req);
}
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
return httpd_resp_send(req, NULL, 0);
}
void startCameraServer(){
Serial.println("***startCameraServer");
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
config.server_port = 80;
httpd_uri_t index_uri = {
.uri = "/",
.method = HTTP_GET,
.handler = index_handler,
.user_ctx = NULL
};
httpd_uri_t cmd_uri = {
.uri = "/action",
.method = HTTP_GET,
.handler = cmd_handler,
.user_ctx = NULL
};
httpd_uri_t stream_uri = {
.uri = "/stream",
.method = HTTP_GET,
.handler = stream_handler,
.user_ctx = NULL
};
if (httpd_start(&camera_httpd, &config) == ESP_OK) {
httpd_register_uri_handler(camera_httpd, &index_uri);
httpd_register_uri_handler(camera_httpd, &cmd_uri);
}
config.server_port += 1;
config.ctrl_port += 1;
if (httpd_start(&stream_httpd, &config) == ESP_OK) {
httpd_register_uri_handler(stream_httpd, &stream_uri);
}
}
The backtrace, as romkey sugested is:
Backtrace: 0x4008e32c:0x3ffb1e50 0x4008e5a5:0x3ffb1e70 0x40153ab7:0x3ffb1e90 0x40153afe:0x3ffb1eb0 0x401531d7:0x3ffb1ed0 0x4015350e:0x3ffb1ef0 0x40153275:0x3ffb1f10 0x400d2e39:0x3ffb1f30 0x400d4059:0x3ffb1f70 0x400d13be:0x3ffb1f90 0x400d55f9:0x3ffb1fb0 0x40090236:0x3ffb1fd0
The results presented by the ESP Exception Decoder tool is:
Decoding stack results
0x4008e32c: invoke_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/panic.c line 156
0x4008e5a5: abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/panic.c line 171
0x40153ab7: __cxxabiv1::__terminate(void (*)()) at /builds/idf/crosstool-NG/.build/src/gcc-5.2.0/libstdc++-v3/libsupc++/eh_terminate.cc line 47
0x40153afe: std::terminate() at /builds/idf/crosstool-NG/.build/src/gcc-5.2.0/libstdc++-v3/libsupc++/eh_terminate.cc line 57
0x401531d7: __cxxabiv1::__cxa_throw(void*, std::type_info*, void (*)(void*)) at /builds/idf/crosstool-NG/.build/src/gcc-5.2.0/libstdc++-v3/libsupc++/eh_throw.cc line 87
0x4015350e: operator new(unsigned int) at /builds/idf/crosstool-NG/.build/src/gcc-5.2.0/libstdc++-v3/libsupc++/new_op.cc line 54
0x40153275: operator new[](unsigned int) at /builds/idf/crosstool-NG/.build/src/gcc-5.2.0/libstdc++-v3/libsupc++/new_opv.cc line 32
0x400d2e39: WiFiUDP::parsePacket() at /home/meslin/.arduino15/packages/esp32/hardware/esp32/1.0.6/libraries/WiFi/src/WiFiUdp.cpp line 210
0x400d4059: ArduinoOTAClass::handle() at /home/meslin/.arduino15/packages/esp32/hardware/esp32/1.0.6/libraries/ArduinoOTA/src/ArduinoOTA.cpp line 379
0x400d13be: loop() at /home/meslin/Desktop/sketch_apr11a/sketch_apr11a.ino line 163
0x400d55f9: loopTask(void*) at /home/meslin/.arduino15/packages/esp32/hardware/esp32/1.0.6/cores/esp32/main.cpp line 23
0x40090236: vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c line 143

Related

Problems in second blocks message digest in self-learning SHA-1 algorithm

Output
I am new in learning C programming. Now, I am trying to do SHA-1 for university project. I think this coding by myself. I am trying to do the message digest from the file above 55characters, which means 2 blocks is needed. The first block message digest is correct, but the second block is wrong. I have checked it very many times, but I still not able to find the mistake. Can anyone with experiences able to help me find it out? Thank you.
patients information.txt
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int length,number_of_block,str_length;
unsigned int i = 0,j = 0,l = 0,e = 0,n = 0, t=0, k=0,f=0;
float x=0;
char c;
int H[5]={0x67452301,0xEFCDAB89,0x98BADCFE,0x10325476,0xC3D2E1F0};
unsigned int temp = 0;
FILE *file;
file = fopen("patients information.txt", "r");//Choose the file that want to access
if (file == NULL)//detect the file is empty or not
{
printf("The file is empty");
}
fseek(file, 0, SEEK_END);// move the file pointer to the end of the file
length = ftell(file);//calculate the length of sting in file
fseek(file, 0, SEEK_SET);// move file pointer back to start of file so we can read each character
printf("The length of string is %d\n",length);//check the number of character in string
char *string = malloc(sizeof(char) * (length+1));
while ( (c = fgetc(file)) != EOF)//pass the every character in the file to the string array
{
string[i] = c;
i++;
}
string[i] = '\0';//terminate the string storing
unsigned char long_msg[length+1];
for (i=0;i<length;i++)//pass the pointer array to the unsigned character array
{
long_msg[i]=string[i];
}
printf("The character store in th array is ");
long_msg[length]=128;
for (i=0;i<=length;i++)//check the message in msg array
{
printf("%X ",long_msg[i]);
}
if (length<=55)
{
number_of_block = 1;
}
else if (length>55 && length<120)
{
number_of_block = 2;
}
else
{
x = ((length - 55)/64);//calculate the number of block needed
number_of_block = x+2;
}
printf("\nNumber of block needed is %d\n",number_of_block);
unsigned char blocks[number_of_block][64];
for (i=0;i<number_of_block;i++)//Split the long string into n number of blocks
{
for(j=0;j<64;j++)
{
blocks[i][j]=long_msg[l];
if(l>length)//padding 0
{
blocks[i][j]=0;
}
l++;
}
}
for (i=0;i<number_of_block;i++)//check the blocks content
{
for(j=0;j<64;j++)
{
printf("%X ",blocks[i][j]);
}
}
printf("\nCheck length padding:\n");
str_length = 8*length;//sting length in bits
if (length<32)//if length of string is 1 bytes in hexadecimal
{
blocks[number_of_block-1][63]=str_length;
}
else
{
blocks[number_of_block-1][62]=(str_length>>8);//second last block
blocks[number_of_block-1][63]=((str_length<<8)>>8);//last block
}
for (i=0;i<number_of_block;i++)//check length padding
{
for(j=0;j<64;j++)
{
printf("%02X ",blocks[i][j]);
}
}
unsigned int w[number_of_block][16][4];
unsigned int W[number_of_block][80];
unsigned int A[number_of_block],B[number_of_block],C[number_of_block],D[number_of_block],E[number_of_block];
for (e=0;e<number_of_block;e++)
{
/*The problem is here*/
n=0;
for (i=0;i<16;i++)//split the padding message into w0 to w15 ,exp. w0 = (w[0][1]),....,(w[0][3])
{
for(j=0;j<4;j++)
{
w[e][i][j] = blocks[e][n];
n++;
}
}
for (i=0;i<16;i++)//combine the hex --> 16 block of hexadecimal(W0 to W15)
{
W[e][i] = ((w[e][i][0])<<24 | (w[e][i][1])<<16 | (w[e][i][2])<<8 | (w[e][i][3]));
}
/*Compute message digest*/
A[e] = 0x67452301;
B[e] = 0xEFCDAB89;
C[e] = 0x98BADCFE;
D[e] = 0x10325476;
E[e] = 0xC3D2E1F0;
for (t=0;t<=79;t++)
{
//for t = 16 -> 79
if (t>=16 && t<=79)//prepare W16 to W79
{
W[e][t]= ( (W[e][t-3]) ^ (W[e][t-8]) ^ (W[e][t-14]) ^ (W[e][t-16]) );
W[e][t]= ( ((W[e][t])<<1) | ((W[e][t]) >> (32-1)));//perform circular left shift
}
if (t>=0 && t<=19)
{
f = (B[e]&C[e]) | ((~B[e])&D[e]);
k = 0x5A827999;
}
else if (t>=20 && t<=39)
{
f = (B[e]^C[e]^D[e]);
k = 0x6ED9EBA1;
}
else if (t>=40 && t<=59)
{
f = (B[e]&C[e]) | (B[e]&D[e]) | (C[e]&D[e]);
k = 0x8F1BBCDC;
}
else if(t>=60 && t<=79)
{
f = (B[e]^C[e]^D[e]);
k = 0xCA62C1D6;
}
temp = ((A[e]<<5) | (A[e] >> (32-5))) + f + E[e] + W[e][t] + k;
E[e] = D[e];
D[e] = C[e];
C[e] = ( (B[e]<<30) | (B[e]>> (32-30)));
B[e] = A[e];
A[e] = temp;
}
printf("\n\n");
printf("%08X %08X %08X %08X %08X",A[e],B[e],C[e],D[e],E[e]);//check the value before adding up
H[0] = ( H[0] + A[e]);
H[1] = ( H[1] + B[e]);
H[2] = ( H[2] + C[e]);
H[3] = ( H[3] + D[e]);
H[4] = ( H[4] + E[e]);
}
printf("\n\n");
printf("Message digest:");
for (i=0;i<5;i++)
{
printf("%X ",H[i]);
}
printf("\n\n");
return 0;
}
The wrong output of second block : CE3A1FD0 01464A63 F6766B50 AF97AC62 8D5DBBDD
The output of second block should be: 906FD62C 58C0AAC0 B6A55520 74E9B89D 9AF00B7F

Sending messages through LoRaWAN using STM32

How do I send the messages through LoRaWAN?
static void PrepareTxFrame( uint8_t port )
{
switch( port ) {
case 10: {
int pos = 0;
pc.printf("Prepare message\n");
#if 0
uint32_t tempValue = ( uint32_t )( LightValue * 1000000.0 );
AppData[0] = LightMode;
AppData[1] = ( ( tempValue & 0xFF000000 ) >> 24 ) & 0xFF;
AppData[2] = ( ( tempValue & 0x00FF0000 ) >> 16 ) & 0xFF;
AppData[3] = ( ( tempValue & 0x0000FF00 ) >> 8 ) & 0xFF;
AppData[4] = ( tempValue & 0x000000FF );
#else
AppData[pos] = count;
pc.printf("\n\r");
pc.printf("The value of the counter is : %d", count);
count++;
pc.printf("\n\r");
time_t seconds = time(NULL);
printf("The time is %s", ctime(&seconds));
AppData[++pos] = seconds;
pc.printf("%d \n %d", AppData[0], AppData[1]);
pc.printf("\n\r");
#endif
pc.printf("Message Ready\n");
}
break;
case 15: {
int pos = 0;
AppData[pos++] = AppLedStateOn;
#if 0
if( IsTxConfirmed == true )
{
AppData[pos++] = LoRaMacDownlinkStatus.DownlinkCounter >> 8;
AppData[pos++] = LoRaMacDownlinkStatus.DownlinkCounter;
AppData[pos++] = LoRaMacDownlinkStatus.Rssi >> 8;
AppData[pos++] = LoRaMacDownlinkStatus.Rssi;
AppData[pos++] = LoRaMacDownlinkStatus.Snr;
}
#endif
AppDataSize = pos;
}
break;
case 224:
if( ComplianceTest.LinkCheck == true ) {
ComplianceTest.LinkCheck = false;
AppDataSize = 3;
AppData[0] = 5;
AppData[1] = ComplianceTest.DemodMargin;
AppData[2] = ComplianceTest.NbGateways;
ComplianceTest.State = 1;
} else {
switch( ComplianceTest.State ) {
case 4:
ComplianceTest.State = 1;
break;
case 1:
AppDataSize = 2;
AppData[0] = ComplianceTest.DownLinkCounter >> 8;
AppData[1] = ComplianceTest.DownLinkCounter;
break;
}
}
break;
default:
break;
}
}
/*!
* \brief
*
* Prepares the pay-load of the frame
*
* \retval [0: frame could be send, 1: error]
*/
static bool SendFrame( void )
{
McpsReq_t mcpsReq;
LoRaMacTxInfo_t txInfo;
if( LoRaMacQueryTxPossible( AppDataSize, &txInfo ) != LORAMAC_STATUS_OK )
{
// Send empty frame in order to flush MAC commands
mcpsReq.Type = MCPS_UNCONFIRMED;
mcpsReq.Req.Unconfirmed.fBuffer = NULL;
mcpsReq.Req.Unconfirmed.fBufferSize = 0;
mcpsReq.Req.Unconfirmed.Datarate = LORAWAN_DEFAULT_DATARATE;
LoRaMacUplinkStatus.Acked = false;
LoRaMacUplinkStatus.Port = 0;
LoRaMacUplinkStatus.Buffer = NULL;
LoRaMacUplinkStatus.BufferSize = 0;
SerialDisplayUpdateFrameType( false );
} else {
LoRaMacUplinkStatus.Acked = false;
LoRaMacUplinkStatus.Port = AppPort;
LoRaMacUplinkStatus.Buffer = AppData;
LoRaMacUplinkStatus.BufferSize = AppDataSize;
SerialDisplayUpdateFrameType( IsTxConfirmed );
if( IsTxConfirmed == false ) {
mcpsReq.Type = MCPS_UNCONFIRMED;
mcpsReq.Req.Unconfirmed.fPort = AppPort;
mcpsReq.Req.Unconfirmed.fBuffer = AppData;
mcpsReq.Req.Unconfirmed.fBufferSize = AppDataSize;
mcpsReq.Req.Unconfirmed.Datarate = LORAWAN_DEFAULT_DATARATE;
} else {
mcpsReq.Type = MCPS_CONFIRMED;
mcpsReq.Req.Confirmed.fPort = AppPort;
mcpsReq.Req.Confirmed.fBuffer = AppData;
mcpsReq.Req.Confirmed.fBufferSize = AppDataSize;
mcpsReq.Req.Confirmed.NbTrials = 8;
mcpsReq.Req.Confirmed.Datarate = LORAWAN_DEFAULT_DATARATE;
}
}
if( LoRaMacMcpsRequest( &mcpsReq ) == LORAMAC_STATUS_OK ) {
return false;
}
return true;
}
Will the counter data and the time be sent? Also is the data in AppData the ones to be transmitted? I want the count and the timestamp to be sent every time the LoRa device transmits.
The payload to send (AppData) is given to the LoRaMAC layer through the MCPS (MAC Common Part Sublayer) request, e.g. for an unconfirmed frame:
mcpsReq.Req.Unconfirmed.fBuffer = AppData;
So physically (i.e. by RF), AppData is sent but it's encrypted and encapsulated before.
PrepareFrame() function builds the frame to send according to the PHYPayload scheme (See the "MAC Message Formats" part in the LoRaWAN™ Specification 1.0.2 document), following these fields:
MHDR (1 byte) Mac header
DevAddr (4 bytes) Address of the end-device
FCtrl (1 byte) Frame control
FCnt (2 bytes) Frame counter
FOpts (0 - 15 bytes) Frame options
FPort (0 - 1 byte) Port field
FRMPayload (0 - N bytes) MAC Frame Payload Encryption, your AppData encrypted
MIC (4 bytes) Message Integrity Code
FRMPayload is encrypted according to FPort. The encryption algorithm is based on AES 128.
If FPort = [1..255], the AppSKey key will be used to encrypt your payload.
Else (FPort = 0), it's encrypted by using the NwkSKey key.
See the LoRaMacPayloadEncrypt() function for more details.
PHYPayload will be encapsulated by the Radio PHY Layer and sent through RF.

How do I use the Mozilla NSS Root Certificate store on Windows, Mac, and Linux?

NSS comes with very little documentation, and a heavily vestigial API. How does it work? It is used for firefox on Window and Mac, and Chrome as well on linux. How do I install, uninstall, and check installation of my own Root Cert?
See this gist, here: https://gist.github.com/pehrlich/08852e8f7da81e136d70
The meat of it is CertificateNSS.cpp, copied here:
#include "stdafx.h"
#include "CertificateNSS.h"
#include "Certificate.h"
#include <boost/filesystem/operations.hpp>
#include <nss.h>
#include <cert.h>
#include <certdb.h>
ProfileLocker::ProfileLocker(const boost::filesystem::path& profilePath) : m_isValid(false)
{
GetSharedMutex().lock();
m_isValid = (NSS_InitReadWrite(profilePath.string().c_str()) == SECSuccess);
if (!m_isValid) {
GetSharedMutex().unlock();
}
}
ProfileLocker::~ProfileLocker()
{
if (m_isValid) {
NSS_Shutdown();
GetSharedMutex().unlock();
}
}
std::mutex& ProfileLocker::GetSharedMutex()
{
static std::mutex s_mutex;
return s_mutex;
}
std::vector<boost::filesystem::path> CertificateNSS::GetUserProfiles()
{
std::vector<boost::filesystem::path> profiles;
const auto path = GetProfilesDirectory();
if (!boost::filesystem::is_directory(path)) {
return profiles;
}
boost::filesystem::directory_iterator endIt;
for (boost::filesystem::directory_iterator it(path); it != endIt; ++it) {
if (boost::filesystem::is_directory(it->status())) {
profiles.push_back(it->path());
}
}
return profiles;
}
bool CertificateNSS::Install() const
{
std::string derCert = m_cert.GetBytes(CertEncoding::DER);
if (derCert.empty()) {
return false;
}
bool wasInstalled = false;
CERTCertDBHandle* certdb = CERT_GetDefaultCertDB();
if (certdb) {
SECItem cert = { siBuffer, (unsigned char*)derCert.c_str(), static_cast<unsigned int>(derCert.size()) };
SECItem* certArray[1] = { &cert };
SECCertUsage noOpUsage = certUsageUserCertImport; // Not used, but required
CERTCertificate** certificates = nullptr;
wasInstalled = (CERT_ImportCerts(certdb, noOpUsage, 1, certArray, &certificates, PR_TRUE, PR_TRUE,
const_cast<char*>(Certificate::GetNickname().c_str())) == SECSuccess);
if (certificates[0]) {
CERTCertTrust trust = { CERTDB_TRUSTED_CA | CERTDB_VALID_CA, 0, 0 };
CERT_ChangeCertTrust(certdb, certificates[0], &trust);
CERT_DestroyCertificate(certificates[0]);
}
}
return wasInstalled;
}
bool CertificateNSS::IsInstalled() const
{
std::string derCert = m_cert.GetBytes(CertEncoding::DER);
if (derCert.empty()) {
return false;
}
bool wasInstalled = false;
SECItem cert = { siBuffer, (unsigned char*)derCert.c_str(), static_cast<unsigned int>(derCert.size()) };
CERTCertDBHandle* certdb = CERT_GetDefaultCertDB();
if (certdb) {
CERTCertificate* certificate = CERT_FindCertByDERCert(certdb, &cert);
if (certificate) {
wasInstalled = true;
CERT_DestroyCertificate(certificate);
}
}
return wasInstalled;
}
bool CertificateNSS::Uninstall() const
{
std::string derCert = m_cert.GetBytes(CertEncoding::DER);
if (derCert.empty()) {
return false;
}
bool wasUninstalled = false;
SECItem cert = { siBuffer, (unsigned char*)derCert.c_str(), static_cast<unsigned int>(derCert.size()) };
CERTCertDBHandle* certdb = CERT_GetDefaultCertDB();
if (certdb) {
CERTCertificate* certificate = CERT_FindCertByDERCert(certdb, &cert);
if (certificate) {
wasUninstalled = (SEC_DeletePermCertificate(certificate) == SECSuccess);
CERT_DestroyCertificate(certificate);
}
}
return wasUninstalled;
}
bool CertificateNSS::UninstallAll()
{
bool wasUninstalled = true;
CERTCertDBHandle* certdb = CERT_GetDefaultCertDB();
if (!certdb) {
return true;
}
// Delete up to 100 profiles
for (int i = 0; i < 100; i++) {
bool failed = true;
CERTCertificate* certificate = CERT_FindCertByNickname(certdb, Certificate::GetNickname().c_str());
if (certificate) {
wasUninstalled = (SEC_DeletePermCertificate(certificate) == SECSuccess);
if (wasUninstalled) {
failed = false;
}
CERT_DestroyCertificate(certificate);
}
if (failed) {
break;
}
}
return wasUninstalled;
}

IOCP not getting triggered

I have writen an IOCP program and I am testing it through VPN.
It was all working OK, but then the server disconnected and the client GetQueuedCompletionStatus didn't trigger an exception.
I waited for one day,cbut it didn't get better. When I changed to a new VPN, the problem was solved, and I didn't get that problem later.
What's wrong? Has anybody seen the same problem before?
enter code here
enter code here
#include "XYTransport.h"
//---------------------------------------------------------------------------
#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
//---------------------------------------------------------------------------
#define XYTCP_LIST_CLIENT0 0
#define XYTCP_LIST_CLIENT1 1
//---------------------------------------------------------------------------
#define XYTRANSPORT_TYPE_TCP_OPEN 0
#define XYTRANSPORT_TYPE_TCP_RECV 1
#define XYTRANSPORT_TYPE_TCP_SEND 2
//---------------------------------------------------------------------------
typedef struct tagXYOVERLAPPED
{
OVERLAPPED o;
SOCKET s;
UINT flags;
WSABUF wb;
}XYOVERLAPPED, *PXYOVERLAPPED;
//---------------------------------------------------------------------------
inline LPVOID XYAlloc(HANDLE heap, UINT size)
{
return(HeapAlloc(heap, 0, size));
}
inline VOID XYFree(HANDLE heap, LPVOID lpdata)
{
HeapFree(heap, 0, lpdata);
}
inline PXYOVERLAPPED XYOverlappedPop(PXYTRANSPORT pt, LPBYTE buffer, SOCKET s)
{
PXYOVERLAPPED pto = NULL;
SOCKADDR_IN name;
if (buffer == NULL)
{
buffer = (LPBYTE)VirtualAlloc(NULL, pt->bufferlength, MEM_COMMIT, PAGE_READWRITE);
}
if (buffer != NULL)
{
pto = (PXYOVERLAPPED)MALLOC(sizeof(XYOVERLAPPED));
if (pto != NULL)
{
pto->wb.buf = (char *)buffer;
pto->wb.len = pt->bufferlength;
if (s == INVALID_SOCKET)
{
pto->s = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
if (pto->s != INVALID_SOCKET)
{
ZeroMemory(&name, sizeof(name));
name.sin_family = AF_INET;
name.sin_addr.S_un.S_addr = INADDR_ANY;
//name.sin_port = fn_htons(0);
name.sin_port = 0;
if (bind(pto->s, (const SOCKADDR *)&name, sizeof(name)) == 0)
{
if (CreateIoCompletionPort((HANDLE)pto->s, pt->hcompletion, (ULONG_PTR)pto->s, 0) == pt->hcompletion)
{
//
}
}
}
}
else
{
pto->s = s;
}
}
}
return(pto);
}
BOOL XYTCPPushReceive(PXYTRANSPORT pt, PXYOVERLAPPED pto, SOCKET s)
{
DWORD numberofbytes;
DWORD flags = 0;
BOOL result;
int error;
if (pto == NULL)
{
pto = XYOverlappedPop(pt, NULL, s);
}
ZeroMemory(&pto->o, sizeof(OVERLAPPED));
pto->flags = XYTRANSPORT_TYPE_TCP_RECV;
result = WSARecv(pto->s, &pto->wb, 1, &numberofbytes, &flags, &pto->o, NULL) != SOCKET_ERROR;
if (!result)
{
error = WSAGetLastError();
result = error == WSA_IO_PENDING;
if (!result)
{
printf("WSARecv\n");
}
}
return(result);
}
inline BOOL XYTCPPushSend(PXYTRANSPORT pt, PXYOVERLAPPED pto)
{
DWORD numberofbytes;
ULONG flags = MSG_PARTIAL;
BOOL result;
int error;
ZeroMemory(&pto->o, sizeof(OVERLAPPED));
pto->flags = XYTRANSPORT_TYPE_TCP_SEND;
//
pto->wb.len = 1024;
//
result = WSASend(pto->s, &pto->wb, 1, &numberofbytes, flags, &pto->o, NULL) != SOCKET_ERROR;
if (!result)
{
error = WSAGetLastError();
result = error == WSA_IO_PENDING;
if (!result)
{
printf("Send Error\n");
}
}
return(result);
}
DWORD WINAPI XYTransportWorkProc(LPVOID parameter)
{
PXYTRANSPORT pt = (PXYTRANSPORT)parameter;
HANDLE hcompletion = pt->hcompletion;
LPOVERLAPPED po;
PXYOVERLAPPED pto;
ULONG_PTR completionkey;
DWORD numberofbytes;
SOCKET s;
BOOL flag;
UINT type;
UINT count;
UINT error;
while(pt->working)
{
flag = GetQueuedCompletionStatus(hcompletion, &numberofbytes, &completionkey, &po, INFINITE);
if (po != NULL)
{
pto = (PXYOVERLAPPED)CONTAINING_RECORD(po, XYOVERLAPPED, o);
s = (SOCKET)completionkey;
type = pto->flags;
if (!flag)
{
//OutputDebugValue(_T("Except Error"), type, numberofbytes);
printf("Except Error %d\n", type);
}
if (numberofbytes == 0)
{
//OutputDebugValue(_T("Length Error"), type);
printf("Length Error %d\n", type);
}
if (!flag)
{
numberofbytes = 0;
}
switch (type)
{
case XYTRANSPORT_TYPE_TCP_OPEN:
if (flag)
{
setsockopt(s, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0);
XYTCPPushSend(pt, pto);
printf("connected\n");
if (!XYTCPPushReceive(pt, NULL, s))
{
//
}
else
{
printf("post recv\n");
}
break;
}
break;
case XYTRANSPORT_TYPE_TCP_RECV:
if (numberofbytes > 0)
{
XYTCPPushReceive(pt, pto, s);
//OutputDebugString(_T("Recv"));
printf("Recv %d\n", numberofbytes);
}
else
{
printf("Recv Error\n");
}
break;
case XYTRANSPORT_TYPE_TCP_SEND:
if (numberofbytes > 0)
{
XYTCPPushSend(pt, pto);
printf("Send %d\n", numberofbytes);
}
else
{
printf("Send Except\n");
}
break;
default:
break;
}
}
else
{
printf("Quit %d, %d", GetCurrentThreadId(), flag);
break;
}
}
return(0);
}
VOID XYTransportStartup(PXYTRANSPORT pt, UINT pagesize)
{
pt->hcompletion = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);
if (pt->hcompletion != INVALID_HANDLE_VALUE)
{
pt->lpfnConnectEx = NULL;
pt->bufferlength = pagesize;
pt->working = TRUE;
pt->hthread = CreateThread(NULL, 0, XYTransportWorkProc, (LPVOID)pt, 0, NULL);
}
}
BOOL XYTCPConnect(PXYTRANSPORT pt, const CHAR *host, USHORT port)
{
GUID id = WSAID_CONNECTEX;
DWORD numberofbytes = 0;
PXYOVERLAPPED pto;
SOCKADDR_IN name;
BOOL result = FALSE;
int error;
pto = XYOverlappedPop(pt, NULL, INVALID_SOCKET);
if (pt->lpfnConnectEx != NULL || WSAIoctl(pto->s, SIO_GET_EXTENSION_FUNCTION_POINTER, &id, sizeof(id), &pt->lpfnConnectEx, sizeof(pt->lpfnConnectEx), &numberofbytes, NULL, NULL) != SOCKET_ERROR)
{
ZeroMemory(&pto->o, sizeof(OVERLAPPED));
pto->flags = XYTRANSPORT_TYPE_TCP_OPEN;
ZeroMemory(&name, sizeof(name));
name.sin_family = AF_INET;
name.sin_port = htons(port);
name.sin_addr.S_un.S_addr = inet_addr(host);
if (name.sin_addr.S_un.S_addr != INADDR_NONE)
{
numberofbytes = 0;
result = pt->lpfnConnectEx(pto->s, (SOCKADDR *)&name, sizeof(name), NULL, 0, &numberofbytes, &pto->o);
if(!result)
{
error = WSAGetLastError();
result = error == ERROR_IO_PENDING;
if (!result)
{
printf("ConnectEx error\n");
}
}
}
}
return(result);
}
//---------------------------------------------------------------------------
the client Thrown an exception is what i desired,so i can know.
I am using C language to write. Under normal circumstances, disconnect one end and the other end will trigger an exception, but I have found that sometimes have to wait a very long time, at least I'm waiting for more than one day are not triggered, and sometimes even in the off time can continue to deliver WSASend success for some time.

UDP WSARecvMsg return WSAEWOULDBLOCK but Wireshark catch packets

I have a problem while reading data from UDP socket (port 7078). I've called WSARecvMsg function and received WSAEWOULDBLOCK error. But, Wireshark catch incoming UDP packet on port 7078! Please help me!
This is my code for creating and binding socket
static ortp_socket_t create_and_bind(const char *addr, int *port, int *sock_family, bool_t reuse_addr){
int err;
int optval = 1;
ortp_socket_t sock=-1;
char num[8];
struct addrinfo hints, *res0, *res;
if (*port==-1) *port=0;
if (*port==0) reuse_addr=FALSE;
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
snprintf(num, sizeof(num), "%d",*port);
err = getaddrinfo(addr,num, &hints, &res0);
if (err!=0) {
ortp_warning ("Error in getaddrinfo on (addr=%s port=%i): %s", addr, *port, gai_strerror(err));
return -1;
}
for (res = res0; res; res = res->ai_next) {
sock = socket(res->ai_family, res->ai_socktype, 0);
if (sock==-1)
continue;
if (reuse_addr){
err = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,
(SOCKET_OPTION_VALUE)&optval, sizeof (optval));
if (err < 0)
{
ortp_warning ("Fail to set rtp address reusable: %s.", getSocketError());
}
}
err = 0;
switch (res->ai_family) {
default:
case AF_INET:
break;
case AF_INET6:
break;
}
if (err < 0) {
ortp_warning("Fail to set recv TTL/HL socket option: %s.", getSocketError());
}
*sock_family=res->ai_family;
err = bind (sock, res->ai_addr, res->ai_addrlen);
if (err != 0){
ortp_debug ("Fail to bind rtp socket to (addr=%s port=%i) : %s.", addr, *port, getSocketError());
close_socket (sock);
sock=-1;
continue;
}
switch (res->ai_family)
{
case AF_INET:
if (IN_MULTICAST(ntohl(((struct sockaddr_in *) res->ai_addr)->sin_addr.s_addr)))
{
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *) res->ai_addr)->sin_addr.s_addr;
mreq.imr_interface.s_addr = INADDR_ANY;
err = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (SOCKET_OPTION_VALUE) &mreq, sizeof(mreq));
if (err < 0){
ortp_warning ("Fail to join address group: %s.", getSocketError());
close_socket (sock);
sock=-1;
continue;
}
}
break;
case AF_INET6:
if (IN6_IS_ADDR_MULTICAST(&(((struct sockaddr_in6 *) res->ai_addr)->sin6_addr)))
{
struct ipv6_mreq mreq;
mreq.ipv6mr_multiaddr = ((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
mreq.ipv6mr_interface = 0;
err = setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (SOCKET_OPTION_VALUE)&mreq, sizeof(mreq));
if (err < 0)
{
ortp_warning ("Fail to join address group: %s.", getSocketError());
close_socket (sock);
sock=-1;
continue;
}
}
break;
}
break;
}
freeaddrinfo(res0);
#if defined(WIN32) || defined(_WIN32_WCE)
if (ortp_WSARecvMsg == NULL) {
GUID guid = WSAID_WSARECVMSG;
DWORD bytes_returned;
if (WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid),
&ortp_WSARecvMsg, sizeof(ortp_WSARecvMsg), &bytes_returned, NULL, NULL) == SOCKET_ERROR) {
ortp_warning("WSARecvMsg function not found.");
}
}
#endif
if (sock!=-1){
set_non_blocking_socket (sock);
if (*port==0){
struct sockaddr_storage saddr;
socklen_t slen=sizeof(saddr);
err=getsockname(sock,(struct sockaddr*)&saddr,&slen);
if (err==-1){
ortp_error("getsockname(): %s",getSocketError());
close(sock);
return (ortp_socket_t)-1;
}
err=getnameinfo((struct sockaddr*)&saddr, slen, NULL, 0, num, sizeof(num), NI_NUMERICHOST | NI_NUMERICSERV);
if (err!=0){
ortp_error("getnameinfo(): %s",gai_strerror(err));
close(sock);
return (ortp_socket_t)-1;
}
*port=atoi(num);
}
}
return sock;
}
And I use WSAIoctl to get WSARECVMSG function pointer
typedef INT (WINAPI * LPFN_WSARECVMSG)(SOCKET, LPWSAMSG, LPDWORD, LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE);
static LPFN_WSARECVMSG ortp_WSARecvMsg = NULL;
if (ortp_WSARecvMsg == NULL) {
GUID guid = WSAID_WSARECVMSG;
DWORD bytes_returned;
if (WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid),
&ortp_WSARecvMsg, sizeof(ortp_WSARecvMsg), &bytes_returned, NULL, NULL) == SOCKET_ERROR) {
ortp_warning("WSARecvMsg function not found.");
}
}
My code for receiving data
int rtp_session_rtp_recv_abstract(ortp_socket_t socket, mblk_t *msg, int flags, struct sockaddr *from, socklen_t *fromlen) {
int ret;
int bufsz = (int) (msg->b_datap->db_lim - msg->b_datap->db_base);
char control[512];
WSAMSG msghdr;
WSACMSGHDR *cmsghdr;
WSABUF data_buf;
DWORD bytes_received;
if (ortp_WSARecvMsg == NULL) {
return recvfrom(socket, (char *)msg->b_wptr, bufsz, flags, from, fromlen);
}
memset(&msghdr, 0, sizeof(msghdr));
memset(control, 0, sizeof(control));
if(from != NULL && fromlen != NULL) {
msghdr.name = from;
msghdr.namelen = *fromlen;
}
data_buf.buf = (char *)msg->b_wptr;
data_buf.len = bufsz;
msghdr.lpBuffers = &data_buf;
msghdr.dwBufferCount = 1;
msghdr.Control.buf = control;
msghdr.Control.len = sizeof(control);
msghdr.dwFlags = flags;
ret = ortp_WSARecvMsg(socket, &msghdr, &bytes_received, NULL, NULL);
if(fromlen != NULL)
*fromlen = msghdr.namelen;
if(ret >= 0) {
ret = bytes_received;
}
else
{
int i;
long m_ErrorCode = WSAGetLastError();
i = 0;
}
return ret;
}