Implementing mbedtls and xTaskCreate() causing memory leak on ESP32 (Arduino IDE) - esp32

So i have the code below. If i directly call signKey() function in the loopTask, the free heap is stable. However if i use that function to create task using xTaskCreate(), the free heap is always decreasing. Am i missing something?
Here is the output on the Serial Monitor using direct call:
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
Here is the output on the Serial Monitor using task:
FreeHeap: 338364
FreeHeap: 337776
FreeHeap: 337228
FreeHeap: 336632
FreeHeap: 336080
FreeHeap: 335508
FreeHeap: 334960
FreeHeap: 334372
FreeHeap: 333812
FreeHeap: 333220
FreeHeap: 332672
FreeHeap: 332108
FreeHeap: 331552
FreeHeap: 330964
FreeHeap: 330416
FreeHeap: 329856
FreeHeap: 329304
FreeHeap: 328716
FreeHeap: 328152
And here is the code:
#include "mbedtls/pk.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
static String privateKey = "-----BEGIN PRIVATE KEY-----\nMIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCID48Vp/9ydCMU\nzZ4n4iQ6pzr6eK+VCL7LcpY8j/tBwLWk3jZ3ETmMm6Ua4MhUMc3ABN84uz0RgDi9\nb4RhOUy2SVbvfm5WZhlvpPmDD0yeTgWEyM3h3fBYPnRzMn/6KjsmCUgcfTWjdA+C\nj9vTL41j7bVCkU0/glBh5Rk3rKeImeX/lf4KfstguvJ+OlznCn039+tDlsCNrRgw\ni+L2AeI4UDZEDGWYRbONzU2WgJ11fr9J+Y6rSCwommDcxhdTtdlorZj2CFEtxRp5\nFCDm6Tvu0+aur8zpuhC+NFUWmYEHxztz18X1I4Pcy5cJpuqKL5t/Hxy5Yu7y32Ek\nE8DZv1DFAgMBAAECggEBAIBF+uW13tSuvSwttf9v6iwJ4UamZRKijg4MV6t9KqoQ\n3q8yeDLE4Ha5fmzaosMNuSZg8XnwvGA1fEjMTAfFF5d7iSR9E9UMqMpixIFU+Sz9\n7aIEFmXs8VygdPTuFU1qZx0y/vMs8FbLYpv6uIpfeHNPdeXuSt+nIdVJQf8FHWVg\nH7EJHJPCh0SoQZHQhV0M/n7K6iacXdC2k4AW2f2KtwPBOV19S+4Ymq7S6ycIyghd\nmMzMhWLgZYoPycMYQRDErEZOSHQHs+BqvKYqp/UVJNKAVihiqYXHmT8hnWMaaj8d\nQzVmcsq7dZO7vX+0Zfjd+krj9gbpCG30ESeNOx5sLAECgYEA0wDiGFyFAu6fVhm5\np4pHhGhFK765Ys3b5bapEgD1uN92BttPat2Qj11TKGdAERa8X0uuBB8McGcWUcvV\nFUIKYE0qj4k/oo7OEw5KmrQVlQLsWv4rls8XTEJcUnoq2lCTXZEfuwEJFBkk4Bkb\nhioZE3CU0cV/Jg78vl37SJZbE4ECgYEApRNmRPCDWH8Jeo7OSqgee8Qy46R+JpBb\nmaaQ9dCO8pp5MYLQSA4C4BeHEpKq4v6C3HL7gf+Z6N/6/WU1X1bqDtXPdito5Zxc\nQ0Sa6URIPu7/txNU4Nc4GOfB6nG0/bxiQRDkxf7Kwk2E8xpmoCAQwDhg58Y1k61q\nO/iTjIJOj0UCgYEAo7yDtrPU47mYG5BK6R/871qakp+l7G4ivddIy5fDFnsRc7Cr\nqBnXG+knpqq4pIooEyr/FmOhm3fjcgXijGR6+M/ovwmaP+LhNxhX/ETSmpdyIgoq\neRSq15qHWdlDd7YfJPSA0vSyvs3kN6JEIZB5dQRf94hyam4m4vK7FFDYzAECgYEA\nlBiva7ILZF20d0ufL8NcddUzgp+UvaxNQa/55U7SsDx99jlR+xL26WyyNat3vGZx\nqK1PjvVtc0tete8SzxH+soiHs5CGb1i0PXVTNWuZFTz+FZU2VPFA1rc1dcvFgM59\np7osRKWt6lv5ptBMueOKo6jw538fmfm+kUcVuL0/FbECgYBx9ADNvyUaPq/3rQEa\n4Nzp+yyBL8r7iguLvI8EAYbCil9lACL+xXtScQ7mCY8EW8D8w/0cqA3Wjamb5ntS\n4T9Id1Iqq6MvzgJlTjNAYrsgoEC+fmU8iPnHNjxXrf74j4Mlh9pm5j6yeYsHQnMI\nv60FP7rcRiL2XnDJ5/ev/BWXaQ==\n-----END PRIVATE KEY-----";
static bool isTask = false;
static bool printSerial = false;
const char base64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
static String base64_encode(const uint8_t *bytesToEncode, uint16_t len) {
String ret;
int i = 0;
int j = 0;
unsigned char char_array_3[3];
unsigned char char_array_4[4];
while (len--) {
char_array_3[i++] = *(bytesToEncode++);
if (i == 3) {
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (i = 0; (i < 4); i++) {
ret += base64_chars[char_array_4[i]];
}
i = 0;
}
}
if (i) {
for (j = i; j < 3; j++) {
char_array_3[j] = '\0';
}
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (j = 0; (j < i + 1); j++) {
ret += base64_chars[char_array_4[j]];
}
}
return ret;
}
static String base64_encode(String str) {
return base64_encode((const unsigned char *) str.c_str(), str.length());
}
uint8_t buffer[2000];
static void signKey(void *parameter) {
String header = "{\"typ\":\"JWT\",\"alg\":\"RS256\"}";
String payload = "{\"payload\":\"my-payload\"}";
String content = base64_encode(header) + "." + base64_encode(payload);
mbedtls_pk_context pk_context;
mbedtls_pk_init(&pk_context);
int rc = mbedtls_pk_parse_key(&pk_context, (uint8_t*)privateKey.c_str(), privateKey.length() + 1, NULL, 0);
if (rc != 0) {
mbedtls_pk_free(&pk_context);
if (printSerial)Serial.println("Failed to parse private key (err_code: 0x" + String(rc, HEX) + ")");
if (isTask)vTaskDelete(NULL);
}
mbedtls_entropy_context entropy;
mbedtls_entropy_init(&entropy);
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_ctr_drbg_init(&ctr_drbg);
const char* pers = "firebase-jwt";
mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char*)pers, strlen(pers));
uint8_t digest[32];
rc = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), (uint8_t*)content.c_str(), content.length(), digest);
if (rc != 0) {
mbedtls_pk_free(&pk_context);
mbedtls_entropy_free(&entropy);
mbedtls_ctr_drbg_free(&ctr_drbg);
if (printSerial)Serial.println("Failed to digest content (err_code: 0x" + String(rc, HEX) + ")");
if (isTask)vTaskDelete(NULL);
}
size_t retSize;
rc = mbedtls_pk_sign(&pk_context, MBEDTLS_MD_SHA256, digest, sizeof(digest), buffer, &retSize, mbedtls_ctr_drbg_random, &ctr_drbg);
if (rc != 0) {
mbedtls_pk_free(&pk_context);
mbedtls_entropy_free(&entropy);
mbedtls_ctr_drbg_free(&ctr_drbg);
if (printSerial)Serial.println("Failed to sign content (err_code: 0x" + String(rc, HEX) + ")");
if (isTask)vTaskDelete(NULL);
}
String signature = base64_encode(buffer, retSize);
if (printSerial)Serial.println(signature);
mbedtls_pk_free(&pk_context);
mbedtls_entropy_free(&entropy);
mbedtls_ctr_drbg_free(&ctr_drbg);
if (isTask)vTaskDelete(NULL);
}
void tryTask() {
isTask = true;
xTaskCreate(signKey, "signKey", 4096, NULL, 1, NULL);
}
void tryDirectCall() {
isTask = false;
signKey(NULL);
}
void setup() {
Serial.begin(115200);
}
void loop() {
tryTask();
//tryDirectCall();
Serial.println("FreeHeap: " + String(ESP.getFreeHeap()));
delay(5000);
}
UPDATE:
I tried to create task on the setup() and made the task looping continuously, the decreasing free heap didn't occured! So the issue only exist when i dynamically creating and deleting task. Why would this happen?

