Getting [e][wifigeneric.cpp:739] hostbyname(): dns failed when performing POST request - c++

I am getting started with electronics and microcontrollers programming.
I have made a simple circuit where I use DHT22 sensor to measure temperature and humidity. I have also made my own API in Node and Express (MongoDB as a database). It is very simple API, just two endpoints: one for getting. and one for posting data. I ma able to create succesfull requests using Postman (and with the browser).
Just to be clear, I want to send temperature and humidity to my API, and then do some work with this data on Vue website (I think that this is not relevant at all, but again, just to be clear what I am trying to achieve).
Now I will say what I am using:
Windows 10 OS
NodeMCU ESP32 microcontroller
DHT22 sensor
HTTPClient library (I think this one is causing a problem)
PlatformIO with Arduino.h header file
Everything is ok, but when I try to send data to my database things fail. I am ALWAYS getting following error
[e][wifigeneric.cpp:739] hostbyname(): dns failed
I have tried to make the POST request using both http://localhost:3000/endpoint and http://127.0.0.1/endpoint (that part is really strange, why I am getting DNS error when using IP address without domain name?).
I have already looked up for the solution on the web. I have come across many similar questions on github, but any of them worked for me). Also, none of them were solving error caused by line 739.
Here I will leave my code. Is is simple and short, so I will post all of it. Please, do not blame me for my c++ skills, I am getting better :D
Thank you in advance, have a nice day or evening.
Kind regards, Bartek.
#include <Arduino.h>
#include <DHT.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <ArduinoJson.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#define DHTPIN 22
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
const char ssid[] = "MY_SSIID";
const char password[] = "MY_WIFI_PASSWORD";
const char apiAddress[] = "http://localhost:3000/reading";
unsigned long lastTime = 0;
unsigned long timerDelay = 60000;
struct sensorReading {
float temperature;
float humidity;
float heatIndex;
};
sensorReading readDataFromSensor();
void sendData(sensorReading * reading);
void setup() {
Serial.begin(9600);
dht.begin();
WiFi.begin(ssid, password);
WiFi.config(IPAddress(192, 168, 1, 223), IPAddress(192, 168, 1, 1), IPAddress(255, 255, 255, 0));
while(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print('.');
}
}
void loop() {
if (millis() > lastTime + timerDelay) {
sensorReading data;
sensorReading * p_data = NULL;
data = readDataFromSensor();
p_data = &data;
sendData(p_data);
}
}
sensorReading readDataFromSensor() {
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
float heatIndex = dht.computeHeatIndex(temperature, humidity, false);
if (isnan(temperature) || isnan(humidity)) {
return sensorReading {};
}
const sensorReading dataToReturn {temperature, humidity, heatIndex};
return dataToReturn;
}
void sendData(sensorReading * reading) {
using namespace std;
if(WiFi.status() == WL_CONNECTED) {
HTTPClient http;
http.begin(apiAddress, 3000);
http.addHeader("Content-Type", "application/json");
DynamicJsonDocument doc(1024);
doc["temperature"] = reading->temperature;
doc["humidity"] = reading->humidity;
doc["heatIndex"] = reading->heatIndex;
String dataToSend;
serializeJson(doc, dataToSend);
int responseCode = http.POST(dataToSend);
Serial.println(responseCode);
http.end();
} else {
Serial.print("Ups...");
}
lastTime = millis();
}

You're calling the begin() method on http with two arguments, which are meant to be a hostname and a port number (and optionally a URI/path). Instead of passing a hostname, you're passing a full URL, which the HTTP client is attempting to resolve as a hostname.
The single argument form of http.begin() does take a URL. The form you're calling does not.
You can confirm this by reading the source code, which allows for these declarations of the begin() method:
bool begin(WiFiClient &client, String url);
bool begin(WiFiClient &client, String host, uint16_t port, String uri = "/", bool https = false);
#ifdef HTTPCLIENT_1_1_COMPATIBLE
bool begin(String url);
bool begin(String url, const char* CAcert);
bool begin(String host, uint16_t port, String uri = "/");
bool begin(String host, uint16_t port, String uri, const char* CAcert);
bool begin(String host, uint16_t port, String uri, const char* CAcert, const char* cli_cert, const char* cli_key);
#endif
A big hint to this problem is that you repeated the port number in both the URL and the second argument to http.begin().
Instead your code should look like either:
http.begin(apiAddress);
or
const char apiName[] = "localhost";
const unsigned apiPort = 3000;
const char apiPath[] = "reading";
...
http.begin(apiName, apiPort, apiPath);
However - this also will not work because localhost and 127.0.0.1 mean "self" or "the same computer". You'll need to provide the real IP address of the server you're trying to reach; localhost and 127.0.0.1 only refer to it when you're running software on it.

