I'm creating (at the time, to learn how) two applications console: a server and a client.
The client can connect to the server. If the server is not available, the application terminates with error.
The server waits make a connection, on line socketServer->Accept(1);. When the client connects, the code continues.. The problem is that the "if" following (if (socketServer->IsConnected()) {) evaluates to false.
Full source
Client
#include <wx/wxprec.h>
#include <wx/cmdline.h>
#include <wx/socket.h>
#include <wx/app.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
static const wxCmdLineEntryDesc cmdLineDesc[] = {
{ wxCMD_LINE_SWITCH, "h", "help", "show this help message",
wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP },
{ wxCMD_LINE_OPTION, "ip", NULL, "set ip; the default values is 127.0.0.1", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
{ wxCMD_LINE_OPTION, "p", "port", "set port; the default values is 3000", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
{ wxCMD_LINE_NONE }
};
int main(int argc, char **argv) {
// Startup
wxApp::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE, "program");
wxInitializer initializer;
if (!initializer) {
fprintf(stderr, "Failed to initialize the wxWidgets library, aborting.\n");
return -1;
}
// Default variables
wxString ip = "127.0.0.1";
wxString port = "3000";
// Parse
wxCmdLineParser parser(cmdLineDesc, argc, argv);
switch (parser.Parse()) {
case -1:
return 0;
break;
case 0:
parser.Found("ip", &ip);
parser.Found("p", &port);
break;
default:
break;
}
// Socket
wxPrintf("Creating socket...\n");
wxSocketClient *socketClient = new wxSocketClient(wxSOCKET_NONE);
wxPrintf("Addressing...\n");
wxPrintf("Usando ip %s\n", ip);
wxIPV4address addr;
if (!addr.Hostname(ip)) {
wxPrintf("Could not set hostname !\n");
return 1;
}
wxPrintf("Usando porta %s\n", port);
if (!addr.Service(port)) {
wxPrintf("Could not set service !\n");
return 1;
}
wxPrintf("Trying to make connection...\n");
if (socketClient->Connect(addr, true)) {
wxPrintf("Success\n");
} else {
wxPrintf("Error!\n");
return 1;
}
// Tell the server which test we are running
wxPrintf("Sending...\n");
unsigned char c = 0xDE;
socketClient->Write(&c, 1);
// This test also is similar to the first one but it sends a
// large buffer so that wxSocket is actually forced to split
// it into pieces and take care of sending everything before
// returning.
socketClient->SetFlags(wxSOCKET_WAITALL);
// Note that len is in kbytes here!
const unsigned char len = 32;
wxCharBuffer buf1(len * 1024);
for (size_t i = 0; i < len * 1024; i++)
buf1.data()[i] = (char) (i % 256);
socketClient->Write(&len, 1);
socketClient->Write(buf1, len * 1024);
wxPrintf("End!\n");
while (1) {
}
return 0;
}
Server
#include <wx/wxprec.h>
#include <wx/cmdline.h>
#include <wx/socket.h>
#include <wx/app.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
static const wxCmdLineEntryDesc cmdLineDesc[] = {
{ wxCMD_LINE_SWITCH, "h", "help", "show this help message",
wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP},
{ wxCMD_LINE_SWITCH, "d", "dummy", "a dummy switch"},
// ... your other command line options here...
{ wxCMD_LINE_NONE}
};
int main(int argc, char **argv) {
// Startup
wxApp::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE, "program");
wxInitializer initializer;
if (!initializer) {
fprintf(stderr, "Failed to initialize the wxWidgets library, aborting.\n");
return -1;
}
// Creat socket
wxPrintf("Criando socket...\n");
wxSocketServer *socketServer;
wxIPV4address addr;
if (!addr.Hostname("127.0.0.1")) {
wxPrintf("Could not set hostname !\n");
return 1;
}
if (!addr.Service(3000)) {
wxPrintf("Could not set service !\n");
return 1;
}
socketServer = new wxSocketServer(addr);
if (!socketServer->IsOk()) {
wxPrintf("Could not listen at the specified port !\n");
return 1;
}
// Efetuar conexao
wxPrintf("Waiting for connection...\n");
socketServer->Accept(1);
if (socketServer->IsConnected()) {
wxPrintf("Success\n");
} else {
wxPrintf("Not connected\n");
}
while (1) {
}
return 0;
}
After hours studying and trying, I solved the problem.
wxPrintf("Waiting for connection...\n");
wxSocketBase socketTest;
socketServer->AcceptWith(socketTest, true);
if (socketTest.IsConnected()) {
wxPrintf("Success\n");
} else {
wxPrintf("Not connected\n");
}
In the manual is written a detail that had not understood:
Accepts an incoming connection request, and creates a new wxSocketBase
object which represents the server-side of the connection.
Related
Could you explain how to close DBus connection correctly/ Below is my variant:
int P_dbus_proto_init(DBusConnection **dbus_conn, const char *name, dbus_MessageHandler mh, int num_rules, const char **rules)
{
int rc = 0;
DBusError dbus_err;
dbus_error_init(&dbus_err);
*dbus_conn = dbus_bus_get(DBUS_BUS_SYSTEM, &dbus_err);
if (dbus_error_is_set(&dbus_err))
{
FILTER_LOG_ERROR("Connection Error (%s)\n", dbus_err.message);
dbus_error_free(&dbus_err);
return -1;
}
rc = dbus_bus_request_name(*dbus_conn, name, DBUS_NAME_FLAG_REPLACE_EXISTING, &dbus_err);
if (dbus_error_is_set(&dbus_err) || (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != rc))
{
FILTER_LOG_ERROR("Connection Error (%s)\n", dbus_err.message);
dbus_error_free(&dbus_err);
return -1;
}
dbus_connection_add_filter(*dbus_conn, mh, NULL, NULL);
if (dbus_error_is_set(&dbus_err))
{
FILTER_LOG_ERROR("Add Filter Error (%s)\n", dbus_err.message);
dbus_error_free(&dbus_err);
return -1;
}
for(int i = 0; i < num_rules; i++)
{
dbus_bus_add_match(*dbus_conn, rules[i], &dbus_err);
if (dbus_error_is_set(&dbus_err))
{
FILTER_LOG_ERROR("Match Error (%s)\n", dbus_err.message);
dbus_error_free(&dbus_err);
return -1;
}
}
return 0;
}
static const char* rules[] = {
"interface='acl_management.method'",
};
And how I use it:
DBusConnection *dbus_conn;
if (P_dbus_proto_init(&dbus_conn, "com.bla-bla-bla.acl", P_dbus_proto_job, 1, rules) == 0)
{
while (dbus_connection_read_write_dispatch(dbus_conn, 5000))
{
if(p_ctx->execute.n_nl_exit_app == 0) //My app can be terminated by n_nl_exit_app flag
{
break;
}
}
dbus_connection_close(dbus_conn);// Should I do it or not?
dbus_connection_unref(dbus_conn);// Should I do it or not?
}
From dbus.freedesktop.org docs I cannot understand how to do it correctly. I can terminate my app by turn on 'n_nl_exit_app' flag - should I call dbus_connection_closein this case?
From several days I searched for this problem:
I want to do a connected device (IoT) using Watson IoT Platform and ESP32 (or similar). This device have some relays on board.
On Watson dashboard I created the device type, the physical/logical interface, I connected the ESP with the platform.
I created a custom action on the dashboard that has a param to identify the relay that I want to switch (switch2) and also a simple custom action (switch) without param.
The problem is that if I generate the action without the param (switch) I see the callback print, if I generate the action with a param (switch2) nothing happens.
I tried also to use the built-in Watson action "firmware update/download", if I use firmware download (that want some params such as uri, version, etc.) nothing happens, if I use firmware update (that don't want params), I see the callback of subscription.
Here you can see the code arduino like for the ESP
// --------------- HEADERS -------------------
#include <Arduino_JSON.h>
#include <EEPROM.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#include <PubSubClient.h> //https://github.com/knolleary/pubsubclient/releases/tag/v2.3
WebServer server(80);
char wifi_ssid[100] = "xxxxxx";
char wifi_psw[200] = "xxxxxxx";
// ----- Watson IBM parameters
#define ORG "xxxx"
#define DEVICE_TYPE "Relay"
#define DEVICE_ID "xxxx"
#define TOKEN "xxxxxxxxxxxxxxxx"
char ibmServer[] = ORG ".messaging.internetofthings.ibmcloud.com";
char authMethod[] = "use-token-auth";
char token[] = TOKEN;
char clientId[] = "d:" ORG ":" DEVICE_TYPE ":" DEVICE_ID;
const char switchTopic[] = "iotdm-1/mgmt/custom/switch-actions-v1/switch2";
const char testTopic[] = "iotdm-1/mgmt/custom/switch-actions-v1/switch"; //"iot-2/cmd/+/fmt/+";
const char observeTopic[] = "iotdm-1/observe";
const char publishTopic[] = "iot-2/evt/status/fmt/json";
const char responseTopic[] = "iotdm-1/response";
const char deviceResponseTopic[] = "iotdevice-1/response";
const char manageTopic[] = "iotdevice-1/mgmt/manage";
const char updateTopic[] = "iotdm-1/mgmt/initiate/firmware/update";
void callback(char* topic, byte* payload, unsigned int payloadLength);
WiFiClient wifiClient;
PubSubClient client(ibmServer, 1883, callback, wifiClient);
bool outputEnable = false;
bool oldOutputEnable = false;
void setup() {
// put your setup code here, to run once:
//Init la porta seriale ed aspetta che si avii
Serial.begin(115200);
while(!Serial) {
delay(1);
}
setupWiFi();
}
void loop() {
// put your main code here, to run repeatedly:
if (!client.loop()) {
mqttConnect();
initManagedDevice();
}
delay(100);
}
// WiFi Settings
void setupWiFi() {
bool state = false;
Serial.println("---- Setup WiFi ----");
Serial.println(wifi_ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(wifi_ssid, wifi_psw);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
mqttConnect();
initManagedDevice();
publishStatus();
Serial.println("");
Serial.print("Connected to ");
Serial.println(wifi_ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
// IBM IoT
void mqttConnect() {
if (!!!client.connected()) {
Serial.print("Reconnecting MQTT client to "); Serial.println(ibmServer);
while (!!!client.connect(clientId, authMethod, token)) {
Serial.print(".");
delay(500);
}
Serial.println();
}
}
void initManagedDevice() {
if (client.subscribe("iotdm-1/response")) {
Serial.println("subscribe to responses OK");
} else {
Serial.println("subscribe to responses FAILED");
}
if (client.subscribe("iotdm-1/device/update")) {
Serial.println("subscribe to update OK");
} else {
Serial.println("subscribe to update FAILED");
}
if (client.subscribe(observeTopic)) {
Serial.println("subscribe to observe OK");
} else {
Serial.println("subscribe to observe FAILED");
}
if (client.subscribe(switchTopic)) {
Serial.println("subscribe to switch OK");
} else {
Serial.println("subscribe to switch FAILED");
}
if (client.subscribe(testTopic)) {
Serial.println("subscribe to Test OK");
} else {
Serial.println("subscribe to Test FAILED");
}
JSONVar root;
JSONVar d;
JSONVar supports;
supports["deviceActions"] = true;
supports["firmwareActions"] = true;
supports["switch-actions-v1"] = true;
d["supports"] = supports;
root["d"] = d;
char buff[300] = "";
JSON.stringify(root).toCharArray(buff, 300);
Serial.println("publishing device metadata:"); Serial.println(buff);
if (client.publish(manageTopic, buff)) {
Serial.println("device Publish ok");
} else {
Serial.print("device Publish failed:");
}
}
void callback(char* topic, byte* payload, unsigned int payloadLength) {
Serial.print("callback invoked for topic: "); Serial.println(topic);
if (strcmp (responseTopic, topic) == 0) {
return; // just print of response for now
}
if (strcmp (updateTopic, topic) == 0) {
handleUpdate(payload);
}
if (strcmp(switchTopic, topic) == 0) {
handleRemoteSwitch(payload);
}
if(strcmp(observeTopic, topic) == 0) {
handleObserve(payload);
}
}
void sendSuccessResponse(const char* reqId) {
JSONVar payload;
payload["rc"] = 200;
payload["reqId"] = reqId;
char buff[300] = "";
JSON.stringify(payload).toCharArray(buff, 300);
if (client.publish(deviceResponseTopic, buff)) {
Serial.println("Success sended");
} else {
Serial.print("Success failed:");
}
}
void publishStatus() {
String payload = "{\"relayStatus\":";
payload += outputEnable;
payload += "}";
Serial.print("Sending payload: "); Serial.println(payload);
if (client.publish(publishTopic, (char*) payload.c_str())) {
Serial.println("Publish OK");
} else {
Serial.println("Publish FAILED");
}
}
void handleUpdate(byte* payload) {
Serial.println("handle Update");
}
void handleObserve(byte* payload) {
JSONVar request = JSON.parse((char*)payload);
JSONVar d = request["d"];
JSONVar fields = d["fields"];
const char* field = fields[0]["field"];
if(strcmp(field, "mgmt.firmware") == 0) {
Serial.println("Upadete the firmware");
sendSuccessResponse(request["reqId"]);
} else {
Serial.println("Unmanaged observe");
Serial.println(request);
}
}
void handleRemoteSwitch(byte* payload) {
Serial.println("handle remote switching");
//invertedSwitch = !invertedSwitch;
outputEnable = !outputEnable;
JSONVar request = JSON.parse((char*)payload);
const char* id = request["reqId"];
sendSuccessResponse(id);
}
Thanks to everyone that wants to try to help me.
After several days I solved the issue, I post here de response for someone with the same problem:
The problem is the PubSubClient library, that accept only 128 bytes response message (including header). The Watson IBM produce longer response message than 128 bytes.
To change the buffer size for the response message, you need to modify the PubSubClient.h file at line
#define MQTT_MAX_PACKET_SIZE 128
And change the 128 byte with bigger number (eg. 1024).
I tried to write a small event-based application in C for serial port reading (sources below). My program is to use the WinApi functions. The comport.c has the functions written to handle COM-port (open, read, write), the utils.c has some helper functions.
My program produces always the following output:
COM1 is selected to be listened.
GetCommMask result: 0x00000029 (EV_RXCHAR: 0x0001, EV_CTS: 0x0008, EV_RLSD: 0x0020)
Press any key to proceed...
I/O is pending (WaitCommEvent)...
I/O is pending (WaitCommEvent)...
I/O is pending (WaitCommEvent)...
I/O is pending (WaitCommEvent)...
I/O is pending (WaitCommEvent)...
It seems, that the function WaitCommEvent fails, the GetLastError() gives back error 87 (I/O pending).
Please help me to find out what the problem is, which parameter is invalid? See below the code.
The main.c:
#include "stdafx.h"
#include "comport.h"
#include "utils.h"
#include <conio.h>
#define READ_BUFF_MAX_LENGTH 1024
int _tmain(int argc, _TCHAR* argv[])
{
DWORD dwEvtMask;
HANDLE hComPort;
OVERLAPPED oEventHandler;
int portNum;
DWORD readTotal;
BOOL bOverlappedPending = FALSE;
char readBuff[READ_BUFF_MAX_LENGTH];
if(2 > argc)
{
printf("Use the program: ZliFuerZlvbusInterface.exe XXX (where XXX is the number of com port), \r\ne.G. for COM1 -> ZliFuerZlvbusInterface.exe 1\r\n");
return 1;
}
else
{
portNum = atoi(argv[1]);
if(0 == IsValidComNumber(portNum))
{
printf("ERROR: COM port number %d is invalid (parsed from '%s').\r\n", portNum, argv[1]);
return 2;
}
else
{
printf("COM%d is selected to be listened.\r\n", portNum);
}
}
if(0 == CreateSerialConnection(&hComPort, &oEventHandler, portNum, 1200, 8, EVEN, STOP1))
{
return 3;
}
if(FALSE == GetCommMask(hComPort, &dwEvtMask))
{
printf("GetCommMask failed with error:\r\n");
PrintLastErrorText();
return 4;
}
else
{
printf("GetCommMask result: 0x%08X (EV_RXCHAR: 0x0001, EV_CTS: 0x0008, EV_RLSD: 0x0020)\r\n", dwEvtMask);
}
printf("Press any key to proceed...\r\n");
getch();
while(1)
{
if(0 != kbhit())
{
if(27 == getch()) // ESC pressed
{
printf("Key ESC pressed, exiting...\r\n");
break;
}
}
bOverlappedPending = FALSE;
readTotal = 0;
if(TRUE == WaitCommEvent(hComPort, &dwEvtMask, &oEventHandler))
{
if(dwEvtMask & EV_CTS) // Clear-to-send signal present
{
PrintCurrentDateTime();
printf("COM%d: Clear-to-send signal set\r\n", portNum);
}
if(dwEvtMask & EV_RLSD) // Data-carrier-detect signal present
{
PrintCurrentDateTime();
printf("COM%d: Data-carrier-detect signal set\r\n", portNum);
}
if(dwEvtMask & EV_RXCHAR) // Data received
{
ReadSerial(&hComPort, &oEventHandler, portNum, readBuff, READ_BUFF_MAX_LENGTH);
}
}
else
{
if(ERROR_IO_PENDING == GetLastError())
{
printf("I/O is pending (WaitCommEvent)...\r\n");
bOverlappedPending = TRUE;
}
else
{
printf("WaitCommEvent failed with error:\r\n");
PrintLastErrorText();
}
}
if(TRUE == bOverlappedPending)
{
if(FALSE == GetOverlappedResult(hComPort, &oEventHandler, &readTotal, TRUE))
{
printf("GetOverlappedResult failed with error:\r\n");
PrintLastErrorText();
}
}
}
CloseSerialConnection(&hComPort);
return 0;
}
The comport.c:
#include <stdio.h>
#include "comport.h"
#include "utils.h"
int IsValidComNumber(int com)
{
if ((com < 1) ||
(com > 256))
{
return 0;
}
return 1;
}
int IsValidBaud(int baud)
{
switch(baud)
{
case CBR_110:
case CBR_300:
case CBR_600:
case CBR_1200:
case CBR_2400:
case CBR_4800:
case CBR_9600:
case CBR_14400:
case CBR_19200:
case CBR_38400:
case CBR_56000:
case CBR_57600:
case CBR_115200:
case CBR_128000:
case CBR_256000:
{
return 1;
break;
}
default:
{
break;
}
}
return 0;
}
int IsValidBits(int bits)
{
if ((bits < 5) ||
(bits > 8))
{
return 0;
}
else
{
return 1;
}
}
int CreateSerialConnection(HANDLE* handle, OVERLAPPED* overlapped, int portNumber, int baud, int bits, enum ParType parity, enum StopType stopbits)
{
DCB dcb;
COMMTIMEOUTS timeouts;
TCHAR portVirtualFile[32];
// For serial port name this format must be used (as virtual file): "\\\\.\\COMx"
memset(portVirtualFile, 0, 32);
#ifdef _UNICODE
swprintf(portVirtualFile, 32, L"\\\\.\\COM%d", portNumber);
#else
sprintf_s(portVirtualFile, 32, "\\\\.\\COM%d", portNumber);
#endif
if(0 == IsValidBaud(baud))
{
printf("ERROR: Specified baud rate %d is invalid for serial connection to COM%d.\r\n", baud, portNumber);
return 0;
}
if(0 == IsValidBits(bits))
{
printf("ERROR: Specified number of data bits %d is invalid for serial connection to COM%d.\r\n", bits, portNumber);
return 0;
}
*handle = CreateFile(portVirtualFile, // Specify port device
GENERIC_READ | GENERIC_WRITE, // Specify mode that open device.
0, // the devide isn't shared.
NULL, // the object gets a default security.
OPEN_EXISTING, // Specify which action to take on file.
FILE_FLAG_OVERLAPPED, // Use overlapped I/O.
NULL); // default.
if(*handle == INVALID_HANDLE_VALUE)
{
printf("ERROR: Opening serial port COM%d failed\r\n", portNumber);
return 0;
}
if(FALSE == GetCommState(*handle, &dcb))
{
printf("ERROR: Getting current state of COM%d\r\n", portNumber);
PrintLastErrorText();
return 0;
}
memset(&dcb, 0, sizeof(dcb)); //zero initialize the structure
dcb.DCBlength = sizeof(dcb); //fill in length
dcb.BaudRate = baud; // baud rate
dcb.ByteSize = bits; // data size, xmit and rcv
dcb.Parity = parity; // parity bit
dcb.StopBits = stopbits; // stop bits
if(FALSE == SetCommState(*handle, &dcb))
{
printf("ERROR: Setting new state of COM%d failed.\r\n", portNumber);
PrintLastErrorText();
return 0;
}
if(FALSE == SetCommMask(*handle, EV_RXCHAR | EV_CTS | EV_RLSD))
{
printf("ERROR: Setting new COM MASK (events) for COM%d failed.\r\n", portNumber);
PrintLastErrorText();
return 0;
}
timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.ReadTotalTimeoutConstant = 0;
timeouts.WriteTotalTimeoutMultiplier = 0;
timeouts.WriteTotalTimeoutConstant = 0;
if(FALSE == SetCommTimeouts(*handle, &timeouts))
{
printf("ERROR: Setting timeout parameters for COM%d failed.\r\n", portNumber);
PrintLastErrorText();
return 0;
}
(*overlapped).hEvent = CreateEvent(
NULL, // default security attributes
TRUE, // manual-reset event
FALSE, // not signaled
NULL // no name
);
if(NULL == overlapped->hEvent)
{
printf("ERROR: CreateEvent for COM%d failed.\r\n", portNumber);
PrintLastErrorText();
return 0;
}
// Initialize the rest of the OVERLAPPED structure to zero.
overlapped->Internal = 0;
overlapped->InternalHigh = 0;
overlapped->Offset = 0;
overlapped->OffsetHigh = 0;
return 1;
}
int CloseSerialConnection(HANDLE* handle)
{
if(FALSE == CloseHandle(*handle))
{
printf("ERROR: Cannot close handle 0x8.8%X\r\n", *handle);
PrintLastErrorText();
return 0;
}
*handle = NULL;
return 1;
}
int ReadSerial(HANDLE* handle, LPOVERLAPPED ov, int num, char* buffer, int max_len)
{
DWORD readTotal = 0;
if(FALSE == ClearCommError(*handle, NULL, NULL))
{
printf("ClearCommError failed with error:\r\n");
PrintLastErrorText();
return 0;
}
else
{
memset(buffer, 0, max_len);
if(FALSE == ReadFile(*handle, buffer, max_len, &readTotal, ov))
{
printf("ERROR: Reading from port COM%d failed\r\n", num);
if(ERROR_IO_PENDING == GetLastError())
{
printf("I/O is pending (ReadFile)...\r\n");
if(FALSE == GetOverlappedResult(*handle, ov, &readTotal, TRUE))
{
printf("GetOverlappedResult failed with error:\r\n");
PrintLastErrorText();
return 0;
}
}
else
{
PrintLastErrorText();
return 0;
}
}
else
{
PrintCurrentDateTime();
printf("Received %d characters on port COM%d: ", readTotal, num);
PrintBufferContent(buffer, readTotal);
}
}
return 1;
}
The utils.c:
#include <Windows.h>
#include <stdio.h>
#include "utils.h"
void PrintLastErrorText(void)
{
DWORD retSize;
LPTSTR pTemp = NULL;
retSize = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY, NULL, GetLastError(), LANG_NEUTRAL, (LPTSTR)&pTemp, 0, NULL);
if ((retSize > 0) &&
(pTemp != NULL))
{
printf("Last error: %s (0x%08X)\r\n", pTemp, GetLastError());
LocalFree((HLOCAL)pTemp);
}
}
void PrintCurrentDateTime(void)
{
SYSTEMTIME systime;
GetLocalTime(&systime);
printf("%04d.%02d.%02d %02d:%02d:%02d:%03d ", systime.wYear, systime.wMonth, systime.wDay, systime.wHour, systime.wMinute, systime.wSecond, systime.wMilliseconds);
}
void PrintBufferContent(char* buff, int len)
{
int i;
for(i = 0; i<len; i++)
{
printf("%02X ", buff[i]);
}
}
You're using the same OVERLAPPED structure for WaitCommEvent and ReadFile. Try using separate/independent OVERLAPPED for each.
UPDATE: Ignore that previous answer.
If your call to WaitCommEvent returns ERROR_IO_PENDING, you're not waiting for it to complete. Rather than loop around and call WaitCommEvent again, you need to wait for the operation to complete (typically via GetOverlappedResult).
You cannot have multiple pending asynchronous requests share a single OVERLAPPED structure. By looping and calling WaitCommEvent again after ERROR_IO_PENDING, that's exactly what's happening.
I am starting a UDP Server and then accepting a DTLS connection to read incoming data. The code is working fine. But once I reuse the connection from the client by restarting the client socket Server is unable to read anything. Using Cyassl library for SSL instance creation.
In Client:
Socket Binding and DTLS initialisation is fine as it is re-using the DTLS context used earlier.
In Server:
Also the socket closing and starting everything is fine but still I am unable to receive in the accepted FD.
But if I put a sleep of exactly 5 seconds between closing and starting the UDP server everything is fine. But I don't want to use blocking I/O like the sleep.
Please do help.
Server:
Accepting data received in m_udp_fd:
if(FD_ISSET(m_udp_fd, &rfds))
{
if(m_accepted_flag==0)
{
udp_read_connect(m_udp_fd);
open_dtls_server();
if(m_ssl_accept(m_udp_fd)>0)
{
media_accepted_flag = 1;
}
}
else
{
// Read data
if(process_dtls_packet(m_udp_fd)<=0)
{
//Clear FD here
}
}
}
Place where the connection is broken depending whether TCP connection is broken or not.
This is getting hit perfectly:
if (FD_ISSET(m_fd, &rfds))
{
if(process_msg(m_fd)<=0)
{
closesocket(m_fd);
FD_CLR(m_fd,recv_fds);
if(recv_fdmax == m_fd)
{
recv_fdmax = max(x_fd,y_fd);
recv_fdmax = max(recv_fdmax,z_fd);
recv_fdmax = max(recv_fdmax,p_fd);
recv_fdmax = max(recv_fdmax,q_fd);
}
}
if(m_accepted_flag!=0)
{
m_accepted_flag = 0;
x_accepted_flag = 0;
//This sleep when kept works perfectly
Sleep(5000);
close_m_and_x_connection(&recv_fdmax,recv_fds,&m_udp_fd,&x_udp_fd);
}
}
UDP Read Connect Function:
int udp_read_connect(SOCKET sockfd)
{
struct sockaddr cliaddr;
char b[1500];
int n;
int len = sizeof(cliaddr);
n = (int)recvfrom(sockfd, (char*)b, sizeof(b), MSG_PEEK,
(struct sockaddr*)&cliaddr, &len);
if (n > 0)
{
if (connect(sockfd, (const struct sockaddr*)&cliaddr,sizeof(cliaddr)) != 0)
printf("udp connect failed");
}
else
printf("recvfrom failed");
return sockfd;
}
Open DTLS Server Method: Here dtls_ctx and dtls_meth are global variables.
int open_dtls_server()
{
int verify_flag = OFF;
int error;
if(dtls_ctx!= NULL)
return;
dtls_ctx = ssl_create_context(DTLS_V1, &dtls_meth);
dtls_meth = CyaDTLSv1_server_method();
if(dtls_meth==NULL)
{
return -1;
}
dtls_ctx = CyaSSL_CTX_new(dtls_meth);
if(NULL == dtls_ctx)
{
ERR_print_errors_fp(stderr);
return -1;
}
if((status = LoadSSLCertificate(dtls_ctx,sslInfo,&error,0)) == 1)
{
return 0;
}
else
return 1;
if(CyaSSL_CTX_use_PrivateKey_file(dtls_ctx, SSL_SERVER_RSA_KEY, SSL_FILETYPE_PEM) <= 0)
{
ERR_print_errors_fp(stderr);
return -1;
}
if(CyaSSL_CTX_check_private_key(dtls_ctx) != 1)
{
return -1;
}
if(verify_flag)
{
if(!CyaSSL_CTX_load_verify_locations(dtls_ctx, SSL_SERVER_RSA_CA_CERT, NULL))
{
ERR_print_errors_fp(stderr);
return -1;
}
CyaSSL_CTX_set_verify(dtls_ctx, SSL_VERIFY_PEER, NULL);
}
CyaSSL_CTX_set_options(dtls_ctx, SSL_OP_ALL);
return 1;
}
m_ssl_accept Function: ssl_m is also a global variable.
int m_ssl_accept(int confd)
{
int ret;
if(ssl_m==NULL)
{
ssl_m = CyaSSL_new(dtls_ctx);
if (ssl_m == NULL)
printf("SSL_new failed");
CyaSSL_set_fd(ssl_m, confd);
}
do
{
if((ret = CyaSSL_accept(ssl_m))!= 1)
{
printf("Handshake Error on M Channel %d with FD: [%d]\n",
return -1;
}
}while(ret != 1);
return 1;
}
I am sending single SSID and frequency to libnl for scanning, but i got multiple scan result along with my requested SSID and frequency,But i need single scan result (only for requested SSID), how to achieve this. Kindly help me , i am sending my code also.This code will run.
Compile: gcc -g -o scan scantesthandler.c -L /usr/lib/i386-linux-gnu/libnl.so -lnl
Run with debug log: NLCB=debug ./scan
#include<assert.h>
#include<errno.h>
#include<ifaddrs.h>
#include<netdb.h>
#include<stddef.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/socket.h>
#include <asm/types.h>
#include <linux/rtnetlink.h>
#include <netlink/netlink.h>
#include <netlink/msg.h>
#include <netlink/cache.h>
#include <netlink/socket.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/ctrl.h>
#include <stdlib.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/ctrl.h>
#include <netlink/route/link.h>
#include <linux/nl80211.h>
static int expectedId;
static int ifIndex;
struct wpa_scan_res
{
unsigned char bssid[6];
int freq;
};
static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
{
int *ret = arg;
*ret = err->error;
return NL_SKIP;
}
static int finish_handler(struct nl_msg *msg, void *arg)
{
int *ret = arg;
*ret = 0;
return NL_SKIP;
}
static int ack_handler(struct nl_msg *msg, void *arg)
{
int *err = arg;
*err = 0;
return NL_STOP;
}
static int bss_info_handler(struct nl_msg *msg, void *arg)
{
printf("\nFunction: %s, Line: %d\n",__FUNCTION__,__LINE__);
struct nlattr *tb[NL80211_ATTR_MAX + 1];
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
struct nlattr *bss[NL80211_BSS_MAX + 1];
static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
[NL80211_BSS_BSSID] = { .type = NLA_UNSPEC },
[NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
[NL80211_BSS_TSF] = { .type = NLA_U64 },
[NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 },
[NL80211_BSS_CAPABILITY] = { .type = NLA_U16 },
[NL80211_BSS_INFORMATION_ELEMENTS] = { .type = NLA_UNSPEC },
[NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 },
[NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 },
[NL80211_BSS_STATUS] = { .type = NLA_U32 },
[NL80211_BSS_SEEN_MS_AGO] = { .type = NLA_U32 },
[NL80211_BSS_BEACON_IES] = { .type = NLA_UNSPEC },
};
struct wpa_scan_res *r = NULL;
r = (struct wpa_scan_res*)malloc(sizeof(struct wpa_scan_res));
nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
genlmsg_attrlen(gnlh, 0), NULL);
if (!tb[NL80211_ATTR_BSS])
return NL_SKIP;
if (nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS],
bss_policy))
return NL_SKIP;
if (bss[NL80211_BSS_BSSID])
memcpy(r->bssid, nla_data(bss[NL80211_BSS_BSSID]),6);
if (bss[NL80211_BSS_FREQUENCY])
r->freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
printf("\nFrequency: %d ,BSSID: %2x:%2x:%2x:%2x:%2x:%2x",r->freq,r->bssid[0],r->bssid[1],r->bssid[2],r->bssid[3],r->bssid[4],r->bssid[5]);
return NL_SKIP;
}
static struct nl_msg* nl80211_scan_common(uint8_t cmd, int expectedId)
{
const char* ssid = "amitssid";
int ret;
struct nl_msg *msg;
int err;
size_t i;
int flags = 0,ifIndex;
msg = nlmsg_alloc();
if (!msg)
return NULL;
// setup the message
if(NULL==genlmsg_put(msg, 0, 0, expectedId, 0, flags, cmd, 0))
{
printf("\nError return genlMsg_put\n");
}
else
{
printf("\nSuccess genlMsg_put\n");
}
ifIndex = if_nametoindex("wlan1");
if(nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifIndex) < 0)
{
goto fail;
}
struct nl_msg *ssids = nlmsg_alloc();
if(nla_put(ssids, 1,strlen(ssid) ,ssid) <0)
{
nlmsg_free(ssids);
goto fail;
}
err = nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS,ssids);
nlmsg_free(ssids);
if (err < 0)
goto fail;
struct nl_msg *freqs = nlmsg_alloc();
if( nla_put_u32(freqs,1 ,2437) < 0) //amitssid
{
printf("\nnla_put_fail\n");
goto fail;
}
else
{
printf("\nnla_put_u32 pass\n");
}
//add message attributes
if(nla_put_nested(msg, NL80211_FREQUENCY_ATTR_FREQ,freqs) < 0)
{
printf("\nnla_put_nested failing:\n");
}
else
{
printf("\nnla_put_nested pass\n");
}
nlmsg_free(freqs);
if (err < 0)
goto fail;
return msg;
nla_put_failure:
printf("\nnla_put_failure\n");
nlmsg_free(msg);
return NULL;
fail:
nlmsg_free(msg);
return NULL;
}
int main(int argc, char** argv)
{
struct nl_msg *msg= NULL;
int ret = -1;
struct nl_cb *cb = NULL;
int err = -ENOMEM;
int returnvalue,getret;
int ifIndex, callbackret=-1;
struct nl_sock* sk = (void*)nl_handle_alloc();
if(sk == NULL)
{
printf("\nmemory error\n");
return;
}
cb = nl_cb_alloc(NL_CB_CUSTOM);
if(cb == NULL)
{
printf("\nfailed to allocate netlink callback\n");
}
enum nl80211_commands cmd;
if(genl_connect((void*)sk))
{
printf("\nConnected failed\n");
return;
}
//find the nl80211 driverID
expectedId = genl_ctrl_resolve((void*)sk, "nl80211");
if(expectedId < 0)
{
printf("\nnegative error code returned\n");
return;
}
else
{
printf("\ngenl_ctrl_resolve returned:%d\n",expectedId);
}
msg = nl80211_scan_common(NL80211_CMD_TRIGGER_SCAN, expectedId);
if (!msg)
{
printf("\nmsgbal:\n");
return -1;
}
err = nl_send_auto_complete((void*)sk, msg);
if (err < 0)
goto out;
else
{
printf("\nSent successfully\n");
}
err = 1;
nl_cb_err(cb,NL_CB_CUSTOM,error_handler,&err);
nl_cb_set(cb,NL_CB_FINISH,NL_CB_CUSTOM,finish_handler,&err);
nl_cb_set(cb,NL_CB_ACK,NL_CB_CUSTOM,ack_handler,&err);
callbackret = nl_cb_set(cb,NL_CB_VALID,NL_CB_CUSTOM,bss_info_handler,&err);
if(callbackret < 0)
{
printf("\n*************CallbackRet failed:***************** %d\n",callbackret);
}
else
{
printf("\n*************CallbackRet pass:***************** %d\n",callbackret);
}
returnvalue=nl_recvmsgs((void*)sk,cb);
printf("\n returnval:%d\n",returnvalue);
nlmsg_free(msg);
msg = NULL;
msg = nlmsg_alloc();
if (!msg)
return -1;
if(NULL==genlmsg_put(msg, 0, 0, expectedId, 0, NLM_F_DUMP, NL80211_CMD_GET_SCAN, 0))
{
printf("\nError return genlMsg_put\n");
}
else
{
printf("\nSuccess genlMsg_put\n");
}
ifIndex = if_nametoindex("wlan1");
printf("\nGet Scaninterface returned :%d\n",ifIndex);
nla_put_u32(msg,NL80211_ATTR_IFINDEX,ifIndex);
err = nl_send_auto_complete((void*)sk,msg);
if(err < 0) goto out;
err = 1;
getret= nl_recvmsgs((void*)sk,cb);
printf("\nGt Scan resultreturn:%d\n",getret);
out:
nlmsg_free(msg);
return err;
nla_put_failure:
printf("\nnla_put_failure\n");
nlmsg_free(msg);
return err;
}
You can just copy and paste this code on your system and run it.
As far as I know (and have seen) the scan command and result is dependent upon the vendor's device driver. One thing for certain there is no option to scan for a specific ssid; instead what you can do is to get all the scan result and loop through to check whether the ssid is in the list or not (wpa_supplicant uses this mechanism to match network configuration with scan result).
Now for the frequency, it should be possible to scan only a certain channel if the device driver has that functionality. But generally scan command scans all channel and returns the SSID (think your network-manager; it shows all the available SSID found for a scan command. which is essentially posted by device driver via cfg80211).