The ESP32 has two types of memory - data and instruction. The Arduino wrapper returns rather liberal interpretation of free heap - the queried cabability MALLOC_CAP_INTERNAL probably includes both types. So it might be just code cache being filled with garbage from single use threads.
That, or you're leaking. In any case, single-use threads are not a commonly used practice on micros - they make everything harder, including such analysis. Standard approach is to create a permanent FreeRTOS task at startup and pass it work items through a message queue whenever it has to do something. I can recommend the FreeRTOS tutorial as an excellent resource.

Related

STM32U575I-EV: While debugging I get an error and this function is called: void HardFault_Handler (void)

The error is generated in this part of the code and precisely here:
writeVal[j] = RBF1[i+1];
I am attaching the code:
#define _FPGA_UPLOAD_C_
#include "globdefs.h"
extern SPI_HandleTypeDef hspi1;
#define MEMORY_ADDR1 ((uint32_t)0x64000000) //FMC_BANK1_2
const uint8_t RBF1[] ={0xA0,0xFF,0x02,0x6A,0xE7,0x82,0xF7,0x07,0xE7,0xF7,0xE7,0xF1,0xFB,0xF1,0xF9,0x82,0xFB,0x83,0xF9,0x08};
uint16_t* fpgaRegx1 = (uint16_t*)FMC_BANK1_1; // FMC_BANK1_1: 0x60000000UL
int8_t FPGA_Loading(char TypeRBF)
{
HAL_GPIO_WritePin(NCONFIG_CYCLONE_GPIO_Port,NCONFIG_CYCLONE_Pin, GPIO_PIN_RESET);
Delay3micro();
HAL_GPIO_WritePin(NCONFIG_CYCLONE_GPIO_Port,NCONFIG_CYCLONE_Pin, GPIO_PIN_SET);
Delay3micro();
int i=0;
uint8_t* writeVal = (uint8_t*)(MEMORY_ADDR1 + sizeof(RBF1));
uint16_t loadOK = 0;
while (hspi1.State != HAL_SPI_STATE_READY)
{};
while (i < sizeof(RBF1))
{
uint8_t n = RBF1[i] & 0x7f;
if (RBF1[i] & 0x80)
{
for (int j=0; j<n; j++){
writeVal[j] = RBF1[i+1];
}
i += 2;
}
else
{
for (int j=0; j<n; j++)
writeVal[j] = RBF1[i+j+1];
i += (n+1);
}
if(HAL_SPI_Transmit (&hspi1, (uint8_t *) writeVal, n, 100)!=HAL_OK)
{
Error_Handler();
}
}
Delay3micro();
Delay3micro();
HAL_SPI_MspDeInit(&hspi1); //spengo l'spi usata per la programmazione dell'fpga
loadOK = fpgaRegx1[0];
loadOK &= 0xF000;
if (loadOK == (uint16_t)0xA000)
{
loadOK=1;
}
else
{
loadOK=0;
//Error_Handler();
}
return loadOK;
}
I tried to generate a new, simpler project by inserting only the code I entered above and I don't get any errors. At this point I have always added on the new project through CubeIDE FILEX, THREADX and SDMMC1 the latter generates the same error written above. For FILEX, THREADX and SDMMC1 the code is only the one generated by CubeIDE.