Related

How to get multiple responses per second with Get Request using ESP32

I'm using an ESP32 controller to send Get requests to a page. I can get 1 response per second using the http protocol and one response every three seconds using HTTPS. I would like to get as many as 3 responses per second if possible. Is there a faster way to get these responses and is the problem with my ESP32, the code, or the server itself? I'm not sure if it helps but my ESP32 is sending the Get request to an ASP.NET application running on a Windows server through an Amazon Web Services EC2 instance. My API is simply returning true or false.
Here is the code running on the ESP32:
#include <Arduino.h>
#include <WiFi.h>
#include <WiFiMulti.h>
#include <HTTPClient.h>
#define USE_SERIAL Serial
WiFiMulti wifiMulti;
//Certificate when using HTTPS
/*
const char* ca = \
"-----BEGIN CERTIFICATE-----\n" \
"examplecertificate\n" \
"-----END CERTIFICATE-----\n" \
*/
void setup() {
USE_SERIAL.begin(115200);
for(uint8_t t = 4; t > 0; t--) {
USE_SERIAL.printf("[SETUP] WAIT %d...\n", t);
USE_SERIAL.flush();
delay(1000);
}
wifiMulti.addAP("ssid", "password");
}
void loop() {
// wait for WiFi connection
if((wifiMulti.run() == WL_CONNECTED)) {
HTTPClient http;
//USE_SERIAL.print("[HTTP] begin...\n");
//http.begin("https://example.com/webapi/controller/getstatus/0", ca); //Using HTTPS takes 3 seconds
http.begin("http://example.com/webapi/controller/getstatus/0"); //Using HTTP takes 1 second
//USE_SERIAL.print("[HTTP] GET...\n");
// start connection and send HTTP header
int httpCode = http.GET();
// httpCode will be negative on error
if(httpCode > 0) {
// file found at server
if(httpCode == HTTP_CODE_OK) {
String payload = http.getString();
USE_SERIAL.println(payload);
}
} else {
USE_SERIAL.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
}
http.end();
}
}

Serial communication between esp8266 and atmega328p

