I managed to get the wpa_supplicant C API to work. But it behaves completly different each time I restart my Program.
The Connection succeeds every time. But then the troubles begin:
Sometimes SCAN
replies an empty String but returns 0 (Ok).
In another run it replies "OK\n"
and returns 0. When I loop and wait for an return of 0 and a "OK\n"
-reply it runs forever with an empty reply and a 0 return.
In rare cases when SCAN
returns 0 and replies "OK\n"
I move on and wait for SCAN_RESULTS
to return 0. At this point it behaves completely random. Sometimes it replies the whole Scan-Results. Sometimes it replies nothing but return 0 and the Scan-results are in my Event-Pipeline.
Or like in most cases: It returns 0 but does nothing. No reply, no Events. Nothing.
For debugging I reduced my Code to this snippet and try to figure out whats wrong. Im done, tried everything and I am somewhat frustrated with the Documentation of the ctrl-interface which doesn't define any workflow or tips. Im sick of reverse engineering the wpa_cli.c to figure out their flow.
I have to attach that mostly the first PING works well. Every other PING results in empty Strings.
/* some includes */
wpa_ctrl* _wpac;
static void callback(char* rply, size_t rplylen){
std::cout << std::string(rply,rplylen) << std::endl;
}
bool ScanResults() {
if(_wpac)
{
char rply[4096]; //same as in wpa_cli.c
size_t rplylen;
int retval = wpa_ctrl_request(_wpac,"SCAN_RESULTS",12,rply,&rplylen,callback);
if(retval == 0) {
std::string rplystring = std::string(rply,rplylen);
std::string message = std::string("wpa_ctrl(SCAN_RESULTS) replied: '").append(rplystring).append("' (").append(std::to_string(retval)).append(")");
std::cout << message << std::cout;
std::cout << std::string("wpa_ctrl(SCAN_RESULTS): Available (").append(std::to_string(retval)).append(")") << std::endl;
return true;
}
else
std::cout << std::string("wpa_ctrl(SCAN_RESULTS): Unavailable (").append(std::to_string(retval)).append(")") << std::endl;
return false;
}
return false;
}
bool InitScan() {
if(_wpac)
{
char rply[4096]; //same as in wpa_cli.c
size_t rplylen;
int retval = wpa_ctrl_request(_wpac,"SCAN",4,rply,&rplylen,callback);
if(retval == 0) {
std::string rplystring = std::string(rply,rplylen);
std::string message = std::string("wpa_ctrl(SCAN) replied: '").append(rplystring).append("' (").append(std::to_string(retval)).append(")");
std::cout << message << std::endl;
if(rplystring == "OK\n") {
std::string message = std::string("wpa_ctrl(SCAN): Scan initiated (").append(std::to_string(retval)).append(")");
std::cout << message << std::endl;
return true;
}
}
std::string message = std::string("wpa_ctrl(SCAN) failed: (").append(std::to_string(retval)).append(")");
std::cout << message << std::endl;
}
return false;
}
int main(){
std::string connection_string = std::string("/var/run/wpa_supplicant/").append(_interface);
wpa_ctrl* _wpac = wpa_ctrl_open(connection_string.c_str());
if(!_wpac)
return 1;
/* Well Working Attach to as Eventlistener omitted */
while(!InitScan())
sleep(1);
while(!ScanResults())
sleep(1)
return 0;
}
Try doing something like this in the appropriate places in your code
char rply[4096];
size_t rplylen = sizeof(rply);
static char cmd[] = "SCAN"; //maybe a bit easier to deal with since you need a command length
int retval = wpa_ctrl_request(_wpac, cmd, sizeof(cmd)-1, rply, &rplylen, NULL);
NULL, because I suspect you really don't need a callback routine. But put one in if you want to.