When simulate input events using windows header it stops the program until give a interrupt manually

Here is the program which i created to simulate multiple input events to give some interrupt for another process using windows header.
This program generate number of left click events ,right click events,mouse cursor move event and key board input events.
#pragma once
class InputEventGenerator
{
public:
InputEventGenerator();
~InputEventGenerator();
static void simulatekeyPressEvent(int keyPressCount);
static void simulateMouseLeftClick(int clickCount);
static void simulateMouseRightClick(int clickCount);
static void simulateMouseCurserMove();
private:
InputEventGenerator(const InputEventGenerator&) = delete;
InputEventGenerator operator=(const InputEventGenerator&) = delete;
};
This is the .cpp file
#include "InputEventGenerator.h"
#include <iostream>
#include <windows.h>
#include<atlbase.h>
#include <atlwin.h>
void InputEventGenerator::simulatekeyPressEvent(int keyPressCount)
{
std::cout << "simulate key press event" << std::endl;
INPUT ip;
int KeyPress = keyPressCount;
Sleep(3000);
while (KeyPress > 0)
{
ip.type = INPUT_KEYBOARD; // Set up a generic keyboard event.
ip.ki.wScan = 0; // hardware scan code for key
ip.ki.time = 0;
ip.ki.dwExtraInfo = 0;
ip.ki.wVk = 0x41; //Press the "A" key virtual-key code for the "a" key
ip.ki.dwFlags = 0; // 0 for key press
SendInput(1, &ip, sizeof(INPUT));
ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
//Release the "A" key
SendInput(1, &ip, sizeof(INPUT));
std::cout << "key press done" << std::endl;
Sleep(3000);
--KeyPress;
}
}
void InputEventGenerator::simulateMouseLeftClick(int clickCount)
{
int click_count = clickCount;
std::cout << "Left click started" << std::endl;
SetCursorPos(748, 294);
while (click_count > 0)
{
INPUT input = { 0 };
input.type = INPUT_MOUSE;
input.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTDOWN;
SendInput(1, &input, sizeof(INPUT));
Sleep(200);
input.type = INPUT_MOUSE;
input.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTUP;
SendInput(1, &input, sizeof(input));
Sleep(200);
std::cout << "left mouse click done" << std::endl;
//::ZeroMemory(&input, sizeof(INPUT));
click_count--;
}
}
void InputEventGenerator::simulateMouseRightClick(int clickCount)
{
int click_count = clickCount;
std::cout << "Right click started" << std::endl;
SetCursorPos(748, 294);
while (click_count > 0)
{
INPUT input = { 0 };
input.type = INPUT_MOUSE;
input.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_RIGHTDOWN;
SendInput(1, &input, sizeof(INPUT));
Sleep(200);
input.type = INPUT_MOUSE;
input.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_RIGHTUP;
SendInput(1, &input, sizeof(input));
std::cout << "right mouse click done" << std::endl;
Sleep(200);
//::ZeroMemory(&input, sizeof(INPUT));
click_count--;
}
}
void InputEventGenerator::simulateMouseCurserMove()
{
std::cout << "simulate mouse move" << std::endl;
POINT p;
SetCursorPos(0, 0);
int loopCount = 100;
while (loopCount > 0)
{
GetCursorPos(&p);
p.x += 10;
p.y += 10;
INPUT input;
input.type = INPUT_MOUSE;
input.mi.mouseData = 0;
input.mi.time = 0;
input.mi.dx = p.x*(65536 / GetSystemMetrics(SM_CXSCREEN));
input.mi.dy = p.y*(65536 / GetSystemMetrics(SM_CYSCREEN));
input.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_VIRTUALDESK |MOUSEEVENTF_ABSOLUTE;
SendInput(1, &input, sizeof(input));
Sleep(500);
--loopCount;
}
}
This is the main function
#include "InputEventGenerator.h"
#include<atlbase.h>
#include <atlwin.h>
int main(int argc, char * argv[])
{
InputEventGenerator::simulateMouseCurserMove();
Sleep(20);
InputEventGenerator::simulateMouseRightClick(10);
Sleep(20);
InputEventGenerator::simulatekeyPressEvent(5);
Sleep(20);
InputEventGenerator::simulateMouseLeftClick(10);
Sleep(20);
return 0;
}
Here in the main function at simulateMouseLeftClick() call it stops the program and wait until press Enter.I don't understand the process behind this

Unable to communicate between libwebsocket as client and socket.io as server