I have a web server running on the esp8266.
The code is here:
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266mDNS.h>
#include <ESP8266WebServer.h>
#include "index.h"
#include "login.h"
ESP8266WiFiMulti wifiMulti; // Create an instance of the ESP8266WiFiMulti class, called 'wifiMulti'
ESP8266WebServer server(80); // Create a webserver object that listens for HTTP request on port 80
void handleRoot(); // function prototypes for HTTP handlers
void handleLogin();
void handleNotFound();
void setup(void){
Serial.begin(115200); // Start the Serial communication to send messages to the computer
delay(100);
wifiMulti.addAP("DIGISOL", "edot2017"); // add Wi-Fi networks you want to connect to
Serial.println("Connecting ...");
while (wifiMulti.run() != WL_CONNECTED) { // Wait for the Wi-Fi to connect: scan for Wi-Fi networks, and connect to the strongest of the networks above
delay(250);
Serial.print('.');
}
Serial.println('\n');
Serial.print("Connected to ");
Serial.println(WiFi.SSID()); // Tell us what network we're connected to
Serial.print("IP address:\t");
Serial.println(WiFi.localIP()); // Send the IP address of the ESP8266 to the computer
server.on("/", HTTP_GET, handleRoot); // Call the 'handleRoot' function when a client requests URI "/"
server.on("/login", HTTP_POST, handleLogin); // Call the 'handleLogin' function when a POST request is made to URI "/login"
server.on("/back",HTTP_POST,handleRoot);
server.onNotFound(handleNotFound); // When a client requests an unknown URI (i.e. something other than "/"), call function "handleNotFound"
server.begin(); // Actually start the server
Serial.println("HTTP server started");
}
void loop(void){
server.handleClient(); // Listen for HTTP requests from clients
}
void handleRoot() { // When URI / is requested, send a web page
String indexPage = MAIN_page;
server.send(200, "text/html",indexPage);
}
void handleLogin() { // If a POST request is made to URI /login
String message = "";
if( ! server.hasArg("data") || server.arg("data") == NULL ){ // If the POST request doesn't have username and password data
server.send(400, "text/plain", "400: Invalid Request"); // The request is invalid, so send HTTP status 400
return;
}
else
{
message += server.arg("data"); //Get the name of the parameter
Serial.println(message);
String loginpage = LOGIN_PAGE;
server.send(200, "text/html",loginpage);
}
}
void handleNotFound(){
server.send(404, "text/plain", "404: Not found"); // Send HTTP status 404 (Not Found) when there's no handler for the URI in the request
}
Then I have a sketch to display a message on to the ledp10 display which is working fine.
ledp10 display message code:
#include <SPI.h>
#include <DMD2.h>
#include <fonts/SystemFont5x7.h>
#include <fonts/Arial14.h>
#include <fonts/Droid_Sans_24.h>
#include <fonts/Droid_Sans_16.h>
// Set Width to the number of displays wide you have
const int WIDTH = 1;
const int COUNTDOWN_FROM = 0;
int counter = COUNTDOWN_FROM;
// You can change to a smaller font (two lines) by commenting this line,
// and uncommenting the line after it:
const uint8_t *FONT = SystemFont5x7;
const uint8_t *FONT2 = SystemFont5x7;
const char *MESSAGE = "GOA";
SoftDMD dmd(WIDTH,1); // DMD controls the entire display
DMD_TextBox box(dmd, 0, 1);
DMD_TextBox box1(dmd,11,1); // "box" provides a text box to automatically write to/scroll the display
// the setup routine runs once when you press reset:
void setup() {
Serial.begin(9600);
dmd.setBrightness(255);
//dmd.selectFont(FONT);
dmd.begin();
}
// the loop routine runs over and over again forever:
void loop() {
dmd.selectFont(FONT);
box.print(counter);
dmd.selectFont(FONT2);
const char *next = MESSAGE;
while(*next) {
Serial.print(*next);
box1.print(*next);
delay(500);
next++;
}
box.println(F(""));
counter++;
if(counter == 60) {
dmd.clearScreen();
counter = 0;
}
}
Now I need to communicate between the esp8266 and atmega328p. I.e the message sent on the web page needs to be displayed on to the ledp10 display.
How should I do it?
Please help only in serial communication between esp8266 and atmega328p.
modify the lcd Atmega sketch to receive a text from Serial Monitor.
Then connect the esp8266 to Serial of Atmega and the Atmega sketch will receive the text you print to Serial in the esp sketch

Cannot find the correct MQTT broker server