This is client code by using libwebsocket version 1.5
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <string.h>
#include <assert.h>
#include <signal.h>
#include <syslog.h>
#include <sys/time.h>
#include <unistd.h>
#include <libwebsockets.h>
static volatile int force_exit = 0;
static int state, command_received = 0, forked = 0;
#define MAX_ECHO_PAYLOAD 1400
#define LOCAL_RESOURCE_PATH "./"
struct per_session_data {
unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + MAX_ECHO_PAYLOAD + LWS_SEND_BUFFER_POST_PADDING];
unsigned int len;
};
//for temporary storing data from tcpdump
struct per_session_data data1;
static int callback_echo(struct libwebsocket_context *context, struct libwebsocket *wsi, enum libwebsocket_callback_reasons reason, void *user, void *in, size_t len)
{
struct per_session_data *pss = (struct per_session_data *)user;
int n;
switch (reason) {
/* when the callback is used for client operations --> */
case LWS_CALLBACK_CLOSED:
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
printf("Closed\n");
state = 0;
break;
case LWS_CALLBACK_ESTABLISHED:
case LWS_CALLBACK_CLIENT_ESTABLISHED:
printf("Client connected\n");
state = 2;
break;
/* we will receive our packet here*/
case LWS_CALLBACK_RECEIVE:
case LWS_CALLBACK_CLIENT_RECEIVE:
printf("Rx from server: %s\n", (char *)in);
if (!strcmp((char *)in, "tcpdump"))
{
command_received = 1;
}
break;
/* we will send our packet here */
case LWS_CALLBACK_CLIENT_WRITEABLE:
printf("client writing to server\n");
pss->len = sprintf((char *)&pss->buf[LWS_SEND_BUFFER_PRE_PADDING], "%s", data1.buf + LWS_SEND_BUFFER_PRE_PADDING);
n = libwebsocket_write(wsi, &pss->buf[LWS_SEND_BUFFER_PRE_PADDING], pss->len, LWS_WRITE_TEXT);
printf("Data: %s\n\n\n\n\n\n\n", &pss->buf[LWS_SEND_BUFFER_PRE_PADDING]);
//error handling for write fail and partial writes
if (n < 0) {
printf("ERROR %d writing to socket, hanging up\n", n);
return -1;
}
if (n < (int)pss->len) {
printf("Partial write\n");
return -1;
}
break;
default:
printf("default...\n");
break;
}
return 0;
}
/* List of available protocols */
static struct libwebsocket_protocols protocols[] = {
{
"default", /* name */
callback_echo, /* callback */
sizeof(struct per_session_data) /* per_session_data_size */
},
{
NULL, NULL, 0 /* End of list */
}
};
void sighandler(int sig)
{
force_exit = 1;
}
int main(int argc, char **argv)
{
//pipe stuff
int pipe_fd[2];
if (pipe(pipe_fd) < 0)
{
perror("PIPE:");
exit(-1);
}
//for libwebsocket_service
int n = 0;
//test port can be overidden
int port = 9000;
struct libwebsocket_context *context;
int opts = 0;
char interface_name[128] = "";
const char *interface = NULL;
int use_ssl = 0;
char ssl_cert[256] = LOCAL_RESOURCE_PATH"/libwebsockets-test-server.pem";
char ssl_key[256] = LOCAL_RESOURCE_PATH"/libwebsockets-test-server.key.pem";
int listen_port = 80;
struct lws_context_creation_info info;
char passphrase[256];
char uri[256] = "/";
char address[256], ads_port[256 + 30];
//lws servicing time intervals
int rate_us = 250000;
unsigned int oldus = 0;
struct libwebsocket *wsi;
//should check this
int debug_level = 2;
memset(&info, 0, sizeof info);
lwsl_notice("Built to support client operations\n");
//re-configuring server ip and port here
if (argc == 3)
{
strncpy(address, argv[1], sizeof(address) - 1);
address[sizeof(address) - 1] = '\0';
port = atoi(argv[2]);
}
else if (argc == 1)
{
strncpy(address, "localhost", sizeof(address) - 1);
address[sizeof(address) - 1] = '\0';
port = 9000;
}
else
{
printf("Try: ./client.exec <ip> <port>\n");
exit(-1);
}
/* we will only try to log things according to our debug_level */
setlogmask(LOG_UPTO (LOG_DEBUG));
openlog("lwsts", 0, LOG_DAEMON);
/* tell the library what debug level to emit and to send it to syslog */
lws_set_log_level(debug_level, lwsl_emit_syslog);
lwsl_notice("libwebsockets echo test - "
"(C) Copyright 2010-2015 Andy Green <andy#warmcat.com> - "
"licensed under LGPL2.1\n");
lwsl_notice("Running in client mode\n");
listen_port = CONTEXT_PORT_NO_LISTEN;
lwsl_info("requiring server cert validation againts %s\n", ssl_cert);
info.ssl_ca_filepath = ssl_cert;
info.port = listen_port;
info.iface = interface;
info.protocols = protocols;
#ifndef LWS_NO_EXTENSIONS
info.extensions = libwebsocket_get_internal_extensions();
#endif
info.gid = -1;
info.uid = -1;
info.options = opts;
context = libwebsocket_create_context(&info);
if (context == NULL) {
lwsl_err("libwebsocket init failed\n");
return -1;
}
signal(SIGINT, sighandler);
n = 0;
while (n >= 0 && !force_exit)
{
//do connect only once
if (!state) {
state = 1;
printf("Client connecting to %s:%u....\n", address, port);
address[sizeof(address) - 1] = '\0';
sprintf(ads_port, "%s:%u", address, port & 65535);
wsi = libwebsocket_client_connect(context, address, port, use_ssl, uri, ads_port, ads_port, NULL, -1);
if (!wsi) {
printf("Client failed to connect to %s:%u\n", address, port);
goto bail;
}
}
if (command_received == 1 && !forked)
{
printf("Going to fork\n");
forked = 1;
pid_t child_pid = fork();
if (child_pid == -1)
{
perror("FORK:");
exit(-1);
}
else if (child_pid == 0)
{
close(pipe_fd[0]);
printf("Starting tcpdump\n");
if (dup2(pipe_fd[1], 1) < 0)
{
perror("DUP2:");
exit(-1);
}
//closing the connection to server for child
libwebsocket_context_destroy(context);
closelog();
char *cmd[] = {"tcpdump", "-i", "any", NULL};
if (execv("/usr/sbin/tcpdump", cmd) < 0)
{
perror("EXECV:");
exit(-1);
}
}
}
/* if (forked == 1)
{
close(pipe_fd[1]);
}
*/
if (command_received == 1)
{
//stay here if the pipe is empty else try to read max 1400 bytes of data
while ((data1.len = read(pipe_fd[0], data1.buf + LWS_SEND_BUFFER_PRE_PADDING, 1400)) <= 0);
//check if server wants any service
//printf("%s\n\n\n\n\n\n\n", data1.buf + LWS_SEND_BUFFER_PRE_PADDING);
libwebsocket_callback_on_writable(context, wsi);
}
//This fn times out every 10usec
n = libwebsocket_service(context, 10);
}
//bail: jump from while loop also if connect fails
bail:
libwebsocket_context_destroy(context);
printf("libwebsockets-test-echo exited cleanly\n");
closelog();
return 0;
}
This is my server code by using socket.io
var io = require('socket.io')();
var middleware = require('socketio-wildcard')();
io.use(middleware);
io.on('connection', function(socket) {
console.log('On socket connection')
socket.on('*', function(event, data){
console.log("---- Event ----- : " + JSON.stringify(event));
console.log("---- Data ----- : " + JSON.stringify(data))
});
});
io.listen(9000, 'localhost');
The client is unable to connect with server. when i tested client with strace it infinitely does receive as below
recv(8, "", 1, 0) = 0
recv(8, "", 1, 0) = 0
recv(8, "", 1, 0) = 0
.
.
.
.
Please point out my mistake. Any help is appreciated.
Thanks

MFRC 522 with ATmega8. Mifare Classic 1K won't authenticate

I have a problem with an ATmega8 and Mifare RC-522 based NFC/RFID controller.
I'm using this library and I've managed to read the UID of a card.
However, I'd like to also read and write other parts of the card but whenever I try to use the MFRC522_Auth function I don't get the idle interrupt which I should, instead it gives me LoAlertIrq saying that FIFObuffer is almost empty.
Here are the docs for the reader and the card, and below are relevant parts of my code.
main.c :
byte = mfrc522_request(PICC_REQALL,str);
if(byte == CARD_FOUND)
{
byte = mfrc522_get_card_serial(str);
if(byte == CARD_FOUND)
{
byte = mfrc522_auth(PICC_AUTHENT1A, 7, sectorKeyA, str);
if( (byte == CARD_FOUND) )
{
byte = MFRC522_Read1(4, str);
if(byte == CARD_FOUND)
{
//write content of that block
}
}
}
Relevant functions from the library :
void mfrc522_write(uint8_t reg, uint8_t data)
{
ENABLE_CHIP();
spi_transmit((reg<<1)&0x7E);
spi_transmit(data);
DISABLE_CHIP();
}
uint8_t mfrc522_read(uint8_t reg)
{
uint8_t data;
ENABLE_CHIP();
spi_transmit(((reg<<1)&0x7E)|0x80);
data = spi_transmit(0x00);
DISABLE_CHIP();
return data;
}
uint8_t mfrc522_to_card(uint8_t cmd, uint8_t *send_data, uint8_t send_data_len, uint8_t *back_data, uint32_t *back_data_len)
{
uint8_t status = 0;
uint8_t irqEn = 0x00;
uint8_t waitIRq = 0x00;
uint8_t lastBits;
uint8_t n;
uint8_t tmp;
uint32_t i;
switch (cmd)
{
case MFAuthent_CMD: //Certification cards close
{
irqEn = 0x12;
waitIRq = 0x10;
break;
}
case Transceive_CMD: //Transmit FIFO data
{
irqEn = 0x77;
waitIRq = 0x30;
break;
}
default:
break;
}
mfrc522_write(ComIEnReg, irqEn|0x80); //Interrupt request
n=mfrc522_read(ComIrqReg);
mfrc522_write(ComIrqReg,n&(~0x80));//clear all interrupt bits
n=mfrc522_read(FIFOLevelReg);
mfrc522_write(FIFOLevelReg,n|0x80);//flush FIFO data
// mfrc522_write(CommandReg, Idle_CMD); //NO action; Cancel the current cmd???
n=mfrc522_read(CommandReg);
mfrc522_write(CommandReg,n|0x00);
//Writing data to the FIFO
for (i=0; i<send_data_len; i++)
{
mfrc522_write(FIFODataReg, send_data[i]);
}
//Execute the cmd
mfrc522_write(CommandReg, cmd);
if (cmd == Transceive_CMD)
{
n=mfrc522_read(BitFramingReg);
mfrc522_write(BitFramingReg,n|0x80);
}
//Waiting to receive data to complete
i = 2000; //i according to the clock frequency adjustment, the operator M1 card maximum waiting time 25ms???
while (1) {
n = mfrc522_read(ComIrqReg); // ComIrqReg[7..0] bits are: Set1 TxIRq RxIRq IdleIRq HiAlertIRq LoAlertIRq ErrIRq TimerIRq
if (n & waitIRq) { // One of the interrupts that signal success has been set.
break;
}
if (n & 0x01) { // Timer interrupt - nothing received in 25ms
// return 6; //debug purpose
if (cmd == MFAuthent_CMD) {
LCD_Clear();
LCD_WriteTextXY(1, 3, LCD_itoa( mfrc522_read(ComIrqReg) ) );
_delay_ms(2500);
}
break;
}
if (--i == 0) { // The emergency break. If all other condions fail we will eventually terminate on this one after 35.7ms. Communication with the MFRC522 might be down.
if (cmd == MFAuthent_CMD) {
LCD_Clear();
LCD_WriteTextXY(1, 3, LCD_itoa( mfrc522_read(ComIrqReg) ) );
_delay_ms(2500);
}
break;
}
}
tmp=mfrc522_read(BitFramingReg);
mfrc522_write(BitFramingReg,tmp&(~0x80));
if (i != 0)
{
if(!(mfrc522_read(ErrorReg) & 0x1B)) //BufferOvfl Collerr CRCErr ProtecolErr
{
status = CARD_FOUND;
if (n & irqEn & 0x01)
{
status = CARD_NOT_FOUND; //??
}
if (cmd == Transceive_CMD)
{
n = mfrc522_read(FIFOLevelReg);
lastBits = mfrc522_read(ControlReg) & 0x07;
if (lastBits)
{
*back_data_len = (n-1)*8 + lastBits;
}
else
{
*back_data_len = n*8;
}
if (n == 0)
{
n = 1;
}
if (n > MAX_LEN)
{
n = MAX_LEN;
}
//Reading the received data in FIFO
for (i=0; i<n; i++)
{
back_data[i] = mfrc522_read(FIFODataReg);
}
}
}
if (cmd == MFAuthent_CMD) {
LCD_WriteTextXY(1, 10, LCD_itoa16( mfrc522_read(Status2Reg) ) );
_delay_ms(2500);
}
} else status = 9;
return status;
}
uint8_t mfrc522_get_card_serial(uint8_t * serial_out)
{
uint8_t status;
uint8_t i;
uint8_t serNumCheck=0;
uint32_t unLen;
mfrc522_write(BitFramingReg, 0x00); //TxLastBists = BitFramingReg[2..0]
serial_out[0] = PICC_ANTICOLL;
serial_out[1] = 0x20;
status = mfrc522_to_card(Transceive_CMD, serial_out, 2, serial_out, &unLen);
if (status == CARD_FOUND)
{
//Check card serial number
for (i=0; i<4; i++)
{
serNumCheck ^= serial_out[i];
}
if (serNumCheck != serial_out[i])
{
status = ERROR;
}
}
return status;
}
uint8_t mfrc522_auth(uint8_t authMode, uint8_t BlockAddr, uint8_t *Sectorkey, uint8_t *serNum)
{
uint8_t status;
uint32_t recvBits;
uint8_t i;
uint8_t buff[12];
// Validate instruction block address + sector + password + card serial number
buff[0] = authMode;
buff[1] = BlockAddr;
for (i=0; i<6; i++)
{
buff[i+2] = 0xFF /**(Sectorkey+i)*/;
}
for (i=0; i<4; i++)
{
buff[i+8] = *(serNum+i);
}
status = mfrc522_to_card(MFAuthent_CMD, buff, 12, buff, &recvBits);
return status;
}
uint8_t MFRC522_Read1(uint8_t blockAddr, uint8_t *recvData)
{
uint8_t status = 0;
uint8_t unLen, efa;
recvData[0] = PICC_READ;
recvData[1] = blockAddr;
CalculateCRC(recvData, 2, &recvData);
status = mfrc522_to_card(Transceive_CMD, recvData, 4, recvData, &unLen);
if ((status != CARD_FOUND)|| (unLen != 0x90))
{
status = ERROR;
}
return status;
}
uint8_t CalculateCRC(uint8_t *pIndata, uint8_t len, uint8_t *pOutData)
{
uint8_t i, n;
uint8_t status = 0;
n = mfrc522_read(DivIrqReg);
mfrc522_write(DivIrqReg,n&(~0x04)); //CRCIrq = 0
n = mfrc522_read(FIFOLevelReg); //FIFO
mfrc522_write(FIFOLevelReg, n|0x80);
//Write_MFRC522(CommandReg, PCD_IDLE);
// Write data to the FIFO
for (i=0; i<len; i++)
{
mfrc522_write(FIFODataReg, *(pIndata+i));
}
mfrc522_write(CommandReg, CalcCRC_CMD);
// Read the CRC calculation result
i = 0xFF;
while(1){
n = mfrc522_read(DivIrqReg);
if (n & 0x04) {
break;
}
if (--i != 0) {
return 7;
}
}
// Read the CRC calculation result
pOutData[3] = mfrc522_read(CRCResultReg_2);
pOutData[4] = mfrc522_read(CRCResultReg_1);
return status = 0;
}

Slow transfer speed on remote computer

Hey there StackOverflow people!
I'm making an IOCP server and I have ironed out most issues so far but one still remain and I do not know where to start looking at. When I run the client/server on my machine everything is fine and dandy. It matches the speed of the Windows SDK Sample maybe a little bit faster and definitely uses less CPU cycle. However when I run the client from a separate computer, transfer speed caps at 37 KB/s and has a roundtrip latency of 200ms (as opposed to 0). Now if I connect the client to the SDK Sample server, I don't have that problem so there is something wrong with my code. As far as I know, the sockets are initialized the exact same way with the same options. I have also ran my server in a profiler to check for bottleneck but I couldn't find any. Also, the computers I have tried it on were connected to the same gigabit switch (with gigabit adapter). I know this is kind of vague but that's because I couldn't pinpoint the problem so far and I would be eternally grateful if any of you guys could point me in the right direction.
Cheers,
-Roxy
EDIT2:
After following Mike's advise, I did some research on the code and found out that when a remote client connects to the server most of the time the code is waiting on GetQueuedCompletionStatus. This suggest that IO request are simply taking a long time to complete but I still don't understand why. This only occurs only when the client is on a remote computer. I'm thinking this has something to do with how a setup the sockets or how I'm posting the request but I don't see any difference with the sample code.
Any ideas?
EDIT (Added sample code):
Alright, here it is! It ain't pretty though!
If you have the Windows SDK installed, you can connect to it using the iocpclient sample (Program Files\Microsoft SDKs\Windows\v7.1\Samples\netds\winsock\iocp\client) and changing it's default port at line 73 to 5000.
Weird things I've just noticed when trying it myself is that it seems the sample iocpclient doesn't cause the same caps at 37KB/s issue... However it looks like the sample code has a limit set to around 800KB/s. I'll post a client if that can be of any help.
#pragma comment(lib, "Ws2_32.lib")
#include <WinSock2.h>
#include <stdio.h>
unsigned int connection = 0;
unsigned int upload = 0;
unsigned int download = 0;
#define IO_CONTEXT_COUNT 5
class NetClientHost
{
friend class gNetProtocolHost;
public:
enum Operation
{
kOperationUnknown,
kOperationRead,
kOperationWrite,
};
struct ClientData
{
SOCKET socket;
};
struct IOContext
{
WSAOVERLAPPED overlapped;
WSABUF wsaReceiveBuf;
WSABUF wsaSendBuf;
char *buf;
char *TESTbuf;
unsigned long bytesReceived;
unsigned long bytesSent;
unsigned long flags;
unsigned int bytesToSendTotal;
unsigned int remainingBytesToSend;
unsigned int chunk;
Operation operation;
};
NetClientHost()
{
memset((void *) &m_clientData, 0, sizeof(m_clientData));
}
NetClientHost::IOContext *NetClientHost::AcquireContext()
{
while (true)
{
for (int i = 0; i < IO_CONTEXT_COUNT; ++i)
{
if (!(m_ioContexts + i)->inUse)
{
InterlockedIncrement(&(m_ioContexts + i)->inUse);
//ResetEvent(*(m_hContextEvents + i));
if ((m_ioContexts + i)->ioContext.TESTbuf == 0)
Sleep(1);
return &(m_ioContexts + i)->ioContext;
}
}
//++g_blockOnPool;
//WaitForMultipleObjects(IO_CONTEXT_COUNT, m_hContextEvents, FALSE, INFINITE);
}
}
const ClientData *NetClientHost::GetClientData() const
{
return &m_clientData;
};
void NetClientHost::Init(unsigned int bufferSize)
{
_InitializeIOContexts(bufferSize ? bufferSize : 1024);
}
void NetClientHost::ReleaseContext(IOContext *ioContext)
{
int i = sizeof(_IOContextData), j = sizeof(IOContext);
_IOContextData *contextData = (_IOContextData *) (((char *) ioContext) - (i - j));
InterlockedDecrement(&contextData->inUse);
//SetEvent(*(m_hContextEvents + contextData->index));
}
struct _IOContextData
{
unsigned int index;
volatile long inUse;
IOContext ioContext;
};
ClientData m_clientData;
_IOContextData *m_ioContexts;
HANDLE *m_hContextEvents;
void _InitializeIOContexts(unsigned int bufferSize)
{
m_ioContexts = new _IOContextData[IO_CONTEXT_COUNT];
m_hContextEvents = new HANDLE[IO_CONTEXT_COUNT];
memset((void *) m_ioContexts, 0, sizeof(_IOContextData) * IO_CONTEXT_COUNT);
for (int i = 0; i < IO_CONTEXT_COUNT; ++i)
{
(m_ioContexts + i)->index = i;
(m_ioContexts + i)->ioContext.buf = new char[bufferSize];
(m_ioContexts + i)->ioContext.wsaReceiveBuf.len = bufferSize;
(m_ioContexts + i)->ioContext.wsaReceiveBuf.buf = (m_ioContexts + i)->ioContext.buf;
(m_ioContexts + i)->ioContext.TESTbuf = new char[10000];
(m_ioContexts + i)->ioContext.wsaSendBuf.buf = (m_ioContexts + i)->ioContext.TESTbuf;
*(m_hContextEvents + i) = CreateEvent(0, TRUE, FALSE, 0);
}
}
void _SetSocket(SOCKET socket)
{
m_clientData.socket = socket;
}
};
bool WriteChunk(const NetClientHost *clientHost, NetClientHost::IOContext *ioContext)
{
int status;
status = WSASend(clientHost->GetClientData()->socket, &ioContext->wsaSendBuf, 1, &ioContext->bytesSent, ioContext->flags, &ioContext->overlapped, 0);
if (status == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING)
{
// ...
return false;
}
return true;
}
bool Write(NetClientHost *clientHost, void *buffer, unsigned int size, unsigned int chunk)
{
//__ASSERT(m_clientHost);
//__ASSERT(m_clientHost->GetClientData()->remainingBytesToSend == 0);
NetClientHost::IOContext *ioContext = clientHost->AcquireContext();
if (!chunk)
chunk = size;
ioContext->wsaSendBuf.buf = ioContext->TESTbuf;
ioContext->operation = NetClientHost::kOperationWrite;
ioContext->flags = 0;
ioContext->wsaSendBuf.buf = new char[size];
memcpy((void *) ioContext->wsaSendBuf.buf, buffer, chunk);
ioContext->wsaSendBuf.len = chunk;
ioContext->chunk = chunk;
ioContext->bytesToSendTotal = size;
ioContext->remainingBytesToSend = size;
return WriteChunk(clientHost, ioContext);
}
void Read(NetClientHost *clientHost)
{
NetClientHost::IOContext *ioContext = clientHost->AcquireContext();
int status;
memset((void *) ioContext, 0, sizeof(NetClientHost::IOContext));
ioContext->buf = new char[1024];
ioContext->wsaReceiveBuf.len = 1024;
ioContext->wsaReceiveBuf.buf = ioContext->buf;
ioContext->flags = 0;
ioContext->operation = NetClientHost::kOperationRead;
status = WSARecv(clientHost->GetClientData()->socket, &ioContext->wsaReceiveBuf, 1, &ioContext->bytesReceived, &ioContext->flags, &ioContext->overlapped, 0);
int i = WSAGetLastError();
if (status == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING)
{
// ...
}
}
bool AddSocket(HANDLE hIOCP, SOCKET socket)
{
++connection;
int bufSize = 0;
LINGER lingerStruct;
lingerStruct.l_onoff = 1;
lingerStruct.l_linger = 0;
setsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *) &bufSize, sizeof(int));
setsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *) &bufSize, sizeof(int));
setsockopt(socket, SOL_SOCKET, SO_LINGER, (char *) &lingerStruct, sizeof(lingerStruct) );
NetClientHost *clientHost = new NetClientHost;
clientHost->_InitializeIOContexts(1024);
clientHost->Init(0);
clientHost->_SetSocket(socket);
// Add this socket to the IO Completion Port
CreateIoCompletionPort((HANDLE) socket, hIOCP, (DWORD_PTR) clientHost, 0);
Read(clientHost);
return true;
}
int read = 0, write = 0;
DWORD WINAPI WorkerThread(LPVOID param)
{
LPOVERLAPPED overlapped;
NetClientHost *clientHost;
HANDLE hIOCP = (HANDLE) param;
DWORD ioSize;
BOOL status;
while (true)
{
status = GetQueuedCompletionStatus(hIOCP, &ioSize, (PULONG_PTR) &clientHost, (LPOVERLAPPED *) &overlapped, INFINITE);
if (!(status || ioSize))
{
--connection;
//_CloseConnection(clientHost);
continue;
}
NetClientHost::IOContext *ioContext = (NetClientHost::IOContext *) overlapped;
switch (ioContext->operation)
{
case NetClientHost::kOperationRead:
download += ioSize;
Write(clientHost, ioContext->wsaReceiveBuf.buf, ioSize, 0);
write++;
clientHost->ReleaseContext(ioContext);
break;
case NetClientHost::kOperationWrite:
upload += ioSize;
if (ioContext->remainingBytesToSend)
{
ioContext->remainingBytesToSend -= ioSize;
ioContext->wsaSendBuf.len = ioContext->chunk <= ioContext->remainingBytesToSend ? ioContext->chunk : ioContext->remainingBytesToSend; // equivalent to min(clientData->chunk, clientData->remainingBytesToSend);
ioContext->wsaSendBuf.buf += ioContext->wsaSendBuf.len;
}
if (ioContext->remainingBytesToSend)
{
WriteChunk(clientHost, ioContext);
}
else
{
clientHost->ReleaseContext(ioContext);
Read(clientHost);
read++;
}
break;
}
}
return 0;
}
DWORD WINAPI ListenThread(LPVOID param)
{
SOCKET sdListen = (SOCKET) param;
HANDLE hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);
CreateThread(0, 0, WorkerThread, hIOCP, 0, 0);
CreateThread(0, 0, WorkerThread, hIOCP, 0, 0);
CreateThread(0, 0, WorkerThread, hIOCP, 0, 0);
CreateThread(0, 0, WorkerThread, hIOCP, 0, 0);
while (true)
{
SOCKET as = WSAAccept(sdListen, 0, 0, 0, 0);
if (as != INVALID_SOCKET)
AddSocket(hIOCP, as);
}
}
int main()
{
SOCKET sdListen;
SOCKADDR_IN si_addrlocal;
int nRet;
int nZero = 0;
LINGER lingerStruct;
WSADATA wsaData;
WSAStartup(0x202, &wsaData);
sdListen = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED);
si_addrlocal.sin_family = AF_INET;
si_addrlocal.sin_port = htons(5000);
si_addrlocal.sin_addr.s_addr = htonl(INADDR_ANY);
nRet = bind(sdListen, (struct sockaddr *)&si_addrlocal, sizeof(si_addrlocal));
nRet = listen(sdListen, 5);
nZero = 0;
nRet = setsockopt(sdListen, SOL_SOCKET, SO_SNDBUF, (char *) &nZero, sizeof(nZero));
nZero = 0;
nRet = setsockopt(sdListen, SOL_SOCKET, SO_RCVBUF, (char *)&nZero, sizeof(nZero));
lingerStruct.l_onoff = 1;
lingerStruct.l_linger = 0;
nRet = setsockopt(sdListen, SOL_SOCKET, SO_LINGER, (char *)&lingerStruct, sizeof(lingerStruct) );
CreateThread(0, 0, ListenThread, (LPVOID) sdListen, 0, 0);
HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
while (true)
{
COORD c = {0};
SetConsoleCursorPosition(console, c);
printf("Connections: %i \nUpload: %iKB/s \nDownload: %iKB/s ", connection, upload * 2 / 1024, download * 2 / 1024);
upload = 0;
download = 0;
Sleep(500);
}
return 0;
}
This kind of asynchronous system should be able to run at full datalink speed. Problems I've found wrong are such as:
timeout settings causing needless retransmissions
in the receiving process, received message A might trigger a database update, such that received message B has to wait, causing an unnecessary delay in the response to message B back to the sender, when the DB update could actually be done in idle time.
There's something called wireshark that can give you some visibility into the message traffic.
I used to do it the hard way, with time-stamped message logs.
BTW: I would first use this method on the individual processes, to clean out any bottlenecks, before doing the asynchronous analysis. If you haven't done this, you can bet they're in there.
Just any old profiler isn't reliable. There are good ones, including Zoom.

Resources