This is my first post so tell me where I go wrong.
Here is my setup.
I have a sensor connected via SCL and STA to a ESP8266 developer kit.
My language is arduino. This works, I can get it to put out the temperature and humidity into the serial monitor. I also have a raspberry pi (3?) that currently works as a wifi router. I used hostapd to do this. I have also signed up for amazon AWS, and have AWSIoT connected with the pi, which i have mosquitto running as the broker. My goal is to be able to leave the pi and esp with sensor in a location, pi connected with ethernet, and have the temperature and humidity come to kibana browser and I be able to see the data.
Here is my problem. mosquitto works with the mosquitto_sub and mosquitto_pub client. However, my arduino code cannot connect. I suspected that this was a problem with the IP address, so I consulted the internet, and got many test sites, but none told me where to find the IP to put as the mqtt broker server. I have included my code, and I live in japan, so don`t be frightened by the time settings. As you can see, I have been trying many different things that maybe could work :/.
#include "SparkFun_Si7021_Breakout_Library.h"
#include <Wire.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <time.h>
#include <WiFiUdp.h>
float humidity = 0;
float tempf = 0;
const char* SSID = "ssid";
const char* PASSWORD = "password";
const int MQTTPORT = 1883;
I tried many different ips here, but none of them worked.
(Using the const char* format below)(The reason I exclude them is for security(right?))
//const char* MQTTSERVER = "mosquitto.service";
//const char* MQTTSERVER = "systemctl";
//const char* MQTTSERVER = "bridgeawsiot2";
const char* MQTTINITTOPIC = "/dev/init/msg/";
const char* MQTTSNTOPIC = "/ras-xdv2/Si7021";
const char* MQTTINITTOPICMSG = "{\"dev\"=\"Si7021\",\"msg\"=\"init\"}";
// APRIME
WiFiUDP ntpUDP;
const char* NTPSERVER = "ntp.nict.jp";
const int NTPTIMEOFFSET = 9 * 60 * 60;
WiFiClient espClient;
PubSubClient client(espClient);
//Create Instance of HTU21D or SI7021 temp and humidity sensor and MPL3115A2 barrometric sensor
Weather sensor;
//---------------------------------------------------------------
void setup_wifi() {
delay(10);
Serial.print("WiFi CONNECTION...");
Serial.println(SSID);
WiFi.begin(SSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED){
delay(500);
Serial.print("Waiting...");
}
randomSeed(micros());
Serial.println(" ");
Serial.println("WiFi connected");
Serial.println("ESP8266 ip:");
Serial.println(WiFi.localIP());
}
//---------------------------------------------------------------
void mqttConnect() {
// client.setServer(MQTTSERVER, MQTTPORT);
while (!client.connected()) {
Serial.print("MQTT communications need more time...");
String clientId = "ESP8266-";
clientId += String(random(0xffff));
delay(3000);
if (client.connect(clientId.c_str())) {
Serial.println("MQTT communications online!");
client.publish(MQTTINITTOPIC, MQTTINITTOPICMSG);
} else {
Serial.print("MQTT communications unavailible, rc=");
Serial.print(client.state());
delay(2000);
Serial.println("Attempting connection in t-2 Seconds...");
delay(2000);
}
}
}
//---------------------------------------------------------------
void setup()
{
Serial.begin(115200);
sensor.begin();
setup_wifi();
client.setServer(MQTTSERVER, MQTTPORT);
delay(5000);
/*if (!sensor.begin()) {
Serial.print("sensor ded :(");
while (1);
}*/
configTime( NTPTIMEOFFSET, 0, NTPSERVER );
}
//---------------------------------------------------------------
void loop()
{
time_t t = time(NULL);
struct tm *tm;
tm = localtime(&t);
char dt[25];
sprintf(dt, "%04d-%02d-%02dT%02d:%02d:%02d+09:00", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
Serial.printf(dt);
if(!client.connected()){
mqttConnect();
} else {
client.loop();
}
char pub_json[100];
//Get readings from all sensors
getWeather();
printInfo();
delay(10000);
char tempfbuf[4];
char humiditybuf[4];
sprintf(pub_json,"{\"Temperature\":%s,\"Humidity\": %s, \"#timestamp\": %s}]}",dtostrf(tempf, 4, 2, tempfbuf), dtostrf(humidity, 4, 2, humiditybuf), dt);
client.publish(MQTTSNTOPIC, pub_json);
Serial.println("TEMPERATURE BEING PUBLISHED...");
Serial.println(pub_json);
delay(60000 * 10);
}
//---------------------------------------------------------------
void getWeather()
{
// Measure Relative Humidity from the HTU21D or Si7021
humidity = sensor.getRH();
// Measure Temperature from the HTU21D or Si7021
tempf = sensor.getTemp();
// Temperature is measured every time RH is requested.
// It is faster, therefore, to read it from previous RH
// measurement with getTemp() instead with readTemp()
}
//---------------------------------------------------------------
void printInfo()
{
//This function prints the weather data out to the default Serial Port
Serial.print("Temp:");
Serial.print(tempf);
Serial.print("F, ");
Serial.print("Humidity:");
Serial.print(humidity);
Serial.println("%");
}
The mosquitto.conf file was nonexistant when I first downloaded mosquitto, so I created it and used this:
Please tell me if I posted sensitive information: I am new to this :)
c4message_size_limit 0
clientid bridgeawsiot2
persistence true
persistence_file mosquitto.db
persistence_location /var/mosquitto/
log_type all
connection_messages true
log_timestamp true
allow_anonymous true
password_file /etc/mosquitto/conf.d/users
allow_anonymous true
listener 9001 127.0.0.1
protocol websockets
connection_messages true
log_timestamp true
listener 1883
connection <awsiot>
address yl42kju76zjjodsbm6nfl4yycq.ap-northeast-1.es.amazonaws.com:8883
topic /esp8266/Si7021/slack out 1
cleansession true
notifications false
start_type automatic
bridge_cafile /etc/mosquitto/certs/root-CA.crt
bridge_certfile /etc/mosquitto/certs/RAS-XD.cert.pem
bridge_keyfile /etc/mosquitto/certs/RAS-XD.private.key
Maybe the problem is the websockets thing?
Any help is appreciated!
Literally any :)
I am doing some pretty good work with the esp8266 and mqtt using arduino IDE. I have mine logging on to my own mqtt broker I set up in a centos 7 box with encryption using x509 certs.
I use mosquitto-auth-plug to manage user access with a mysql database set up on the same machine
when you think about it the operating system is free, mosquitto broker is free, and mysql server is free.
the only expense to having your own setup is a fixed IP and fast enough connection. Which you could set up pretty cheap in a virtual machine on azure.
Anyhow when I first started a friend (the guy who sold me my first nodemcu .9 board). Hooked me up with this script and I have been able to get it all done using this as my example.
the part I liked was if you monitored your mqtt from a client like mqtt box or others. When the chip first starts it sends payload "Start" to topic "device_name/status". This way you can always tell when it's online.
I copied the notes he gave me they are located below.
good luck
/*
* Skeleton for ESPP based sensors.
* Supports:
* - OTA fw update via HTTP
* http://ipaddr/update
* - REST access
* http://ipaddr:8080/<id>
* - MQTT publish and subscribe
*/
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <ESP8266HTTPUpdateServer.h>
#include <aREST.h>
// Define device name
const char* device_name = "myHostName";
const char* ssid = "WiFiSSID";
const char* password = "wiFiPassword";
const char* mqtt_server = "mqtt_hostname.example.com";
char host[14];
int rest_test = 7467;
/* WiFi Client */
WiFiClient espClient;
/* MQTT Client */
PubSubClient client(espClient);
/* HTTP client, for remote updates */
ESP8266WebServer httpServer(80);
ESP8266HTTPUpdateServer httpUpdater;
/* Rest server */
aREST rest = aREST();
WiFiServer restServer(8080);
void setup() {
char topic[80];
Serial.begin(115200);
/* Start WiFi */
setup_wifi();
/* Setup MQTT client */
client.setServer(mqtt_server, 1883);
client.setCallback(mqtt_callback);
/* Start the HTTP update server */
MDNS.begin(host);
httpUpdater.setup(&httpServer);
httpServer.begin();
MDNS.addService("http", "tcp", 80);
/* Set REST variables */
rest.set_id("1");
rest.set_name(host);
rest.variable("test", &rest_test);
/*
rest.variable("temperature", &temp);
rest.variable("distance", &dist);
rest.variable("reset_count", &reset_count);
rest.set_id("1");
rest.set_name("esp8266");
*/
restServer.begin();
/* Connect to the MQTT broker */
reconnect();
client.subscribe("network/broadcast");
sprintf(topic, "network/%s", device_name);
client.subscribe(topic);
sprintf(topic, "%s/status", device_name);
client.publish(topic, "start");
Serial.print("Node ");
Serial.print(device_name);
Serial.println(" started.");
Serial.print("Hostname ");
Serial.println(host);
Serial.print("IP Address ");
Serial.println(WiFi.localIP());
}
void setup_wifi() {
uint8_t mac[6];
delay(10);
WiFi.begin(ssid, password);
WiFi.macAddress(mac);
sprintf(host, "esp-%02x%02x%02x", mac[3], mac[4], mac[5]);
WiFi.hostname(host);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
}
/* Handle incoming MQTT messages */
void mqtt_callback(char* topic, byte* payload, unsigned int length) {
char payloadStr[80];
if (length > 79) {
length = 79;
}
memcpy(payloadStr, payload, length);
payloadStr[length] = '\0';
if (strcmp(payloadStr, "discover") == 0) {
delay(random(10, 1000));
client.publish("network/presence", device_name);
}
if (strcmp(payloadStr, "refresh") == 0) {
/* Publish all sensor data */
}
}
/* Connect (or re-connect) to the MQTT broker */
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
// Attempt to connect
/* TODO: Create this based on the MAC address */
if (client.connect(host)) {
} else {
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void loop() {
WiFiClient restClient;
/* Check MQTT connection, reconnect if needed */
if (!client.connected()) {
reconnect();
}
/* Process MQTT tasks */
client.loop();
/* Process HTTP FW update requests */
httpServer.handleClient();
/* Process REST requests */
restClient = restServer.available();
if (restClient) {
while (!restClient.available()) {
delay(1);
}
rest.handle(restClient);
}
/* Insert normal sensor code here. */
/* Publish results with client.publish(topic, value); */
}
My code sets up it's own device name, subscribes to the MQTT topics "network/broadcast", "network/(device name)".
When it starts it sends "(device_name)/status" with a payload of "start".
When it gets a "network/broadcast" with a payload of "discover" it replies by publishing a "network/presence" and its name.
Basically, you sent MQTT events with client.publish(topic, payload).
You subscribe to events with client.subscribe(topic).
When an event is received that matches your subscription it will call mqtt_callback and give it the topic, the payload, and the length.
Hope that helps.

SFML, how to send SoundBuffer with a packet?

I am trying to create a voice chat using SFML.
Program records 1 second-long parts with a SoundbufferRecorder.
when I test the code below, console shows this:
Failed to load sound file from memory
void receiveData()
{
received_data = false;
unsigned short port;
if (serwer) port = s_port;
else port = k_port;
Packet p;
socket.receive(p, ip, port);
bufferfrommemory.loadFromMemory(p.getData(), p.getDataSize());
received_data= true;
}
void sendData()
{
unsigned short port;
if (serwer) port = k_port;
else port = s_port;
const sf::SoundBuffer& buffer = recorder.getBuffer();
const sf::Int16* samples = buffer.getSamples();
std::size_t count = buffer.getSampleCount();
Packet p;
p.append(samples, count);
socket.send(p, ip, port);
}
void playIt()
{
Sound g;
g.setBuffer(bufferfrommemory);
g.play();
}
Thanks in advance for any help.

WebRTC DTLS-SRTP OpenSSL Server Handshake Failure

Here is my procedure in OpenSSL Server Mode,
Initialization Part of SSL and BIO variables:
map<int, SSL> m_SSLMap;
map<int, BIO> m_BioWriteMap;
map<int, BIO> m_BioReadMap;
int InitializeServerNegotiationMode(int iFd)
{
SSL *pServSslFd;
BIO *pWb, *pRb;
pServSslFd = SSL_new(m_pCtx);
assert(pServSslFd);
if ( SSL_version(pServSslFd) == DTLS1_VERSION)
{
pWb = BIO_new(BIO_s_mem());
pRb = BIO_new(BIO_s_mem());
assert(pWb);
assert(pRb);
SSL_set_bio(pServSslFd, pRb, pWb);
SSL_set_accept_state(pServSslFd);
}
m_SSLMap[iFd] = *pServSslFd;
m_BioReadMap[iFd] = *pRb;
m_BioWriteMap[iFd] = *pWb;
return INITIALIZATION_SUCCESS;
}
Server Mode Negotiation Operations when DTLS data comes to the server:
int ServerModeDTLSNegotiation(int iChannel, const char *pBuff, const int iLen, int iFd)
{
SSL *pServSslFd;
BIO *pRbio;
BIO *pWbio;
pServSslFd = &m_SSLMap[iFd];
pRbio = &m_BioReadMap[iFd];
pWbio = &m_BioWriteMap[iFd];
char buff[4096];
memset(buff, 0, strlen(buff));
BIO_write(pRbio, pBuff, iLen);
if(!SSL_is_init_finished(pServSslFd))
{
int iRet = SSL_do_handshake(pServSslFd);
}
int iNewLen = BIO_read(pWbio, buff, 2048);
if(iNewLen>0)
{
char *pNewData = new char[iNewLen+1];
for(int i=0;i<iNewLen;i++)
pNewData[i] = buff[i];
m_pEventHandler->SendReply(iChannel, (unsigned char *)pNewData, iNewLen);
}
else
{
printf("[DTLS]:: HandShaking Response failed for this data,
return -1;
}
return NEGOTIATION_SUCCESS;
}
Here I am attaching Wireshark TCP-Dump for better monitoring about the issue.
https://www.dropbox.com/s/quidcs6gilnvt2o/WebRTC%20DTLS%20Handshake%20Failure.pcapng?dl=0
Now, I am confident about my initialization of SSL_CTX variable. Because, Sometimes Handshake successfully negotiate for every port. But sometimes Handshake fails for one or two port. I am working for 5 days to solve WebRTC DTLS Server Mode Negotiation for Google Chrome. But I haven't found the root cause for this problem.
The link for TCP-Dump is not working.
Anyway, it seems your solution should work.
As it's a server program, it's definitely multi threaded. But it's really dangerous to initialize SSL variables or to perform handshake procedure without locking. In that case so many things can happen if these two methods are processed by multiple thread.
My suggestion is to add locking mechanism for these methods.