Upstream vwifi v7.0 (Raizo62/vwifi @ 4a9842e)

Unmodified upstream source from https://github.com/Raizo62/vwifi
Commit: 4a9842e "CMakeLists.txt : VERSION = 7.0"

Simulator of WiFi (802.11) interfaces to communicate between
several Virtual Machines via mac80211_hwsim + TCP relay.

License: Apache-2.0
This commit is contained in:
Guy Resheff
2026-03-08 08:19:45 -07:00
commit 92df7a383a
75 changed files with 8628 additions and 0 deletions
+152
View File
@@ -0,0 +1,152 @@
/*
From : https://android.googlesource.com/device/generic/goldfish/+/refs/heads/master/wifi/mac80211_create_radios/main.cpp
Licence http://www.apache.org/licenses/LICENSE-2.0
*/
#include <memory>
#include <netlink/genl/ctrl.h>
#include <netlink/genl/genl.h>
#include <netlink/netlink.h>
#include <net/ethernet.h>
#include <climits>
#include <stdio.h>
#include <unistd.h> // getuid
#include "addinterfaces.h"
#include "config_hwsim.h"
const char* nlErrStr(const int e)
{
return (e < 0) ? nl_geterror(e) : "";
}
#define RETURN(R) return (R);
#define RETURN_ERROR(C, R) \
do { \
fprintf(stderr,"%s:%d '%s' failed\n", __func__, __LINE__, C); \
return (R); \
} while (false);
#define RETURN_NL_ERROR(C, NLR, R) \
do { \
fprintf(stderr,"%s:%d '%s' failed with '%s'\n", __func__, __LINE__, C, nlErrStr((NLR))); \
return (R); \
} while (false);
struct nl_sock_deleter
{
void operator()(struct nl_sock* x) const
{
nl_socket_free(x);
}
};
struct nl_msg_deleter
{
void operator()(struct nl_msg* x) const
{
nlmsg_free(x);
}
};
int ParseAddress(const char* str, TByte addr[ETH_ALEN])
{
return sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
&addr[0], &addr[1], &addr[2],&addr[3], &addr[4], &addr[5]);
}
std::unique_ptr<struct nl_msg, nl_msg_deleter> CreateNlMessage(
const int family,
const int cmd)
{
std::unique_ptr<struct nl_msg, nl_msg_deleter> msg(nlmsg_alloc());
if (!msg)
{
RETURN_ERROR("nlmsg_alloc", nullptr);
}
void* user = genlmsg_put(msg.get(), NL_AUTO_PORT, NL_AUTO_SEQ, family, 0,
NLM_F_REQUEST, cmd, VERSION_NR);
if (!user)
{
RETURN_ERROR("genlmsg_put", nullptr);
}
RETURN(msg);
}
std::unique_ptr<struct nl_msg, nl_msg_deleter>
BuildCreateRadioMessage(const int family, const TByte mac[ETH_ALEN])
{
std::unique_ptr<struct nl_msg, nl_msg_deleter> msg =
CreateNlMessage(family, HWSIM_CMD_NEW_RADIO);
if (!msg)
{
RETURN(nullptr);
}
int ret;
ret = nla_put(msg.get(), HWSIM_ATTR_PERM_ADDR, ETH_ALEN, mac);
if (ret)
{
RETURN_NL_ERROR("nla_put(HWSIM_ATTR_PERM_ADDR)", ret, nullptr);
}
ret = nla_put_flag(msg.get(), HWSIM_ATTR_SUPPORT_P2P_DEVICE);
if (ret)
{
RETURN_NL_ERROR("nla_put(HWSIM_ATTR_SUPPORT_P2P_DEVICE)", ret, nullptr);
}
RETURN(msg);
}
int CreateRadios(struct nl_sock* socket, const int netlinkFamily,
const int nRadios, TByte* mac)
{
for (int idx = 0; idx < nRadios; ++idx)
{
if( nRadios != 1 ) // if i set only 1 interface, the mac address is not modified : the user can choose all the mac address
mac[5] = idx;
std::unique_ptr<struct nl_msg, nl_msg_deleter> msg =
BuildCreateRadioMessage(netlinkFamily, mac);
if (msg)
{
int ret = nl_send_auto(socket, msg.get());
if (ret < 0)
{
RETURN_NL_ERROR("nl_send_auto", ret, 1);
}
}
else
{
RETURN(1);
}
}
RETURN(0);
}
int ManageRadios(const int nRadios, TByte* macPrefix)
{
std::unique_ptr<struct nl_sock, nl_sock_deleter> socket(nl_socket_alloc());
if (!socket)
{
RETURN_ERROR("nl_socket_alloc", 1);
}
int ret;
ret = genl_connect(socket.get());
if (ret)
{
RETURN_NL_ERROR("genl_connect", ret, 1);
}
const int netlinkFamily = genl_ctrl_resolve(socket.get(), KERNEL_HWSIM_FAMILY_NAME);
if (netlinkFamily < 0)
{
fprintf(stderr,"The kernel module 'mac80211_hwsim' is not loaded\n");
return 2;
//RETURN_NL_ERROR("genl_ctrl_resolve", ret, 1);
}
ret = CreateRadios(socket.get(), netlinkFamily, nRadios, macPrefix);
if (ret)
{
RETURN(ret);
}
RETURN(0);
}
+10
View File
@@ -0,0 +1,10 @@
#ifndef _ADDINTERFACE_H_
#define _ADDINTERFACE_H_
#include "types.h"
int ParseAddress(const char* str, TByte addr[ETH_ALEN]);
int ManageRadios(const int nRadios, TByte* macPrefix);
#endif
+80
View File
@@ -0,0 +1,80 @@
#include "ccoordinate.h"
#include <math.h> // sqrt
TScale Scale=1;
CCoordinate::CCoordinate(TValue x, TValue y, TValue z)
{
Set(x, y, z);
}
CCoordinate::CCoordinate()
{
X=0;
Y=0;
Z=0;
}
CCoordinate::CCoordinate(const CCoordinate& coo)
{
*this=coo;
}
void CCoordinate::SetX(TValue x)
{
X=x;
}
void CCoordinate::SetY(TValue y)
{
Y=y;
}
void CCoordinate::SetZ(TValue z)
{
Z=z;
}
void CCoordinate::Set(TValue x, TValue y)
{
SetX(x);
SetY(y);
}
void CCoordinate::Set(TValue x, TValue y, TValue z)
{
Set(x, y);
SetZ(z);
}
void CCoordinate::Set(CCoordinate coo)
{
Set(coo.X,coo.Y,coo.Z);
}
TDistance CCoordinate::DistanceWith(TValue x, TValue y, TValue z)
{
return Scale*sqrt( (X-x)*(X-x)+(Y-y)*(Y-y)+(Z-z)*(Z-z) );
}
TDistance CCoordinate::DistanceWith(CCoordinate coo)
{
return DistanceWith(coo.X, coo.Y, coo.Z);
}
void CCoordinate::Display(ostream& os) const
{
os << X << " " << Y << " " << Z;
}
ostream& operator<<(ostream& os, const CCoordinate& coo)
{
coo.Display(os) ;
return os;
}
CCoordinate& CCoordinate::operator=(const CCoordinate& coo)
{
Set(coo.X,coo.Y,coo.Z);
return *this;
}
+41
View File
@@ -0,0 +1,41 @@
#ifndef _CCOORDINATE_H_
#define _CCOORDINATE_H_
#include <iostream>
#include "types.h" // TValue, TDistance
using namespace std;
extern TScale Scale;
class CCoordinate
{
TValue X;
TValue Y;
TValue Z;
public :
CCoordinate();
CCoordinate(TValue x, TValue y, TValue z);
CCoordinate(const CCoordinate& coo);
void SetX(TValue x);
void SetY(TValue y);
void SetZ(TValue z);
void Set(TValue x, TValue y);
void Set(TValue x, TValue y, TValue z);
void Set(CCoordinate coo);
TDistance DistanceWith(TValue x, TValue y, TValue z);
TDistance DistanceWith(CCoordinate coo);
void Display(ostream& os) const;
friend ostream& operator<<(ostream& os, const CCoordinate& coo);
CCoordinate& operator=(const CCoordinate& coo);
};
#endif
+455
View File
@@ -0,0 +1,455 @@
#include <cstring> // strcpy
#include "cctrlserver.h"
#include "config.h" // MAX_SIZE_NAME
CCTRLServer::CCTRLServer(CWifiServer* wifiServerVTCP, CWifiServer* wifiServerITCP, CWifiServer* wifiServerSPY, CSelect* scheduler) : CSocketServer()
{
WifiServerVTCP=wifiServerVTCP;
WifiServerITCP=wifiServerITCP;
WifiServerSPY=wifiServerSPY;
Scheduler=scheduler;
}
CCTRLServer::~CCTRLServer()
{
// Close any open connections
CloseAllClient();
}
bool CCTRLServer::_Listen(TDescriptor& master, TPort port)
{
return CSocketServerFunctionITCP::_Listen(master, port);
}
TDescriptor CCTRLServer::_Accept(TDescriptor master, TCID& cid)
{
return CSocketServerFunctionITCP::_Accept(master, cid);
}
ssize_t CCTRLServer::Read(char* data, ssize_t sizeOfData)
{
return CSocket::Read(GetSocketClient(0),data, sizeOfData);
}
ssize_t CCTRLServer::Send(char* data, ssize_t sizeOfData)
{
return CSocket::Send(GetSocketClient(0),data, sizeOfData);
}
TOrder CCTRLServer::GetOrder()
{
TOrder order;
if( GetNumberClient() != 1 )
return TORDER_NO;
if( Read(reinterpret_cast<char*>(&order), sizeof(TOrder)) == SOCKET_ERROR )
return TORDER_NO;
return order;
}
bool CCTRLServer::SendCInfoWifi(CInfoWifi* infoWifi)
{
TCID cid=infoWifi->GetCid();
if( Send(reinterpret_cast<char*>(&cid),sizeof(cid)) == SOCKET_ERROR )
{
cerr<<"Error : SendCInfoWifi : cid : "<<infoWifi->GetCid()<<endl;
return false;
}
CCoordinate coo=(*infoWifi);
if( Send(reinterpret_cast<char*>(&coo),sizeof(coo)) == SOCKET_ERROR )
{
cerr<<"Error : SendCInfoWifi : CCoordinate : "<<infoWifi->GetCid()<<endl;
return false;
}
int sizeName=infoWifi->GetSizeName();
if( Send(reinterpret_cast<char*>(&sizeName),sizeof(sizeName)) == SOCKET_ERROR )
{
cerr<<"Error : SendCInfoWifi : size of name : "<<infoWifi->GetCid()<<endl;
return false;
}
if( sizeName > 0 )
{
char name[MAX_SIZE_NAME+1]; // +1 : \0
strcpy(name,(infoWifi->GetName()).c_str());
if( Send(name,sizeName+1) == SOCKET_ERROR ) // +1 : \0
{
cerr<<"Error : SendCInfoWifi : name : "<<infoWifi->GetCid()<<endl;
return false;
}
}
return true;
}
void CCTRLServer::SendList()
{
// because the same List is shared by WifiServerVTCP and WifiServerITCP
CInfoWifi* infoWifi;
// Spies :
TIndex number=WifiServerSPY->GetNumberClient();
if( Send(reinterpret_cast<char*>(&number), sizeof(number)) == SOCKET_ERROR )
return;
for(TIndex i=0; i<number;i++)
{
if( WifiServerSPY->IsEnable(i) )
{
infoWifi=WifiServerSPY->GetReferenceOnInfoWifiByIndex(i);
if( ! SendCInfoWifi(infoWifi) )
{
cerr<<"Error : SendList : Send : Spies : CInfoWifi : "<<*infoWifi<<endl;
return;
}
}
}
// Clients
number=WifiServerITCP->GetNumberClient();
if( Send(reinterpret_cast<char*>(&number), sizeof(number)) == SOCKET_ERROR )
return;
for(TIndex i=0; i<number;i++)
{
if( WifiServerITCP->IsEnable(i) )
{
infoWifi=WifiServerITCP->GetReferenceOnInfoWifiByIndex(i);
if( ! SendCInfoWifi(infoWifi) )
{
cerr<<"Error : SendList : Send : Clients : CInfoWifi : "<<*infoWifi<<endl;
return;
}
}
}
}
void CCTRLServer::ChangeCoordinate()
{
TCID cid;
if( Read(reinterpret_cast<char*>(&cid), sizeof(TCID)) == SOCKET_ERROR )
return;
CCoordinate coo;
if( Read(reinterpret_cast<char*>(&coo), sizeof(coo)) == SOCKET_ERROR )
return;
if( cid < TCID_GUEST_MIN )
return;
// because the same List is shared by WifiServerVTCP and WifiServerITCP
CInfoWifi* infoWifi;
infoWifi=WifiServerITCP->GetReferenceOnInfoWifiByCID(cid);
if( infoWifi != NULL )
{
infoWifi->Set(coo);
return;
}
infoWifi=WifiServerITCP->GetReferenceOnInfoWifiDeconnectedByCID(cid);
if( infoWifi != NULL )
{
infoWifi->Set(coo);
return;
}
CInfoWifi infoNewWifi(cid,coo);
WifiServerITCP->AddInfoWifiDeconnected(infoNewWifi);
}
void CCTRLServer::SetName()
{
TCID cid;
if( Read(reinterpret_cast<char*>(&cid), sizeof(TCID)) == SOCKET_ERROR )
return;
int sizeName;
char strName[MAX_SIZE_NAME+1]; // +1 : \0
if( Read(reinterpret_cast<char*>(&sizeName), sizeof(sizeName)) == SOCKET_ERROR )
return;
if( Read(reinterpret_cast<char*>(strName), sizeof(strName)) == SOCKET_ERROR )
return;
if( cid < TCID_GUEST_MIN )
return;
// because the same List is shared by WifiServerVTCP and WifiServerITCP
string name(strName);
CInfoWifi* infoWifi;
infoWifi=WifiServerITCP->GetReferenceOnInfoWifiByCID(cid);
if( infoWifi != NULL )
{
infoWifi->SetName(name);
return;
}
infoWifi=WifiServerITCP->GetReferenceOnInfoWifiDeconnectedByCID(cid);
if( infoWifi != NULL )
{
infoWifi->SetName(name);
return;
}
infoWifi=WifiServerSPY->GetReferenceOnInfoWifiByCID(cid);
if( infoWifi != NULL )
{
infoWifi->SetName(name);
return;
}
}
void CCTRLServer::ChangePacketLoss()
{
int value;
if( Read(reinterpret_cast<char*>(&value), sizeof(value)) == SOCKET_ERROR )
return;
if ( value )
{
#ifdef _DEBUG
cout<<"Packet loss : Enable"<<endl;
#endif
CanLostPackets=true;
}
else
{
#ifdef _DEBUG
cout<<"Packet loss : Disable"<<endl;
#endif
CanLostPackets=false;
}
}
void CCTRLServer::SendStatus()
{
if( Send(reinterpret_cast<char*>(&CanLostPackets),sizeof(CanLostPackets)) == SOCKET_ERROR )
{
cerr<<"Error : SendStatus : Send : PacketLoss"<<endl;
return;
}
if( Send(reinterpret_cast<char*>(&Scale),sizeof(Scale)) == SOCKET_ERROR )
{
cerr<<"Error : SendStatus : Send : Scale"<<endl;
return;
}
#ifdef ENABLE_VHOST
// VHOST
if( Send(reinterpret_cast<char*>(&WifiServerVTCP->Port),sizeof(WifiServerVTCP->Port)) == SOCKET_ERROR )
{
cerr<<"Error : SendStatus : Send : Port VHOST"<<endl;
return;
}
#endif
// INET
if( Send(reinterpret_cast<char*>(&WifiServerITCP->Port),sizeof(WifiServerITCP->Port)) == SOCKET_ERROR )
{
cerr<<"Error : SendStatus : Send : Port INET"<<endl;
return;
}
// SizeOfDisconnected
// be careful : the same List is shared by WifiServerVTCP and WifiServerITCP
if( Send(reinterpret_cast<char*>(&WifiServerITCP->MaxClientDeconnected),sizeof(WifiServerITCP->MaxClientDeconnected)) == SOCKET_ERROR )
{
cerr<<"Error : SendStatus : Send : Size MaxClientDeconnected"<<endl;
return;
}
// SPY
bool spyIsConnected=( WifiServerSPY->GetNumberClient() > 0 );
if( Send(reinterpret_cast<char*>(&spyIsConnected),sizeof(spyIsConnected)) == SOCKET_ERROR )
{
cerr<<"Error : SendStatus : Send : spyIsConnected"<<endl;
return;
}
}
void CCTRLServer::SendShow()
{
if( Send(reinterpret_cast<char*>(&CanLostPackets),sizeof(CanLostPackets)) == SOCKET_ERROR )
{
cerr<<"Error : SendShow : Send : PacketLoss"<<endl;
return;
}
if( Send(reinterpret_cast<char*>(&Scale),sizeof(Scale)) == SOCKET_ERROR )
{
cerr<<"Error : SendShow : Send : Scale"<<endl;
return;
}
bool spyIsConnected=( WifiServerSPY->GetNumberClient() > 0 );
if( Send(reinterpret_cast<char*>(&spyIsConnected),sizeof(spyIsConnected)) == SOCKET_ERROR )
{
cerr<<"Error : SendShow : Send : spyIsConnected"<<endl;
return;
}
}
void CCTRLServer::SendDistance()
{
TCID cid1, cid2;
if( Read(reinterpret_cast<char*>(&cid1), sizeof(TCID)) == SOCKET_ERROR )
return;
if( Read(reinterpret_cast<char*>(&cid2), sizeof(TCID)) == SOCKET_ERROR )
return;
int codeError;
// because the same List is shared by WifiServerVTCP and WifiServerITCP
CCoordinate* coo1;
coo1=WifiServerITCP->GetReferenceOnInfoWifiByCID(cid1);
if( coo1 == NULL )
{
coo1=WifiServerITCP->GetReferenceOnInfoWifiDeconnectedByCID(cid1);
if( coo1 == NULL )
{
codeError=-1;
if( Send(reinterpret_cast<char*>(&codeError),sizeof(codeError)) == SOCKET_ERROR )
cerr<<"Error : SendDistance : Send : unknown cid1"<<endl;
return ;
}
}
CCoordinate* coo2;
coo2=WifiServerITCP->GetReferenceOnInfoWifiByCID(cid2);
if( coo2 == NULL )
{
coo2=WifiServerITCP->GetReferenceOnInfoWifiDeconnectedByCID(cid2);
if( coo2 == NULL )
{
codeError=-2;
if( Send(reinterpret_cast<char*>(&codeError),sizeof(codeError)) == SOCKET_ERROR )
cerr<<"Error : SendDistance : Send : unknown cid2"<<endl;
return ;
}
}
codeError=0;
if( Send(reinterpret_cast<char*>(&codeError),sizeof(codeError)) == SOCKET_ERROR )
{
cerr<<"Error : SendDistance : Send : no error"<<endl;
return ;
}
TDistance distance=coo1->DistanceWith(*coo2);
if( Send(reinterpret_cast<char*>(&distance),sizeof(distance)) == SOCKET_ERROR )
{
cerr<<"Error : SendDistance : Send : distance"<<endl;
return;
}
}
void CCTRLServer::SetScale()
{
TScale new_scale;
if( Read(reinterpret_cast<char*>(&new_scale), sizeof(new_scale)) == SOCKET_ERROR )
return;
Scale=new_scale;
}
void CCTRLServer::CloseAllClient()
{
// because the same List is shared by WifiServerVTCP and WifiServerITCP
// Clients :
// be careful : In the Scheduler, i must delete only the nodes of WifiServer, not the node of the CTRLServer
for (TIndex i = 0; i < WifiServerITCP->GetNumberClient(); i++)
Scheduler->DelNode((*WifiServerITCP)[i]);
WifiServerITCP->CloseAllClient();
// Spies :
for (TIndex i = 0; i < WifiServerSPY->GetNumberClient(); i++)
Scheduler->DelNode((*WifiServerSPY)[i]);
WifiServerSPY->CloseAllClient();
}
void CCTRLServer::ReceiveOrder()
{
if ( Accept() == SOCKET_ERROR )
return;
TOrder order=GetOrder();
switch( order )
{
case TORDER_NO : break ;
case TORDER_LIST :
SendList();
break;
case TORDER_CHANGE_COORDINATE :
ChangeCoordinate();
break;
case TORDER_SETNAME :
SetName();
break;
case TORDER_PACKET_LOSS :
ChangePacketLoss();
break;
case TORDER_STATUS :
SendStatus();
break;
case TORDER_SHOW :
SendShow();
break;
case TORDER_DISTANCE_BETWEEN_CID :
SendDistance();
break;
case TORDER_SET_SCALE :
SetScale();
break;
case TORDER_CLOSE_ALL_CLIENT :
CloseAllClient();
break;
}
CloseClient(0);
}
+56
View File
@@ -0,0 +1,56 @@
#ifndef _CCTRLSERVER_H_
#define _CCTRLSERVER_H_
#include "cwifiserver.h" // CWifiServer CSocketServer
#include "csocketserverfunctionitcp.h" // CSocketServerFunctionITCP
#include "cselect.h" // CSelect
#include "types.h" // TOrder
class CCTRLServer : public CSocketServer, public CSocketServerFunctionITCP
{
CWifiServer* WifiServerVTCP;
CWifiServer* WifiServerITCP;
CWifiServer* WifiServerSPY;
CSelect* Scheduler;
bool _Listen(TDescriptor& master, TPort port) override;
TDescriptor _Accept(TDescriptor master, TCID& cid) override;
using CSocketServer::Read;
ssize_t Read(char* data, ssize_t sizeOfData);
using CSocketServer::Send;
ssize_t Send(char* data, ssize_t sizeOfData);
TOrder GetOrder();
bool SendCInfoWifi(CInfoWifi* infoWifi);
void SendList();
void ChangeCoordinate();
void SetName();
void ChangePacketLoss();
void SendStatus();
void SendShow();
void SendDistance();
void SetScale();
void CloseAllClient();
public :
CCTRLServer(CWifiServer* wifiServerVTCP, CWifiServer* wifiServerITCP, CWifiServer* wifiServerSPY, CSelect* scheduler);
virtual ~CCTRLServer();
void ReceiveOrder();
};
#endif
+62
View File
@@ -0,0 +1,62 @@
#include <iostream>
#include <string.h> // memcpy
#include "cdynbuffer.h"
const int DEFAULT_SIZE_BUFFER=1024;
CDynBuffer::CDynBuffer()
{
Buffer = nullptr;
Size=0;
Allocate(DEFAULT_SIZE_BUFFER,false);
}
CDynBuffer::~CDynBuffer()
{
if( Buffer != nullptr )
{
delete Buffer;
Buffer=nullptr;
Size=0;
}
}
void CDynBuffer::NeededSize(int size, bool keepValues)
{
if( size <= Size )
return;
Allocate(size,keepValues);
}
char* CDynBuffer::GetBuffer() const
{
return Buffer;
}
void CDynBuffer::Allocate(int size, bool keepValues)
{
if( ! keepValues )
{
if( Buffer != nullptr )
delete[] Buffer;
Buffer = new char [size];
}
else
{
char* newBuffer = new char [size];
if( Buffer != nullptr )
{
memcpy(newBuffer,Buffer,Size);
delete[] Buffer;
}
Buffer = newBuffer;
}
Size=size;
}
+25
View File
@@ -0,0 +1,25 @@
#ifndef _CDYNBUFFER_H_
#define _CDYNBUFFER_H_
class CDynBuffer
{
private :
char* Buffer;
int Size;
void Allocate(int size, bool keepValues);
public :
CDynBuffer();
~CDynBuffer();
void NeededSize(int size, bool keepValues);
char* GetBuffer() const;
};
#endif
+53
View File
@@ -0,0 +1,53 @@
#include <unistd.h> // close
#include <assert.h> // assert
#include "cinfosocket.h"
CInfoSocket::CInfoSocket()
{
SetDescriptor(-1);
DisableIt();
}
CInfoSocket::CInfoSocket(TDescriptor descriptor)
{
SetDescriptor(descriptor);
EnableIt();
}
void CInfoSocket::SetDescriptor(TDescriptor descriptor)
{
Descriptor=descriptor;
EnableIt();
}
TDescriptor CInfoSocket::GetDescriptor() const
{
return Descriptor;
}
void CInfoSocket::EnableIt()
{
assert( Descriptor >= 0 );
Enable=true;
}
void CInfoSocket::DisableIt()
{
Enable=false;
}
bool CInfoSocket::IsEnable()
{
return Enable;
}
void CInfoSocket::Close()
{
if( IsEnable() )
{
DisableIt();
close(Descriptor);
}
}
+35
View File
@@ -0,0 +1,35 @@
#ifndef _CINFOSOCKET_H_
#define _CINFOSOCKET_H_
#include <iostream> // ostream
#include "types.h" // TDescriptor
using namespace std;
class CInfoSocket
{
TDescriptor Descriptor;
bool Enable;
void EnableIt();
public :
CInfoSocket();
explicit CInfoSocket(TDescriptor descriptor);
void SetDescriptor(TDescriptor descriptor);
TDescriptor GetDescriptor() const;
void DisableIt();
bool IsEnable();
void Close();
};
#endif
+63
View File
@@ -0,0 +1,63 @@
#include <assert.h> // assert
#include "config.h" // MAX_SIZE_NAME
#include "cinfowifi.h"
CInfoWifi::CInfoWifi(): CCoordinate()
{
SetCid(0);
}
CInfoWifi::CInfoWifi(TCID cid, CCoordinate coo) : CCoordinate(coo)
{
SetCid(cid);
}
void CInfoWifi::SetCid(TCID cid)
{
// with the empty constructor : cid=0
assert( cid==0 || cid >=TCID_GUEST_MIN );
Cid=cid;
}
TCID CInfoWifi::GetCid() const
{
return Cid;
}
void CInfoWifi::SetName(string name)
{
if( name.size() > MAX_SIZE_NAME )
name.resize(MAX_SIZE_NAME);
Name=name;
}
string CInfoWifi::GetName() const
{
return Name;
}
int CInfoWifi::GetSizeName() const
{
return Name.size();
}
bool CInfoWifi::HasName() const
{
return ! Name.empty();
}
void CInfoWifi::Display(ostream& os) const
{
os << Cid << " ";
if( HasName() )
os << "("<<Name<<") ";
CCoordinate::Display(os);
}
ostream& operator<<(ostream& os, const CInfoWifi& infowifi)
{
infowifi.Display(os) ;
return os;
}
+39
View File
@@ -0,0 +1,39 @@
#ifndef _CINFOWIFI_H_
#define _CINFOWIFI_H_
#include <iostream> // ostream
#include <string>
#include "ccoordinate.h"
#include "types.h" // TCID
const TCID TCID_GUEST_MIN=3;
using namespace std;
class CInfoWifi : public CCoordinate
{
TCID Cid;
string Name;
public :
CInfoWifi();
CInfoWifi(TCID cid, CCoordinate coo);
void SetCid(TCID cid);
TCID GetCid() const;
void SetName(string name);
string GetName() const;
int GetSizeName() const;
bool HasName() const;
void Display(ostream& os) const;
friend ostream& operator<<(ostream& os, const CInfoWifi& infowifi);
};
#endif
+1095
View File
File diff suppressed because it is too large Load Diff
+275
View File
@@ -0,0 +1,275 @@
#ifndef _CKERNELWIFI_H_
#define _CKERNELWIFI_H_
#include <string>
#include <mutex>
#include "config_hwsim.h"
#include "cwirelessdevice.h"
#include "cwirelessdevicelist.h"
#include "cmonwirelessdevice.h"
#include "cselect.h"
#include <pthread.h>
#include "cthread.h"
#include <condition_variable>
#include "cdynbuffer.h"
namespace ckernelwifi{
class CallFromStaticFunc ;
}
class CKernelWifi : public intthread::AsyncTask {
protected :
pthread_t serverloop_id ;
CSelect Scheduler;
bool _connected_to_server { false };
std::mutex _mutex_connected_to_server ;
std::condition_variable _cond_connected_to_server ;
bool _being_initialized { false } ;
bool _being_started { false } ;
std::mutex _being_started_mutex ;
WirelessDeviceList _list_winterfaces ;
/** pointer for netlink socket */
struct nl_sock * _netlink_socket { nullptr };
/** pointer for netlink callback function */
struct nl_cb * _cb { nullptr };
/** For the family ID used by hwsim */
int m_family_id { 1 };
intthread::InterruptibleThread hwsimloop_task ;
intthread::InterruptibleThread serverloop_task ;
intthread::InterruptibleThread monitorloop_task ;
intthread::InterruptibleThread winterface_update_loop_task ;
intthread::InterruptibleThread connection_to_server_loop_task ;
bool _initialized { false } ;
std::mutex _mutex_initialized ;
MonitorWirelessDevice * monwireless = nullptr ;
int init();
int init_first();
void mac_address_to_string(char *address, struct ether_addr *mac);
public :
static ckernelwifi::CallFromStaticFunc * forward ;
/**
* \brief Default Constructor
*/
CKernelWifi();
/**
* \brief Default Destructor
*/
~CKernelWifi();
/**
* \brief start the all activity
*/
int start();
/**
* \brief stop the all activity
*/
int stop();
int process_messages(struct nl_msg *msg);
/**
* \brief free dynamicly allocated memory and socket descriptors
*/
void clean_all();
bool initialized();
void connected_to_server(bool v);
bool is_connected_to_server();
bool reconnect_to_server() ;
void manage_server_crash_loop() ;
void being_started(bool v);
bool is_being_started();
protected :
void cout_mac_address(struct ether_addr *src);
/**
* \brief Callback function to process messages received from kernel
* It processes the frames received from hwsim via netlink messages.
* These frames get sent via vsock to vwifi-server.
* \param msg - pointer to netlink message
* \param arg - pointer to additional args
* \return success or failure
*/
static int process_messages_cb(struct nl_msg *msg, void *arg);
/**
* \brief Send a register message to kernel via netlink
* This informs hwsim we wish to receive frames
* Taken from wmediumd
* \return void
*/
int send_register_msg();
/**
* \brief Initialize netlink communications
* Taken from wmediumd
* \return void
*/
int init_netlink();
int init_netlink_first();
/**
* \brief start receiving hwsim netlink frame from hwsim driver
*/
void recv_msg_from_hwsim_loop_start();
/**
* \brief Send a tx_info frame to the kernel space. This frame indicates
* that the frame was transmitted/acked successfully. The ack is sent back
* to the driver with HWSIM_ATTR_ADDR_TRANSMITTER unmodified.
* This is derived form wmediumd.
* TODO: modify if we create more accurate acking.
* \param src - mac address of transmitting radio
* \param flags - falgs
* \param signal - signal strength
* \param tx_attempts - number of transmit attempts
* \param cookie - unique identifier for frame
* \return success or failure
*/
int send_tx_info_frame_nl(struct ether_addr *src,
unsigned int flags, int signal,
struct hwsim_tx_rate *tx_attempts,
u64 cookie);
/**
* \brief start receiving hwsim frame from vwifi-server loop
*/
void recv_msg_from_server_loop_start();
static void recv_msg_from_server_signal_handle(int sig_num);
/**
* @brief this is meant to be a thread which detects removal of driver
* Used to suspend normal actions until driver is loaded
* @return void
*/
void monitor_hwsim_loop();
void winet_update_loop();
/**
* \brief Send a cloned frame to the kernel space driver.
* This will send a frame to the driver using netlink.
* It is received by hwsim with hwsim_cloned_frame_received_nl()
* This is taken from wmediumd and modified. It is called after the
* message has been received from wmasterd.
* \param dst - mac address of receving radio
* \param data - frame data
* \param data_len - length of frame
* \param rate_idx - number of attempts
* \param signal - signal strength
* \param freq - frequency
* \return success or failure
*/
int send_cloned_frame_msg(struct ether_addr *dst, char *data, int data_len,int rate_idx, int signal, uint32_t freq);
/**
* \brief handle messages received from server
*/
void recv_from_server();
/**
* \brief callback from cmonitorwirelessdevice that is called to
* handle addding wireless inet
*/
void handle_new_winet_notification(WirelessDevice);
/**
* \brief callback from cmonitorwirelessdevice that is called to
* handle deleting wireless inet
*/
void handle_del_winet_notification(const WirelessDevice&);
/**
* \brief callback from cmonitorwirelessdevice that is called to
* handle initial wireless inet
*/
void handle_init_winet_notification(WirelessDevice);
/**
* \brief get permanent mac address of ifname interface
*/
bool get_pmaddr(struct ether_addr &,const char *ifname);
/**
*\biref reconnecting to a server when detecting a socket disconnection
*/
void manage_server_crash();
// virtual :
virtual bool _Connect(int* id) = 0;
virtual ssize_t _SendSignal(TPower* power, const char* buffer, int sizeOfBuffer) = 0;
virtual ssize_t _RecvSignal(TPower* power, CDynBuffer* buffer) = 0;
virtual void _Close() = 0;
};
/**
* \namespace ckernelwifi
*
* A namespace is used here, since a class CallFromStaticFunc is defined in other files
*/
namespace ckernelwifi {
/**
* \class CallFromStaticFunc
* \brief this class is an artifact used to call a member function from static function
*/
class CallFromStaticFunc {
CKernelWifi * m_obj ;
public:
explicit CallFromStaticFunc(CKernelWifi * obj){
m_obj = obj ;
};
int process_messages(struct nl_msg *msg) {
// add exception to check null ptr
m_obj->process_messages(msg);
return 0 ;
};
};
}
#endif /* _CKERNELWIFI_H_ */
+11
View File
@@ -0,0 +1,11 @@
#ifndef _CLISTINFO_H_
#define _CLISTINFO_H_
#include <vector> // vector
template <typename TypeInfo>
class CListInfo : public std::vector<TypeInfo>
{
};
#endif
+672
View File
@@ -0,0 +1,672 @@
#include "cmonwirelessdevice.h"
#include "cwirelessdevice.h"
#include <asm/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <unistd.h>
#include <cstring>
#include <iostream>
#include <net/if_arp.h>
#include <stdexcept>
#include <thread>
#include <netlink/netlink.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/ctrl.h>
#include <netlink/genl/family.h>
#include <netlink/route/link.h>
#include <linux/nl80211.h>
#ifdef _DEBUG
#include <net/if.h> // IFF_UP
#endif
/* allow calling a non static function from static function */
monitorinet::CallFromStaticFunc * MonitorWirelessDevice::forward = nullptr ;
void MonitorWirelessDevice::setNewInetCallback(CallbackFunction cb){
_newinet_cb = cb ;
}
void MonitorWirelessDevice::setDelInetCallback(CallbackFunction cb){
_delinet_cb = cb ;
}
void MonitorWirelessDevice::setInitInetCallback(CallbackFunction cb){
_initinet_cb = cb ;
}
MonitorWirelessDevice::MonitorWirelessDevice(){
struct sockaddr_nl addr;
/* create a netlink route socket */
if(( _inetsock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0)
throw std::runtime_error("couldn't create a AF_NETLINK socket");
/* joins the multicast groups for link notifications */
std::memset(&addr, 0, sizeof addr);
addr.nl_family = AF_NETLINK;
addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;
if (bind(_inetsock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
throw std::runtime_error("couldn't bind to AF_NETLINK socket");
/* allows calls from static callback to non static member function */
forward = new monitorinet::CallFromStaticFunc(this);
/* init netlink 80211 */
if (nl80211_init() < 0)
throw std::runtime_error("Error initializing netlink 802.11");
}
MonitorWirelessDevice::~MonitorWirelessDevice(){
#ifdef _DEBUG
std::cout << __func__ << std::endl ;
#endif
if (started())
stop();
while(!outside_loop());
clean();
}
void MonitorWirelessDevice::clean(){
close(_inetsock);
nl_cb_put(wifi.cb);
nl_cb_put(wifi.cb1);
nl_close(wifi.nls);
nl_socket_free(wifi.nls);
}
int MonitorWirelessDevice::main_loop() {
fd_set rfds;
struct timeval tv;
_outsideloopmutex.lock() ;
_outsideloop = false ;
_outsideloopmutex.unlock();
while (started()) {
FD_ZERO(&rfds);
FD_CLR(_inetsock, &rfds);
FD_SET(_inetsock, &rfds);
tv.tv_sec = 1;
tv.tv_usec = 0;
int retval = select(FD_SETSIZE, &rfds, NULL, NULL, &tv);
if (retval == -1){
perror("select in MonitorWirelessDevice main_loop function");
stop();
}
else
if (retval){
#ifdef _DEBUG
std::cout << __func__ << "process event received from AF_NETLINK socket" << std::endl ;
#endif
recv_inet_event();
}
}
_outsideloopmutex.lock() ;
_outsideloop = true ;
_outsideloopmutex.unlock();
return 0;
}
bool MonitorWirelessDevice::outside_loop(){
bool outsideorno = false ;
_outsideloopmutex.lock();
if (_outsideloop) outsideorno = true ;
_outsideloopmutex.unlock();
return outsideorno ;
}
void MonitorWirelessDevice::start() {
if(started())
return ;
if (!outside_loop())
return ;
_startedmutex.lock() ;
_started = true ;
_startedmutex.unlock();
std::thread mainloop(&MonitorWirelessDevice::main_loop,this);
mainloop.detach();
}
void MonitorWirelessDevice::stop() {
_startedmutex.lock();
_started = false ;
_startedmutex.unlock();
}
bool MonitorWirelessDevice::started() {
bool startorno = false ;
_startedmutex.lock();
if (_started) startorno = true ;
_startedmutex.unlock();
return startorno ;
}
/***********************************************************************************************/
/***************** handle netlink net device events from kernel ******************************/
/**********************************************************************************************/
void MonitorWirelessDevice::recv_inet_event()
{
int len;
char buf[IFLIST_REPLY_BUFFER];
struct iovec iov = { buf, sizeof(buf) };
struct sockaddr_nl snl;
struct msghdr msg = { static_cast<void *>(&snl), sizeof(snl), &iov, 1, NULL, 0, 0 };
struct nlmsghdr *nlmsgheader;
/* read the waiting message */
len = recvmsg(_inetsock, &msg, 0);
if (len < 0)
perror("read_netlink");
for (nlmsgheader = reinterpret_cast<struct nlmsghdr *>(buf); NLMSG_OK(nlmsgheader, (unsigned int)len); nlmsgheader = NLMSG_NEXT(nlmsgheader, len)) {
switch (nlmsgheader->nlmsg_type) {
case NLMSG_DONE:
break;
case NLMSG_ERROR:
perror("read_netlink");
break;
// case RTM_SETLINK: /* we try to use it in order to detect chaging in wireless inet configuration, but it didn't work
//#ifdef _DEBUG
// std::cout << "Network interface configuration modified" << std::endl ;
//#endif
// break;
case RTM_NEWLINK:
#ifdef _DEBUG
std::cout << "Network interface added" << std::endl ;
#endif
new_net_interface(nlmsgheader);
break;
case RTM_DELLINK:
#ifdef _DEBUG
std::cout << "Network interface deleted" << std::endl ;
#endif
del_net_interface(nlmsgheader);
break;
default:
break;
}
}
}
void MonitorWirelessDevice::new_net_interface(struct nlmsghdr *h)
{
int len;
struct rtattr *tb[IFLA_MAX + 1];
char *name;
struct rtattr *rta;
struct ifinfomsg *ifi;
struct ether_addr macaddr ;
ifi = static_cast<struct ifinfomsg *>(NLMSG_DATA(h));
/*if (!(ifi->ifi_flags & IFLA_ADDRESS))
{
std::cout << "! IFLA_ADDRESS" << std::endl ;
return;
}*/
#ifdef _DEBUG
if (ifi->ifi_flags & IFF_UP) { // get UP flag of the network interface
std::cout << "interface UP" << std::endl;
} else {
std::cout << "Interface DOWN" << std::endl;
}
#endif
/* retrieve all attributes */
memset(tb, 0, sizeof(tb));
rta = IFLA_RTA(ifi);
len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifinfomsg));
while (RTA_OK(rta, len)) {
if (rta->rta_type <= IFLA_MAX)
tb[rta->rta_type] = rta;
rta = RTA_NEXT(rta, len);
}
/* require name field to be set */
if (tb[IFLA_IFNAME]) {
name = static_cast<char *>(RTA_DATA(tb[IFLA_IFNAME]));
} else {
std::cerr << "do not find interface name" << std::endl ;
return;
}
#ifdef _DEBUG
if (ifi->ifi_family == AF_UNSPEC)
std::cout << "family: AF_UNSPEC" << std::endl;
if (ifi->ifi_family == AF_INET6)
std::cout << "family: AF_INET6" << std::endl ;
#endif
/* require address field to be set */
if (tb[IFLA_ADDRESS]) {
std::memcpy(&macaddr, static_cast<void *>(RTA_DATA(tb[IFLA_ADDRESS])), ETH_ALEN);
}
std::string inet_name(name);
WirelessDevice inetdevice (inet_name,ifi->ifi_index,ifi->ifi_type,macaddr,0);
if(inetdevice.checkif_wireless_device()){
get_winterface_infos(ifi->ifi_index); // we can call a callback here, instead calling it in recv_winterface_infos, to reduce cpu
}
}
void MonitorWirelessDevice::del_net_interface(struct nlmsghdr *h)
{
int len;
struct rtattr *tb[IFLA_MAX + 1];
char *name;
struct rtattr *rta;
struct ifinfomsg *ifi;
struct ether_addr macaddr ;
ifi = static_cast<struct ifinfomsg *>(NLMSG_DATA(h));
/*if (!(ifi->ifi_flags & IFLA_ADDRESS))
{
std::cout << "! IFLA_ADDRESS" << std::endl ;
return;
}*/
/* retrieve all attributes */
memset(tb, 0, sizeof(tb));
rta = IFLA_RTA(ifi);
len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifinfomsg));
while (RTA_OK(rta, len)) {
if (rta->rta_type <= IFLA_MAX)
tb[rta->rta_type] = rta;
rta = RTA_NEXT(rta, len);
}
/* require name field to be set */
if (tb[IFLA_IFNAME]) {
name = static_cast<char *>(RTA_DATA(tb[IFLA_IFNAME]));
} else {
std::cerr << "do not find interface name" << std::endl ;
return;
}
#ifdef _DEBUG
if (ifi->ifi_family == AF_UNSPEC)
std::cout << "family: AF_UNSPEC" << std::endl;
if (ifi->ifi_family == AF_INET6)
std::cout << "family: AF_INET6" << std::endl ;
#endif
/* require address field to be set */
if (tb[IFLA_ADDRESS]) {
std::memcpy(&macaddr, static_cast<void *>(RTA_DATA(tb[IFLA_ADDRESS])), ETH_ALEN);
std::string inet_name(name);
WirelessDevice inetdevice (inet_name,ifi->ifi_index,ifi->ifi_type,macaddr,0);
if(inetdevice.checkif_wireless_device()){
_delinet_cb(inetdevice);
}
}
}
/***********************************************************************************************/
/***************** handle communication with nl80211 module ***********************************/
/**********************************************************************************************/
int MonitorWirelessDevice::nl80211_init(){
std::cout << __func__ << std::endl ;
/* init netlink socket with nl80211 module */
wifi.nls = nl_socket_alloc();
if (!wifi.nls) {
std::cerr << "Failed to allocate netlink socket." << std::endl ;
return -ENOMEM;
}
nl_socket_set_buffer_size(wifi.nls, 8192, 8192);
if (genl_connect(wifi.nls)) {
std::cerr << "Failed to connect to generic netlink" << std::endl ;
nl_close(wifi.nls);
nl_socket_free(wifi.nls);
return -ENOLINK;
}
wifi.nl80211_id = genl_ctrl_resolve(wifi.nls, "nl80211");
if (wifi.nl80211_id < 0) {
std::cerr << "nl80211 not found." << std::endl ;
nl_close(wifi.nls);
nl_socket_free(wifi.nls);
return -ENOENT;
}
/*set a callback that receive messages from a module */
wifi.cb = nl_cb_alloc(NL_CB_DEFAULT);
if (!wifi.cb) {
std::cerr << "Failed to allocate netlink callback." << std::endl ;
nl_close(wifi.nls);
nl_socket_free(wifi.nls);
return -ENOMEM;
}
/*set a callback that receive messages from a module */
wifi.cb1 = nl_cb_alloc(NL_CB_DEFAULT);
if (!wifi.cb1) {
std::cerr << "Failed to allocate netlink callback." << std::endl ;
nl_close(wifi.nls);
nl_socket_free(wifi.nls);
return -ENOMEM;
}
/* set callbacks */
nl_cb_set(wifi.cb1, NL_CB_VALID, NL_CB_CUSTOM,recv_winterface_extra_infos_cb, &(wifi.err1));
nl_cb_set(wifi.cb1, NL_CB_FINISH, NL_CB_CUSTOM, handle_iee80211_com_finish_cb, &(wifi.err1));
nl_cb_set(wifi.cb, NL_CB_VALID, NL_CB_CUSTOM,recv_winterface_infos_cb, &(wifi.err));
nl_cb_set(wifi.cb, NL_CB_FINISH, NL_CB_CUSTOM, handle_iee80211_com_finish_cb, &(wifi.err));
return wifi.nl80211_id ;
}
int MonitorWirelessDevice::get_winterface_infos(int ifindex)
{
wifi.err = 1 ;
int flags ;
/* for one interface or for all interface */
if (ifindex != 0)
flags = 0;
else
flags = NLM_F_DUMP;
/* allocate a msg to send to a module */
struct nl_msg *msg = nlmsg_alloc();
if (!msg) {
std::cerr << "Failed to allocate netlink message." << std::endl ;
return -ENOMEM;
}
/* send get inerface command to deriver */
genlmsg_put(msg, 0, 0, wifi.nl80211_id, 0, flags , NL80211_CMD_GET_INTERFACE, 0);
//genlmsg_put(msg,NL_AUTO_PORT,NL_AUTO_SEQ,wifi.nl80211_id,0,flags, NL80211_CMD_GET_INTERFACE, 0);
if (ifindex != 0)
nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifindex);
if (nl_send_auto(wifi.nls, msg) < 0)
{
nlmsg_free(msg);
return -1 ;
}
if (ifindex != 0)
nl_recvmsgs(wifi.nls, wifi.cb);
else
while(wifi.err > 0)
nl_recvmsgs(wifi.nls, wifi.cb);
nlmsg_free(msg);
return 0 ;
}
int MonitorWirelessDevice::recv_winterface_infos_cb(struct nl_msg *msg, [[maybe_unused]] void *arg){
forward->recv_winterface_infos(msg);
return 0 ;
}
int MonitorWirelessDevice::recv_winterface_infos(struct nl_msg *msg){
struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
struct genlmsghdr *gnlh = static_cast<struct genlmsghdr *>(nlmsg_data(nlmsg_hdr(msg)));
char *ifname;
int ifindex;
int iftype;
struct ether_addr macaddr ;
uint32_t txp = 0;
nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
if (tb_msg[NL80211_ATTR_IFNAME])
ifname = nla_get_string(tb_msg[NL80211_ATTR_IFNAME]) ;
else
return NL_SKIP;
if (tb_msg[NL80211_ATTR_IFINDEX])
ifindex = nla_get_u32(tb_msg[NL80211_ATTR_IFINDEX]);
else
return NL_SKIP;
if (tb_msg[NL80211_ATTR_MAC])
std::memcpy(&macaddr, static_cast<void *>(nla_data(tb_msg[NL80211_ATTR_MAC])), ETH_ALEN);
else
return NL_SKIP;
if (tb_msg[NL80211_ATTR_IFTYPE])
iftype = nla_get_u32(tb_msg[NL80211_ATTR_IFTYPE]);
else
return NL_SKIP;
if (tb_msg[NL80211_ATTR_WIPHY_TX_POWER_LEVEL]) {
txp = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_TX_POWER_LEVEL]);
}
std::string inet_name(ifname);
WirelessDevice inetdevice (inet_name,ifindex,iftype,macaddr,txp);
if(!init_interfaces){
_initinet_cb(inetdevice);
init_interfaces = true ;
}
else
_newinet_cb(inetdevice) ;
return NL_SKIP;
}
int MonitorWirelessDevice::recv_winterface_extra_infos_cb(struct nl_msg *msg, [[maybe_unused]] void *arg){
forward->recv_winterface_extra_infos(msg);
return 0 ;
}
int MonitorWirelessDevice::recv_winterface_extra_infos(struct nl_msg *msg){
struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
struct genlmsghdr *gnlh = static_cast<struct genlmsghdr *>(nlmsg_data(nlmsg_hdr(msg)));
struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
// struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
struct nla_policy stats[NL80211_STA_INFO_MAX + 1];
stats[NL80211_STA_INFO_INACTIVE_TIME].type = NLA_U32 ;
stats[NL80211_STA_INFO_RX_BYTES].type = NLA_U32 ;
stats[NL80211_STA_INFO_TX_BYTES].type = NLA_U32 ;
stats[NL80211_STA_INFO_RX_PACKETS].type = NLA_U32 ;
stats[NL80211_STA_INFO_TX_PACKETS].type = NLA_U32 ;
stats[NL80211_STA_INFO_SIGNAL].type = NLA_U8 ;
stats[NL80211_STA_INFO_TX_BITRATE].type = NLA_NESTED;
stats[NL80211_STA_INFO_LLID].type = NLA_U16 ;
stats[NL80211_STA_INFO_PLID].type = NLA_U16 ;
stats[NL80211_STA_INFO_PLINK_STATE].type = NLA_U8 ;
nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
/* get signal power-tx */
if (!tb_msg[NL80211_ATTR_STA_INFO]) {
std::cerr << __func__ << "sta stats missing!" << std::endl ;
return NL_SKIP;
}
if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb_msg[NL80211_ATTR_STA_INFO], stats))
{
std::cerr << "failed to parse nested attributes" << std::endl;
return NL_SKIP;
}
if (sinfo[NL80211_STA_INFO_SIGNAL]) {
int signal = 100+(int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
std::cout << __func__ << " Signal : " << signal << std::endl ;
}
return NL_SKIP;
}
int MonitorWirelessDevice::handle_iee80211_com_finish_cb( [[maybe_unused]] struct nl_msg *msg, void *arg){
forward->handle_iee80211_com_finish(arg);
return 0 ;
}
int MonitorWirelessDevice::handle_iee80211_com_finish(void *arg){
#ifdef _DEBUG
std::cout << __func__ << std::endl ;
#endif
int *ret = static_cast<int *>(arg);
*ret = 0;
return NL_SKIP;
}
+199
View File
@@ -0,0 +1,199 @@
#ifndef _CMONITORWIRELESSDEVICE_H_
#define _CMONITORWIRELESSDEVICE_H_
#include "cwirelessdevice.h"
#include <list>
#include <mutex>
#include <functional>
namespace monitorinet {
class CallFromStaticFunc;
}
/** Buffer size for netlink route interface list */
#define IFLIST_REPLY_BUFFER 4096
typedef std::function<void(WirelessDevice)> CallbackFunction ;
typedef struct {
struct nl_sock *nls;
int nl80211_id;
int err,err1 ;
struct nl_cb* cb;
struct nl_cb* cb1;
} WIFI;
class MonitorWirelessDevice {
/* set to true when wireless interfaces are initialised */
bool init_interfaces = false ;
/* for netlink communication with 80211 module */
WIFI wifi ;
bool _outsideloop { true } ;
bool _started { false } ;
int _inetsock ;
std::mutex _startedmutex ;
std::mutex _outsideloopmutex ;
int main_loop();
/**
* \brief processes netlink route events from the kernel
* Determines the event type for netlink route messages (del/new).
* \return void
*/
void recv_inet_event();
bool outside_loop();
void clean();
/**
* \brief processes RTM_NEWLINK messages
* Detects when interfaces are created and modified
* \param struct nlmsghdr * - netlink message header
* \return void
*/
void new_net_interface(struct nlmsghdr *) ;
void del_net_interface(struct nlmsghdr *h);
/**
* \brief callback to be set through setCallback function by another object
* this callback is called by new_net_interface function in order to send a created, deleted or changed wirelessdevice
*/
CallbackFunction _newinet_cb ;
/**
* \brief callback to be set through setCallback function by another object
* this callback is called by new_net_interface function in order to send a created, deleted or changed wirelessdevice
*/
CallbackFunction _delinet_cb ;
/**
* \brief callback to be set through setCallback function by another object
* this callback is called by recv_winterface_infos function in order to send infos of each existing wireless interface
*/
CallbackFunction _initinet_cb ;
static int recv_winterface_infos_cb(struct nl_msg *msg, void *arg);
static int recv_winterface_extra_infos_cb(struct nl_msg *msg, void *arg);
static int handle_iee80211_com_finish_cb(struct nl_msg *msg, void *arg);
static monitorinet::CallFromStaticFunc * forward ;
public:
MonitorWirelessDevice();
~MonitorWirelessDevice();
MonitorWirelessDevice(const MonitorWirelessDevice &) = delete ;
MonitorWirelessDevice & operator=(const MonitorWirelessDevice&) = delete ;
void start();
void stop();
bool started();
/**
* \brief set new interface notification callback
* \param CallbackFunction - defined earlier as typedef std::function<void(WirelessDevice)> CallbackFunction
* \return void
*/
void setNewInetCallback(CallbackFunction);
/**
* \brief set delete interface notification callback
* \param CallbackFunction - defined earlier as typedef std::function<void(WirelessDevice)> CallbackFunction
* \return void
*/
void setInitInetCallback(CallbackFunction);
/**
* \brief set interface initial list notification callback
* \param CallbackFunction - defined earlier as typedef std::function<void(WirelessDevice)> CallbackFunction
* \return void
*/
void setDelInetCallback(CallbackFunction);
/**
*\fn int get_interface_infos()
* \brief Uses nl80211 to initialize a list of wireless interfaces Processes multiple netlink messages containing interface data
*\return error codes
*/
int get_winterface_infos(int);
int recv_winterface_infos(struct nl_msg *msg);
int recv_winterface_extra_infos(struct nl_msg *msg);
int handle_iee80211_com_finish(void *arg);
int nl80211_init() ;
};
/**
* \namespace monitorinet
*
* A namespace is used here, since a class CallFromStaticFunc is defined in other files
*/
namespace monitorinet {
/**
* \class CallFromStaticFunc
* \brief this class is an artifact used to call a member function from static function
*/
class CallFromStaticFunc {
MonitorWirelessDevice * m_obj ;
public:
explicit CallFromStaticFunc(MonitorWirelessDevice * obj){
m_obj = obj ;
};
int recv_winterface_infos(struct nl_msg *msg) {
// add exception to check null ptr
m_obj->recv_winterface_infos(msg);
return 0 ;
};
int recv_winterface_extra_infos(struct nl_msg *msg) {
// add exception to check null ptr
m_obj->recv_winterface_extra_infos(msg);
return 0 ;
};
int handle_iee80211_com_finish(void *arg) {
// add exception to check null ptr
m_obj->handle_iee80211_com_finish(arg);
return 0 ;
};
};
}
#endif
+33
View File
@@ -0,0 +1,33 @@
#ifndef _CONFIG_H_
#define _CONFIG_H_
#include "types.h" // TIndex / TPort
#ifndef DISABLE_VHOST
#define ENABLE_VHOST
#endif
const TIndex WIFI_MAX_DECONNECTED_CLIENT = 15;
const bool LOST_PACKET_BY_DEFAULT=false;
const TPort DEFAULT_WIFI_CLIENT_PORT_VHOST = 8211;
const TPort DEFAULT_WIFI_CLIENT_PORT_INET = DEFAULT_WIFI_CLIENT_PORT_VHOST+1;
const TPort DEFAULT_WIFI_SPY_PORT = DEFAULT_WIFI_CLIENT_PORT_VHOST+2;
const TPort DEFAULT_CTRL_PORT = DEFAULT_WIFI_CLIENT_PORT_VHOST+3;
#define DEFAULT_ADDRESS_IP "127.0.0.1"
const int MAX_SIZE_NAME=12;
const int DEFAULT_NUMBER_WLAN_INTERFACE=0;
#define DEFAULT_MAC_PREFIX "74:F8:F6"
#ifdef _DEBUG
// #define _VERBOSE1
// #define _VERBOSE2
#endif
#endif
+8
View File
@@ -0,0 +1,8 @@
#ifndef _CONFIG_HWSIM_
#define _CONFIG_HWSIM_
#include "hwsim.h"
constexpr char KERNEL_HWSIM_FAMILY_NAME[] = "MAC80211_HWSIM";
#endif
+99
View File
@@ -0,0 +1,99 @@
#include <errno.h> // errno
#include <assert.h> // assert
#include <cstddef> // NULL
#include "cselect.h"
using namespace std;
CSelect::CSelect()
{
Init();
}
void CSelect::Init()
{
//clear the socket set
FD_ZERO(&Master);
//clear the socket set
FD_ZERO(&Dup);
MaxDescriptor=-1;
}
void CSelect::UpdateMaxDescriptor(TDescriptor descriptor)
{
//highest file descriptor number, need it for the select function
if ( descriptor > MaxDescriptor )
MaxDescriptor=descriptor;
}
bool CSelect::AddNode(TDescriptor descriptor)
{
//add new socket to array of sockets
ListNodes.push_back(descriptor);
//add child sockets to set
FD_SET( descriptor , &Master);
//highest file descriptor number, need it for the select function
UpdateMaxDescriptor(descriptor);
return true;
}
void CSelect::DelNode(TDescriptor descriptor)
{
MaxDescriptor=-1;
for (auto node = ListNodes.begin() ; node != ListNodes.end(); ++node)
{
if( *node == descriptor )
{
auto node_to_delete = node;
FD_CLR(descriptor , &Master);
for (++node ; node != ListNodes.end(); ++node)
UpdateMaxDescriptor(*node);
ListNodes.erase(node_to_delete);
return;
}
UpdateMaxDescriptor(*node);
}
}
TDescriptor CSelect::Wait()
{
return Wait(NULL);
}
TDescriptor CSelect::Wait(const sigset_t *sigmask)
{
/* back up master */
Dup = Master;
//wait for an activity on one of the sockets , timeout is NULL ,
//so wait indefinitely
int activity=pselect( MaxDescriptor + 1 , &Dup , NULL , NULL , NULL, sigmask);
if ((activity < 0) && (errno!=EINTR))
return SCHEDULER_ERROR;
return activity;
}
bool CSelect::DescriptorHasAction(TDescriptor descriptor)
{
return FD_ISSET( descriptor , &Dup);
}
bool CSelect::NodeHasAction(TIndex index)
{
assert( index < ListNodes.size() );
return FD_ISSET( ListNodes[index] , &Dup);
}
+45
View File
@@ -0,0 +1,45 @@
#ifndef _CSELECT_H_
#define _CSELECT_H_
#include <sys/select.h> // fd_set
#include <sys/socket.h>
#include <vector> // vector
#include "types.h" // TDescriptor
const int SCHEDULER_ERROR=-1;
class CSelect
{
private :
//set of socket descriptors
fd_set Master;
fd_set Dup;
TDescriptor MaxDescriptor;
std::vector<TDescriptor> ListNodes;
void UpdateMaxDescriptor(TDescriptor descriptor);
void Init();
public :
CSelect();
bool AddNode(TDescriptor descriptor);
void DelNode(TDescriptor descriptor);
TDescriptor Wait();
TDescriptor Wait(const sigset_t *sigmask);
bool DescriptorHasAction(TDescriptor descriptor);
bool NodeHasAction(TIndex index);
};
#endif
+106
View File
@@ -0,0 +1,106 @@
#include <cstdio> //perror
#include <iostream> // cout
#include <sys/socket.h> //socket
#include <arpa/inet.h> // struct sockaddr_in & inet_ntoa & ntohs
#include <linux/vm_sockets.h> // struct sockaddr_vm
#include <unistd.h> // close
#include <fcntl.h> // F_GETFL O_NONBLOCK
#include "csocket.h"
using namespace std;
CSocket::CSocket()
{
Master=0;
}
CSocket::~CSocket()
{
Close();
}
CSocket::CSocket( const CSocket & socket )
{
Master=socket.Master;
}
TDescriptor CSocket::GetDescriptor() const
{
return Master;
}
ssize_t CSocket::Send(TDescriptor descriptor, const char* data, ssize_t sizeOfData)
{
ssize_t ret = send(descriptor, data, sizeOfData, 0);
if ( ret != sizeOfData )
return SOCKET_ERROR ;
return ret;
}
ssize_t CSocket::SendBigData(TDescriptor descriptor, const char* data, TMinimalSize sizeOfData)
{
ssize_t ret = Send(descriptor, (char*)&sizeOfData, (unsigned)sizeof(sizeOfData));
if( ret == SOCKET_ERROR )
return SOCKET_ERROR;
return Send(descriptor, data, sizeOfData);
}
ssize_t CSocket::Read(TDescriptor descriptor, char* data, ssize_t sizeOfData)
{
ssize_t ret = recv(descriptor , data, sizeOfData, 0);
if ( ret <= 0 )
return SOCKET_ERROR ;
return ret;
}
ssize_t CSocket::ReadEqualSize(TDescriptor descriptor, CDynBuffer* data, ssize_t byteAlreadyRead, ssize_t sizeToRead)
{
ssize_t sizeToRead_backup = sizeToRead;
sizeToRead-=byteAlreadyRead;
data->NeededSize(sizeToRead_backup,(byteAlreadyRead!=0));
char* buffer = data->GetBuffer();
buffer+=byteAlreadyRead;
while( sizeToRead > 0 )
{
ssize_t sizeRead=Read(descriptor, buffer, sizeToRead);
if( sizeRead == SOCKET_ERROR )
return SOCKET_ERROR;
sizeToRead-=sizeRead;
buffer+=sizeRead;
}
return sizeToRead_backup;
}
ssize_t CSocket::ReadBigData(TDescriptor descriptor, CDynBuffer* data)
{
TMinimalSize size;
int ret = Read(descriptor, (char*)&size, (unsigned)sizeof(size));
if( ret == SOCKET_ERROR )
return SOCKET_ERROR;
return ReadEqualSize(descriptor, data, 0, size);
}
CSocket::operator int()
{
return Master;
}
void CSocket::Close()
{
close(Master);
}
+43
View File
@@ -0,0 +1,43 @@
#ifndef _CSOCKET_H_
#define _CSOCKET_H_
#include <sys/types.h> // ssize_t
#include "types.h" // TDescriptor / TSocket
#include "cdynbuffer.h" // CDynBuffer
const int SOCKET_ERROR=-1;
class CSocket
{
friend class CWifi;
protected :
TDescriptor Master;
CSocket();
CSocket( const CSocket & socket );
TDescriptor GetDescriptor() const;
virtual ssize_t Send(TDescriptor descriptor, const char* data, ssize_t sizeOfData);
virtual ssize_t SendBigData(TDescriptor descriptor, const char* data, TMinimalSize sizeOfData);
virtual ssize_t Read(TDescriptor descriptor, char* data, ssize_t sizeOfData);
virtual ssize_t ReadBigData(TDescriptor descriptor, CDynBuffer* data);
private :
ssize_t ReadEqualSize(TDescriptor descriptor, CDynBuffer* data, ssize_t byteAlreadyRead, ssize_t sizeToRead);
public :
void Close();
~CSocket();
operator int();
};
#endif
+102
View File
@@ -0,0 +1,102 @@
#include <iostream> // cout
#include <cstdio> //perror
#include <sys/ioctl.h> // ioctl
#include <fcntl.h> // open
#include <arpa/inet.h> // INADDR_ANY
#include <unistd.h> // close
#include <assert.h> // assert
#include "csocketclient.h"
#include "tools.h"
using namespace std;
// ----------------- CSocketClient
CSocketClient::~CSocketClient()
{
CSocket::Close();
}
CSocketClient::CSocketClient() : CSocket()
{
Init();
}
void CSocketClient::Init()
{
IsConnected=false;
StopTheReconnect=false ;
}
bool CSocketClient::ConnectLoop()
{
while ( ! StopTheReconnect )
{
if( _Connect() )
return true;
}
// The system asks to stop the reconnect
return false;
}
bool CSocketClient::Connect(struct sockaddr* server, size_t size_of_server)
{
if( ! _Configure() )
{
cerr<<"Error : CSocketClient::Connect : Configure"<<endl;
return false;
}
if( ! connect(Master,server,size_of_server) )
{
IsConnected=true;
return true;
}
perror("CSocketClient::Connect : connect");
Close();
sleep(2);
return false;
}
ssize_t CSocketClient::Send(const char* data, ssize_t sizeOfData)
{
if ( IsConnected ){
return CSocket::Send(Master, data, sizeOfData);
}
return SOCKET_ERROR;
}
ssize_t CSocketClient::SendBigData(const char* data, TMinimalSize sizeOfData)
{
if ( IsConnected ){
return CSocket::SendBigData(Master, data, sizeOfData);
}
return SOCKET_ERROR;
}
ssize_t CSocketClient::Read(char* data, ssize_t sizeOfData)
{
if ( IsConnected ){
return CSocket::Read(Master, data, sizeOfData);
}
return SOCKET_ERROR;
}
ssize_t CSocketClient::ReadBigData(CDynBuffer* data)
{
if ( IsConnected ){
return CSocket::ReadBigData(Master, data);
}
return SOCKET_ERROR;
}
+43
View File
@@ -0,0 +1,43 @@
#ifndef _CSOCKETCLIENT_H_
#define _CSOCKETCLIENT_H_
#include "csocket.h"
class CSocketClient : public CSocket
{
bool IsConnected;
bool StopTheReconnect;
void Init();
protected :
bool Connect(struct sockaddr* server, size_t size_of_server);
public :
CSocketClient();
virtual ~CSocketClient();
using CSocket::Send;
ssize_t Send(const char* data, ssize_t sizeOfData);
using CSocket::SendBigData;
ssize_t SendBigData(const char* data, TMinimalSize sizeOfData);
using CSocket::Read;
ssize_t Read(char* data, ssize_t sizeOfData);
using CSocket::ReadBigData;
ssize_t ReadBigData(CDynBuffer* data);
bool ConnectLoop();
// virtual :
virtual bool _Configure() = 0;
virtual bool _Connect() = 0;
virtual int _GetID() = 0;
};
#endif
+53
View File
@@ -0,0 +1,53 @@
#include <iostream> // cout
#include <cstdio> //perror
#include <sys/ioctl.h> // ioctl
#include <fcntl.h> // open
#include <arpa/inet.h> // INADDR_ANY
#include <unistd.h> // close
#include <assert.h> // assert
#include "csocketclientitcp.h"
#include "tools.h"
using namespace std;
CSocketClientITCP::CSocketClientITCP() : CSocketClient()
{
}
void CSocketClientITCP::Init(const char* IP, TPort port)
{
Server.sin_family = AF_INET;
Server.sin_addr.s_addr = inet_addr(IP);
Server.sin_port = htons(port);
}
bool CSocketClientITCP::_Configure()
{
Master = socket(AF_INET , SOCK_STREAM , 0);
if( Master == SOCKET_ERROR )
{
perror("CSocketClientITCP::Configure : socket");
return false;
}
return true;
}
bool CSocketClientITCP::_Connect()
{
return Connect((struct sockaddr*) &Server, sizeof(Server));
}
int CSocketClientITCP::_GetID()
{
struct sockaddr_in my_addr;
socklen_t len = sizeof(my_addr);
getsockname(Master, (struct sockaddr *) &my_addr, &len);
return hash_ipaddr(&my_addr) ;
}
+27
View File
@@ -0,0 +1,27 @@
#ifndef _CSOCKETCLIENTITCP_H_
#define _CSOCKETCLIENTITCP_H_
#include "csocketclient.h"
#include <netinet/ip.h> // struct sockaddr_in
class CSocketClientITCP : public CSocketClient
{
private :
struct sockaddr_in Server;
public :
CSocketClientITCP();
void Init(const char* IP, TPort port);
bool _Configure() override;
bool _Connect() override;
int _GetID() override;
};
#endif
+66
View File
@@ -0,0 +1,66 @@
#include <iostream> // cout
#include <cstdio> //perror
#include <sys/ioctl.h> // ioctl
#include <fcntl.h> // open
#include <arpa/inet.h> // INADDR_ANY
#include <unistd.h> // close
#include <assert.h> // assert
#include <cstring> // memset
#include "csocketclientvtcp.h"
#include "tools.h"
using namespace std;
CSocketClientVTCP::CSocketClientVTCP() : CSocketClient()
{
}
void CSocketClientVTCP::Init(TPort port)
{
memset(&Server, 0, sizeof(Server));
Server.svm_family = AF_VSOCK;
Server.svm_port = port;
Server.svm_cid = 2;
}
bool CSocketClientVTCP::_Configure()
{
Master = socket(AF_VSOCK , SOCK_STREAM , 0);
if( Master == SOCKET_ERROR )
{
perror("CSocketClientVTCP::Configure : socket");
return false;
}
return true;
}
bool CSocketClientVTCP::_Connect()
{
return Connect((struct sockaddr*) &Server, sizeof(Server));
}
int CSocketClientVTCP::_GetID()
{
int cid;
int ioctl_fd = open("/dev/vsock", 0);
if (ioctl_fd < 0)
{
perror("Error : CSocketClientVHOST::GetID : open /dev/vsock :");
return -1;
}
if( ioctl(ioctl_fd, IOCTL_VM_SOCKETS_GET_LOCAL_CID, &cid) < 0 )
{
perror("Error : CSocketClientVHOST::GetID : ioctl : Cannot get local CID :");
close(ioctl_fd);
return -1;
}
close(ioctl_fd);
return cid;
}
+28
View File
@@ -0,0 +1,28 @@
#ifndef _CSOCKETCLIENTVTCP_H_
#define _CSOCKETCLIENTVTCP_H_
#include <netinet/ip.h> // struct sockaddr_in
#include <linux/vm_sockets.h> // struct sockaddr_vm
#include "csocketclient.h"
class CSocketClientVTCP : public CSocketClient
{
private :
struct sockaddr_vm Server;
public :
CSocketClientVTCP();
void Init(TPort port);
bool _Configure() override;
bool _Connect() override;
int _GetID() override;
};
#endif
+166
View File
@@ -0,0 +1,166 @@
#include <iostream> // cout
#include <cstdio> //perror
#include <cstring> // memcpy
#include <assert.h> // assert
#include <arpa/inet.h> // INADDR_ANY
#include <sys/socket.h>
#include <linux/vm_sockets.h> // struct sockaddr_vm
#include "csocketserver.h"
using namespace std;
CSocketServer::CSocketServer(CListInfo<CInfoSocket>* infoSockets) : CSocket()
{
Init(0);
if( infoSockets == NULL )
{
InfoSockets = new CListInfo<CInfoSocket>;
ListInfoSelfManaged=true;
}
else
{
InfoSockets = infoSockets;
ListInfoSelfManaged=false;
}
}
CSocketServer::CSocketServer( const CSocketServer & socketServer ) : CSocket(socketServer)
{
*this=socketServer;
}
CSocketServer& CSocketServer::operator=(const CSocketServer& socketServer)
{
if( this != &socketServer )
{
// protect against invalid self-assignment
Init(socketServer.GetPort());
ListInfoSelfManaged=socketServer.ListInfoSelfManaged;
if( ListInfoSelfManaged )
{
if( InfoSockets != NULL )
delete InfoSockets;
InfoSockets = new CListInfo<CInfoSocket>(*(socketServer.InfoSockets));
}
else
{
InfoSockets = socketServer.InfoSockets;
}
}
// by convention, always return *this
return *this;
}
void CSocketServer::Init(TPort port)
{
Port=port;
}
TPort CSocketServer::GetPort() const
{
return Port;
}
CSocketServer::~CSocketServer()
{
for (auto& infoSocket : *InfoSockets)
infoSocket.Close();
delete InfoSockets;
CSocket::Close();
}
bool CSocketServer::Listen()
{
return _Listen(Master, Port);
}
TDescriptor CSocketServer::Accept(TCID& cid)
{
TDescriptor new_socket;
new_socket = _Accept(Master, cid);
if( new_socket == SOCKET_ERROR )
return SOCKET_ERROR;
//add new socket to array of sockets
InfoSockets->push_back(CInfoSocket(new_socket));
return new_socket;
}
TDescriptor CSocketServer::Accept()
{
TCID cid;
return Accept(cid);
}
TDescriptor CSocketServer::GetSocketClient(TIndex index) const
{
assert( index < InfoSockets->size() );
return (*InfoSockets)[index].GetDescriptor();
}
TDescriptor CSocketServer::operator[] (TIndex index)
{
return GetSocketClient(index);
}
TIndex CSocketServer::GetNumberClient() const
{
return InfoSockets->size();
}
bool CSocketServer::IsEnable(TIndex index)
{
assert( index < GetNumberClient() );
return (*InfoSockets)[index].IsEnable();
}
void CSocketServer::DisableClient(TIndex index)
{
assert( index < InfoSockets->size() );
(*InfoSockets)[index].DisableIt();
}
void CSocketServer::CloseClient(TIndex index)
{
assert( index < InfoSockets->size() );
(*InfoSockets)[index].Close();
InfoSockets->erase (InfoSockets->begin()+index);
}
ssize_t CSocketServer::Send(TDescriptor descriptor, const char* data, ssize_t sizeOfData)
{
return CSocket::Send(descriptor, data, sizeOfData);
}
ssize_t CSocketServer::SendBigData(TDescriptor descriptor, const char* data, TMinimalSize sizeOfData)
{
return CSocket::SendBigData(descriptor, data, sizeOfData);
}
ssize_t CSocketServer::Read(TDescriptor descriptor, char* data, ssize_t sizeOfData)
{
return CSocket::Read(descriptor, data, sizeOfData);
}
ssize_t CSocketServer::ReadBigData(TDescriptor descriptor, CDynBuffer* data)
{
return CSocket::ReadBigData(descriptor, data);
}
+63
View File
@@ -0,0 +1,63 @@
#ifndef _CSOCKETSERVER_H_
#define _CSOCKETSERVER_H_
#include "csocket.h"
#include "cinfosocket.h"
#include "clistinfo.h"
#include "types.h" // TIndex
class CSocketServer : public CSocket
{
protected :
TPort Port;
bool ListInfoSelfManaged;
CListInfo<CInfoSocket>* InfoSockets;
TDescriptor GetSocketClient(TIndex index) const;
TDescriptor Accept(TCID& cid);
TDescriptor Accept();
explicit CSocketServer(CListInfo<CInfoSocket>* infoSockets = NULL);
CSocketServer(TSocket type, CListInfo<CInfoSocket>* infoSockets = NULL);
CSocketServer( const CSocketServer & socketServer );
~CSocketServer();
CSocketServer& operator=(const CSocketServer& socketServer);
TPort GetPort() const;
void DisableClient(TIndex index);
void CloseClient(TIndex index);
ssize_t Send(TDescriptor descriptor, const char* data, ssize_t sizeOfData) override;
ssize_t SendBigData(TDescriptor descriptor, const char* data, TMinimalSize sizeOfData) override;
ssize_t Read(TDescriptor descriptor, char* data, ssize_t sizeOfData) override;
ssize_t ReadBigData(TDescriptor descriptor, CDynBuffer* data) override;
// virtual :
virtual bool _Listen(TDescriptor& master, TPort port) = 0;
virtual TDescriptor _Accept(TDescriptor master, TCID& cid) = 0;
public :
TIndex GetNumberClient() const;
TDescriptor operator[] (TIndex index);
bool IsEnable(TIndex index);
void Init(TPort port);
bool Listen();
};
#endif
+95
View File
@@ -0,0 +1,95 @@
#include <iostream> // cout
#include <cstdio> //perror
#include <cstring> // memcpy
#include <assert.h> // assert
#include <arpa/inet.h> // INADDR_ANY
#include <sys/socket.h>
#include "csocket.h" // SOCKET_ERROR
#include "csocketserverfunctionitcp.h"
#include "tools.h"
using namespace std;
bool CSocketServerFunctionITCP::Configure(TDescriptor& master)
{
//create a master socket
master = socket(AF_INET , SOCK_STREAM , 0);
if( master == SOCKET_ERROR )
{
perror("CSocketServerFunctionITCP::Configure : socket");
return false;
}
return true;
}
bool CSocketServerFunctionITCP::_Listen(TDescriptor& master, TPort port)
{
if( ! Configure(master) )
{
cerr<<"Error : CSocketServerFunctionITCP::_Listen : Configure"<<endl;
return false;
}
//set master socket to allow multiple connections ,
//this is just a good habit, it will work without this
int opt = 1 ; // TRUE
if( setsockopt(master, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0 )
{
perror("CSocketServerFunctionITCP::_Listen : setsockopt : SO_REUSEADDR");
return false;
}
struct timeval timeout;
timeout.tv_sec = 3;
timeout.tv_usec = 0;
if (setsockopt (master, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0)
perror("CSocketServerFunctionITCP::_Listen : setsockopt : SO_RCVTIMEO\n");
if (setsockopt (master, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)) < 0)
perror("CSocketServerFunctionITCP::_Listen : setsockopt : SO_SNDTIMEO\n");
//type of socket created
struct sockaddr_in address;
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( port );
//bind the socket
if (bind(master, (struct sockaddr *)&address, sizeof(address))<0)
{
perror("CSocketServer::_Listen : bind");
return false;
}
cout<<"Listener on port : "<<port<<endl;
//try to specify maximum of 3 pending connections for the master socket
if( listen(master, 3) < 0 )
{
perror("CSocketServerFunctionITCP::_Listen : listen");
return false;
}
return true;
}
TDescriptor CSocketServerFunctionITCP::_Accept(TDescriptor master, TCID& cid)
{
TDescriptor new_socket;
struct sockaddr_in address;
int addrlen = sizeof(address);
if( (new_socket = accept(master, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0 )
{
perror("CSocketServerFunctionITCP::_Accept : accept");
return SOCKET_ERROR;
}
cid=hash_ipaddr(&address);
return new_socket;
}
+20
View File
@@ -0,0 +1,20 @@
#ifndef _CSOCKETSERVERFUNCTIONITCP_H_
#define _CSOCKETSERVERFUNCTIONITCP_H_
#include "types.h"
class CSocketServerFunctionITCP
{
private :
bool Configure(TDescriptor& master);
protected:
bool _Listen(TDescriptor& master, TPort port);
TDescriptor _Accept(TDescriptor master, TCID& cid);
};
#endif
+91
View File
@@ -0,0 +1,91 @@
#include <iostream> // cout
#include <cstdio> //perror
#include <cstring> // memset
#include <assert.h> // assert
#include <arpa/inet.h> // INADDR_ANY
#include <sys/socket.h>
#include <linux/vm_sockets.h> // struct sockaddr_vm
#include "csocket.h" // SOCKET_ERROR
#include "csocketserverfunctionvtcp.h"
using namespace std;
bool CSocketServerFunctionVTCP::Configure(TDescriptor& master)
{
//create a master socket
master = socket(AF_VSOCK , SOCK_STREAM , 0);
if( master == SOCKET_ERROR )
{
perror("CSocketServerFunctionVTCP::_Configure : socket");
return false;
}
return true;
}
bool CSocketServerFunctionVTCP::_Listen(TDescriptor& master, TPort port)
{
if( ! Configure(master) )
{
cerr<<"Error : CSocketServerFunctionVTCP::_Listen : Configure"<<endl;
return false;
}
//type of socket created
struct sockaddr_vm address;
memset(&address, 0, sizeof(address));
address.svm_family = AF_VSOCK;
address.svm_port = port;
address.svm_cid = VMADDR_CID_ANY;
//bind the socket
if (bind(master, (struct sockaddr*)&address, sizeof(address)) != 0)
{
perror("CSocketServerFunctionVTCP::_Listen : bind");
return false;
}
/* Seems useless with VSOCK : the server detects immediately that a client is disconnected
struct timeval timeout;
timeout.tv_sec = 3;
timeout.tv_usec = 0;
if (setsockopt (master, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0)
perror("CSocketServerFunctionVTCP::_Listen : setsockopt : SO_RCVTIMEO\n");
if (setsockopt (master, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)) < 0)
perror("CSocketServerFunctionVTCP::_Listen : setsockopt : SO_SNDTIMEO\n");
*/
cout<<"Listener on port : "<<port<<endl;
//try to specify maximum of 3 pending connections for the master socket
if( listen(master, 3) < 0 )
{
perror("CSocketServerFunctionVTCP::_Listen : listen");
return false;
}
return true;
}
TDescriptor CSocketServerFunctionVTCP::_Accept(TDescriptor master, TCID& cid)
{
TDescriptor new_socket;
struct sockaddr_in address;
int addrlen = sizeof(address);
if( (new_socket = accept(master, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0 )
{
perror("CSocketServerFunctionVTCP::_Accept : accept");
return SOCKET_ERROR;
}
cid=((struct sockaddr_vm*)&address)->svm_cid;
return new_socket;
}
+20
View File
@@ -0,0 +1,20 @@
#ifndef _CSOCKETSERVERFUNCTIONVTCP_H_
#define _CSOCKETSERVERFUNCTIONVTCP_H_
#include "types.h"
class CSocketServerFunctionVTCP
{
private :
bool Configure(TDescriptor& master);
protected:
bool _Listen(TDescriptor& master, TPort port);
TDescriptor _Accept(TDescriptor master, TCID& cid);
};
#endif
+142
View File
@@ -0,0 +1,142 @@
#include "cthread.h"
#include <condition_variable>
#include <signal.h>
namespace intthread {
/*********************************************************/
/* Global variables and functions */
/********************************************************/
thread_local InterruptFlag this_thread_interrupt_flag ;
void interruption_point(){
if(this_thread_interrupt_flag.is_set())
{
throw thread_interrupted();
}
}
/*********************************************************/
/* InterruptFlag class definitions */
/********************************************************/
InterruptFlag::InterruptFlag()
{
_set = false ;
}
void InterruptFlag::set(){
std::lock_guard<std::mutex> guard(_mutex);
_set = true ;
}
bool InterruptFlag::is_set() {
std::lock_guard<std::mutex> guard(_mutex);
return _set ;
}
/*********************************************************/
/* InterruptibleThread class definitions */
/********************************************************/
int InterruptibleThread::number_thread = 0 ;
std::mutex InterruptibleThread::_number_thread_mutex ;
InterruptibleThread::InterruptibleThread(){
count_thread();
}
bool InterruptibleThread::started()
{
return _started ;
}
void InterruptibleThread::interrupt(){
if (_interrupt_flag != nullptr){
_interrupt_flag->set();
}
_started = false ;
}
void InterruptibleThread::join(){
_internal_thread.join();
}
pthread_t InterruptibleThread::get_native_handle(){
return _internal_thread.native_handle();
}
std::thread::id InterruptibleThread::get_id(){
return _internal_thread.get_id();
}
void InterruptibleThread::count_thread(){
std::unique_lock<std::mutex> lk(_number_thread_mutex);
number_thread++;
}
void InterruptibleThread::uncount_thread(){
std::unique_lock<std::mutex> lk(_number_thread_mutex);
number_thread--;
}
bool InterruptibleThread::all_thread_interrupted(){
std::unique_lock<std::mutex> lk(_number_thread_mutex);
return (number_thread == 0);
}
/*********************************************************/
/* AsyncTask class definitions */
/********************************************************/
AsyncTask::AsyncTask(){
}
void AsyncTask::dead() {
std::unique_lock<std::mutex> lk(_mutex_condition);
InterruptibleThread::uncount_thread() ;
_condition.notify_all();
lk.unlock();
}
}
+127
View File
@@ -0,0 +1,127 @@
#ifndef _CTHREAD_H_
#define _CTHREAD_H_
#include <pthread.h>
#include <thread>
#include <future>
#include <iostream>
#include <mutex>
//#include <functional>
namespace intthread {
void interruption_point();
struct thread_interrupted{};
class InterruptFlag
{
private:
bool _set ;
std::mutex _mutex ;
public:
InterruptFlag();
void set();
bool is_set() ;
};
class AsyncTask
{
protected :
std::condition_variable _condition ;
std::mutex _mutex_condition ;
public:
AsyncTask();
void dead() ;
};
extern thread_local InterruptFlag this_thread_interrupt_flag ;
class InterruptibleThread
{
private:
InterruptFlag* _interrupt_flag {nullptr} ;
std::thread _internal_thread ;
static int number_thread ;
static std::mutex _number_thread_mutex ;
bool _started {false} ;
public:
InterruptibleThread();
pthread_t get_native_handle();
/* include <functional> with this version */
/*template<typename CLASS>
void start(CLASS * obj , void (CLASS::* f)() ){
std::function< void(void)> _f = std::bind(f,*obj) ;
std::promise<InterruptFlag*> p ;
_internal_thread = std::thread([_f,&p]{
p.set_value(&this_thread_interrupt_flag);
_f();
});
_interrupt_flag = p.get_future().get();
}*/
bool started() ;
template <typename OBJECT, typename FUNC>
void start(OBJECT * obj , FUNC f ){
std::promise<InterruptFlag*> p ;
_internal_thread = std::thread([obj,f,&p]{
p.set_value(&this_thread_interrupt_flag);
(obj->*f)();
});
_interrupt_flag = p.get_future().get();
_started = true ;
}
void interrupt();
void join();
std::thread::id get_id();
static bool all_thread_interrupted();
static void count_thread();
static void uncount_thread();
};
} // intthread space
#endif
+97
View File
@@ -0,0 +1,97 @@
#include <math.h> // log10
#include <stdlib.h> // rand
#include <iostream>
#include <netlink/netlink.h> // (struct nlmsghdr *)
#include "hwsim.h" // HWSIM_ATTR_FREQ
#include <netlink/genl/genl.h> // genlmsg_parse
#include "cwifi.h"
//#include "config.h"
const double ConstanteC=92.45;
const TFrequency DEFAULT_FREQUENCY=2412; // Hz
const int MTU=2352; // Maximum Transmission Unit : 2352 (from include/linux/ieee80211.h)
TFrequency CWifi::GetFrequency(struct nlmsghdr* nlh)
{
/* we get the attributes*/
struct nlattr *attrs[HWSIM_ATTR_FREQ + 1];
genlmsg_parse(nlh, 0, attrs, HWSIM_ATTR_FREQ, NULL);
/* we get frequence */
if (attrs[HWSIM_ATTR_FREQ])
return nla_get_u32(attrs[HWSIM_ATTR_FREQ]);
else
return DEFAULT_FREQUENCY;
}
// distance : meter
// frequency : Hz
int CWifi::Attenuation(TDistance distance, TFrequency frequency)
{
if( distance == 0 )
return 0;
// ConstanteC+20*log10(frequency/1000)+20*log10(distance/1000);
// ConstanteC+20*(log10(frequency)-log10(1000))+20*(log10(distance)-log10(1000))
return ConstanteC+20*(log10(frequency)-3)+20*(log10(distance)-3);
}
TPower CWifi::BoundedPower(int power)
{
if( power < TPower_MIN )
return TPower_MIN;
if( power > TPower_MAX )
return TPower_MAX;
return power;
}
bool CWifi::PacketIsLost(TPower signalLevel)
{
//don't forget : signalLevel is negative
int alea = rand() % 53 + 40; // between 40 and 92
if( alea > -signalLevel )
return false;
return true;
}
ssize_t CWifi::SendSignalWithSocket(CSocket* socket, TDescriptor descriptor, TPower* power, const char* buffer, int sizeOfBuffer)
{
// cout<<"send power : "<<power<<endl;
int val=socket->Send(descriptor, reinterpret_cast<const char*>(power), sizeof(TPower));
if( val <= 0 )
return val;
// std::cout<<"send big data of size : "<<sizeOfBuffer<<std::endl;
return socket->Send(descriptor, buffer, sizeOfBuffer);
}
ssize_t CWifi::RecvSignalWithSocket(CSocket* socket, TDescriptor descriptor, TPower* power, CDynBuffer* buffer)
{
int valread;
// read the power
valread = socket->Read(descriptor, reinterpret_cast<char*>(power), sizeof(TPower));
if ( valread <= 0 )
return valread;
// read the signal
// "nlmsg_len" (type "uint32_t") is the first attribut of the "struct nlmsghdr" in "libnl3/netlink/netlink-kernel.h"
ssize_t sizeRead = socket->ReadEqualSize(descriptor, buffer, 0, sizeof(struct nlmsghdr));
if( sizeRead == SOCKET_ERROR )
return SOCKET_ERROR;
int sizeTotal=reinterpret_cast<struct nlmsghdr *>(buffer->GetBuffer())->nlmsg_len;
if( sizeTotal > MTU ) // to avoid that a error packet overfulls the memory
return SOCKET_ERROR;
return socket->ReadEqualSize(descriptor, buffer, sizeRead, sizeTotal);
}
+25
View File
@@ -0,0 +1,25 @@
#ifndef _WIFI_H_
#define _WIFI_H_
#include "types.h" // TPower
#include "csocket.h" // CSocket
class CWifi
{
protected :
TFrequency GetFrequency(struct nlmsghdr* nlh);
// distance : meter
int Attenuation(TDistance distance, TFrequency frequency);
// return power value between [TPower_MIN,TPower_MAX]
TPower BoundedPower(int power);
bool PacketIsLost(TPower signalLevel);
ssize_t SendSignalWithSocket(CSocket* socket, TDescriptor descriptor, TPower* power, const char* buffer, int sizeOfBuffer);
ssize_t RecvSignalWithSocket(CSocket* socket, TDescriptor descriptor, TPower* power, CDynBuffer* buffer);
};
#endif
+1
View File
@@ -0,0 +1 @@
#include "cwificlient.h"
+35
View File
@@ -0,0 +1,35 @@
#ifndef _CWIFICLIENT_H_
#define _CWIFICLIENT_H_
#include "ckernelwifi.h"
#include "csocketclient.h"
#include "cwifi.h"
template <typename TypeCSocketClient>
class CWifiClient : public CKernelWifi, public CWifi, public TypeCSocketClient
{
bool _Connect(int* id) override
{
if( ! TypeCSocketClient::_Connect() )
return false;
if( ! Scheduler.AddNode(*this) )
return false;
*id=TypeCSocketClient::_GetID();
return true;
}
ssize_t _SendSignal(TPower* power, const char* buffer, int sizeOfBuffer) override
{ return SendSignalWithSocket(this, this->GetDescriptor(), power, buffer, sizeOfBuffer); }
ssize_t _RecvSignal(TPower* power, CDynBuffer* buffer) override
{ return RecvSignalWithSocket(this, this->GetDescriptor(), power, buffer); }
void _Close() override { TypeCSocketClient::Close(); };
};
#endif /* _CWIFICLIENT_H_ */
+267
View File
@@ -0,0 +1,267 @@
#include <iostream> // cout
#include <cstdio> //perror
#include <cstring> // memcpy
#include <assert.h> // assert
#include <arpa/inet.h> // struct sockaddr_in
#include <sys/socket.h> // AF_VSOCK / AF_INET
#include <linux/vm_sockets.h> // struct sockaddr_vm
#include "cwifiserver.h"
#include "tools.h"
#include "config.h" // LOST_PACKET_BY_DEFAULT
bool CanLostPackets=LOST_PACKET_BY_DEFAULT;
using namespace std;
CWifiServer::CWifiServer() : CSocketServer ()
{
DefaultValues();
InfoWifis = new CListInfo<CInfoWifi>;
InfoWifisDeconnected = new CListInfo<CInfoWifi>;
}
CWifiServer::CWifiServer(CListInfo<CInfoSocket>* infoSockets, CListInfo<CInfoWifi>* infoWifis, CListInfo<CInfoWifi>* infoWifisDeconnected) : CSocketServer (infoSockets)
{
DefaultValues();
InfoWifis = infoWifis;
InfoWifisDeconnected = infoWifisDeconnected;
}
CWifiServer::CWifiServer( const CWifiServer & wifiServer ) : CSocketServer(wifiServer), CWifi(wifiServer)
{
*this=wifiServer;
}
CWifiServer::~CWifiServer()
{
if( ListInfoSelfManaged )
{
delete InfoWifis;
delete InfoWifisDeconnected;
}
}
CWifiServer& CWifiServer::operator=(const CWifiServer& wifiServer)
{
if( this != &wifiServer )
{
// protect against invalid self-assignment
MaxClientDeconnected=wifiServer.MaxClientDeconnected;
if( ListInfoSelfManaged )
{
if( InfoWifis != NULL )
{
delete InfoWifis;
delete InfoWifisDeconnected;
}
InfoWifis = new CListInfo<CInfoWifi>(*(wifiServer.InfoWifis));
InfoWifisDeconnected = new CListInfo<CInfoWifi>(*(wifiServer.InfoWifisDeconnected));
}
else
{
InfoWifis = wifiServer.InfoWifis;
InfoWifisDeconnected = wifiServer.InfoWifisDeconnected;
}
}
// by convention, always return *this
return *this;
}
void CWifiServer::DefaultValues()
{
MaxClientDeconnected=0;
}
bool CWifiServer::Listen(TIndex maxClientDeconnected)
{
MaxClientDeconnected=maxClientDeconnected;
if( ! _Listen(Master, Port) )
return false;
return true;
}
bool CWifiServer::RecoverInfosOfInfoWifiDeconnected(TCID cid, CCoordinate& coo, string& name)
{
for (auto infoWifiDeconnected = InfoWifisDeconnected->begin(); infoWifiDeconnected != InfoWifisDeconnected->end(); ++infoWifiDeconnected)
{
if ( infoWifiDeconnected->GetCid() == cid )
{
coo=*infoWifiDeconnected;
name=infoWifiDeconnected->GetName();
InfoWifisDeconnected->erase(infoWifiDeconnected);
return true;
}
}
return false;
}
bool CWifiServer::RecoverInfosOfInfoWifi(TCID cid, CCoordinate& coo, string& name)
{
int index=0;
for (auto& infoWifi : *InfoWifis)
{
if( IsEnable(index) )
if( infoWifi.GetCid() == cid )
{
coo=infoWifi;
name=infoWifi.GetName();
DisableClient(index);
return true;
}
index++;
}
return false;
}
TDescriptor CWifiServer::Accept()
{
TCID cid;
TDescriptor new_socket = CSocketServer::Accept(cid);
if( new_socket == SOCKET_ERROR )
return SOCKET_ERROR;
CInfoWifi infoWifi;
CCoordinate coo;
string name;
if( RecoverInfosOfInfoWifiDeconnected(cid,coo,name) || RecoverInfosOfInfoWifi(cid, coo,name) )
{
infoWifi.Set(coo);
infoWifi.SetName(name);
}
infoWifi.SetCid(cid);
InfoWifis->push_back(infoWifi);
return new_socket;
}
void CWifiServer::ShowInfoWifi(TIndex index)
{
assert( index < GetNumberClient() );
cout<<(*InfoWifis)[index];
}
void CWifiServer::CloseClient(TIndex index)
{
assert( index < GetNumberClient() );
CSocketServer::CloseClient(index);
// save the InfoWifi (the coordinate of the cid)
AddInfoWifiDeconnected( (*InfoWifis)[index] );
InfoWifis->erase(InfoWifis->begin()+index);
}
void CWifiServer::CloseAllClient()
{
// ( be careful : "TIndex i" is a **unsigned** int : i=0 ; i-1 != -1 but = 65534 )
TIndex nbre=GetNumberClient(); // because CloseClient changes the value of GetNumberClient()
for (TIndex i = 0; i < nbre; i++)
CloseClient(0); // we can Close the 0 because we use the shift
}
ssize_t CWifiServer::SendSignal(TDescriptor descriptor, TPower* power, const char* buffer, int sizeOfBuffer)
{
return SendSignalWithSocket(this, descriptor, power, buffer, sizeOfBuffer);
}
ssize_t CWifiServer::RecvSignal(TDescriptor descriptor, TPower* power, CDynBuffer* buffer)
{
return RecvSignalWithSocket(this, descriptor, power, buffer);
}
void CWifiServer::SendAllOtherClients(TIndex index,TPower power, const char* data, ssize_t sizeOfData)
{
CCoordinate coo=(*InfoWifis)[index];
// cout<<"Forward "<<sizeOfData<<" bytes with "<<power<<" powers"<<endl;
for (TIndex i = 0; i < GetNumberClient(); i++)
{
if( i != index )
if( IsEnable(i) )
{
TFrequency frequency = static_cast<TFrequency>(GetFrequency( reinterpret_cast<struct nlmsghdr*>(const_cast<char*>(data)) ));
TPower signalLevel=BoundedPower(power-Attenuation(coo.DistanceWith((*InfoWifis)[i]),frequency));
if( ! CanLostPackets || ! PacketIsLost(signalLevel) )
if( SendSignal((*InfoSockets)[i].GetDescriptor(), &signalLevel, data, sizeOfData) < 0 )
(*InfoSockets)[i].DisableIt();
}
}
}
void CWifiServer::SendAllOtherClientsWithoutLoss(TIndex index, TPower power, const char* data, ssize_t sizeOfData)
{
for (TIndex i = 0; i < GetNumberClient(); i++)
{
if( i != index )
if( IsEnable(i) )
if( SendSignal((*InfoSockets)[i].GetDescriptor(), &power, data, sizeOfData) < 0 )
(*InfoSockets)[i].DisableIt();
}
}
void CWifiServer::SendAllClientsWithoutLoss(TPower power, const char* data, ssize_t sizeOfData)
{
for (TIndex i = 0; i < GetNumberClient(); i++)
if( IsEnable(i) )
if( SendSignal((*InfoSockets)[i].GetDescriptor(), &power, data, sizeOfData) < 0 )
(*InfoSockets)[i].DisableIt();
}
CInfoWifi* CWifiServer::GetReferenceOnInfoWifiByCID(TCID cid) const
{
for (auto& infoWifi : *InfoWifis)
{
if( infoWifi.GetCid() == cid )
return &infoWifi;
}
return NULL;
}
CInfoWifi* CWifiServer::GetReferenceOnInfoWifiDeconnectedByCID(TCID cid) const
{
for (auto& infoWifiDeconnected : *InfoWifisDeconnected)
{
if( infoWifiDeconnected.GetCid() == cid )
return &infoWifiDeconnected;
}
return NULL;
}
CInfoWifi* CWifiServer::GetReferenceOnInfoWifiByIndex(TIndex index) const
{
assert( index < GetNumberClient() );
return &((*InfoWifis)[index]);
}
void CWifiServer::AddInfoWifiDeconnected(CInfoWifi infoWifi)
{
if( InfoWifisDeconnected->size() >= MaxClientDeconnected )
InfoWifisDeconnected->erase(InfoWifisDeconnected->begin());
InfoWifisDeconnected->push_back(infoWifi);
}
+67
View File
@@ -0,0 +1,67 @@
#ifndef _CWIFISERVER_H_
#define _CWIFISERVER_H_
#include "csocketserver.h"
#include "cinfowifi.h"
#include "cwifi.h"
extern bool CanLostPackets;
class CWifiServer : public CSocketServer, public CWifi
{
friend class CCTRLServer;
TIndex MaxClientDeconnected;
CListInfo<CInfoWifi>* InfoWifis;
CListInfo<CInfoWifi>* InfoWifisDeconnected;
bool RecoverInfosOfInfoWifiDeconnected(TCID cid, CCoordinate& coo, string& name);
bool RecoverInfosOfInfoWifi(TCID cid, CCoordinate& coo, string& name);
void DefaultValues();
public :
CWifiServer();
CWifiServer(CListInfo<CInfoSocket>* infoSockets, CListInfo<CInfoWifi>* infoWifis, CListInfo<CInfoWifi>* infoWifisDeconnected);
CWifiServer( const CWifiServer & wifiServer );
~CWifiServer();
CWifiServer& operator=(const CWifiServer& wifiServer);
bool Listen(TIndex maxClientDeconnected);
TDescriptor Accept();
void ShowInfoWifi(TIndex index);
void CloseClient(TIndex index);
void CloseAllClient();
ssize_t SendSignal(TDescriptor descriptor, TPower* power, const char* buffer, int sizeOfBuffer);
ssize_t RecvSignal(TDescriptor descriptor, TPower* power, CDynBuffer* buffer);
void SendAllOtherClients(TIndex index,TPower power, const char* data, ssize_t sizeOfData);
void SendAllOtherClientsWithoutLoss(TIndex index, TPower power, const char* data, ssize_t sizeOfData);
void SendAllClientsWithoutLoss(TPower power, const char* data, ssize_t sizeOfData);
CInfoWifi* GetReferenceOnInfoWifiByCID(TCID cid) const;
CInfoWifi* GetReferenceOnInfoWifiDeconnectedByCID(TCID cid) const;
CInfoWifi* GetReferenceOnInfoWifiByIndex(TIndex index) const;
void AddInfoWifiDeconnected(CInfoWifi infoWifi);
};
#endif
+19
View File
@@ -0,0 +1,19 @@
#include"cwifiserveritcp.h"
CWifiServerITCP::CWifiServerITCP() : CWifiServer()
{
}
CWifiServerITCP::CWifiServerITCP(CListInfo<CInfoSocket>* infoSockets, CListInfo<CInfoWifi>* infoWifis, CListInfo<CInfoWifi>* infoWifisDeconnected) : CWifiServer(infoSockets, infoWifis, infoWifisDeconnected)
{
}
bool CWifiServerITCP::_Listen(TDescriptor& master, TPort port)
{
return CSocketServerFunctionITCP::_Listen(master, port);
}
TDescriptor CWifiServerITCP::_Accept(TDescriptor master, TCID& cid)
{
return CSocketServerFunctionITCP::_Accept(master, cid);
}
+22
View File
@@ -0,0 +1,22 @@
#ifndef _CWIFISERVERITCP_H_
#define _CWIFISERVERITCP_H_
#include "csocketserverfunctionitcp.h"
#include "cwifiserver.h"
class CWifiServerITCP : public CWifiServer, public CSocketServerFunctionITCP
{
public:
CWifiServerITCP();
CWifiServerITCP(CListInfo<CInfoSocket>* infoSockets, CListInfo<CInfoWifi>* infoWifis, CListInfo<CInfoWifi>* infoWifisDeconnected);
private:
bool _Listen(TDescriptor& master, TPort port) override;
TDescriptor _Accept(TDescriptor master, TCID& cid) override;
};
#endif
+16
View File
@@ -0,0 +1,16 @@
#include"cwifiservervtcp.h"
CWifiServerVTCP::CWifiServerVTCP(CListInfo<CInfoSocket>* infoSockets, CListInfo<CInfoWifi>* infoWifis, CListInfo<CInfoWifi>* infoWifisDeconnected) : CWifiServer(infoSockets, infoWifis, infoWifisDeconnected)
{
}
bool CWifiServerVTCP::_Listen(TDescriptor& master, TPort port)
{
return CSocketServerFunctionVTCP::_Listen(master, port);
}
TDescriptor CWifiServerVTCP::_Accept(TDescriptor master, TCID& cid)
{
return CSocketServerFunctionVTCP::_Accept(master, cid);
}
+20
View File
@@ -0,0 +1,20 @@
#ifndef _CWIFISERVERVTCP_H_
#define _CWIFISERVERVTCP_H_
#include "csocketserverfunctionvtcp.h"
#include "cwifiserver.h"
class CWifiServerVTCP : public CWifiServer, public CSocketServerFunctionVTCP
{
public:
CWifiServerVTCP(CListInfo<CInfoSocket>* infoSockets, CListInfo<CInfoWifi>* infoWifis, CListInfo<CInfoWifi>* infoWifisDeconnected);
private :
bool _Listen(TDescriptor& master, TPort port) override;
TDescriptor _Accept(TDescriptor master, TCID& cid) override;
};
#endif
+107
View File
@@ -0,0 +1,107 @@
#include "cwirelessdevice.h"
#include <sys/socket.h>
#include <net/if_arp.h>
#include <cstring>
#include <regex>
const std::regex wlan("wlan[0-9]*");
WirelessDevice::WirelessDevice(){
}
WirelessDevice::~WirelessDevice(){
}
WirelessDevice::WirelessDevice(const std::string & name,int index ,int iftype ,const struct ether_addr & macaddr,int txpower):_name(name),_index(index),_iftype(iftype), _txpower(txpower), _macaddr(macaddr), _machwsim(macaddr) {
// _machwsim.ether_addr_octet[0] |= 0x40 ;
// std::memcpy(&_macaddr,&macaddr,ETH_ALEN);
}
WirelessDevice::WirelessDevice(const std::string & name,int index ,int iftype ,const struct ether_addr & macaddr,const struct ether_addr & machwsim,int txpower):_name(name),_index(index),_iftype(iftype), _txpower(txpower), _macaddr(macaddr), _machwsim(machwsim) {
}
std::string WirelessDevice::getName() const {
return _name ;
}
struct ether_addr WirelessDevice::getMacaddr() const {
return _macaddr ;
}
void WirelessDevice::setMachwsim(const struct ether_addr & machwsim) {
_machwsim = machwsim ;
// std::memcpy(&_macaddr,&macaddr,ETH_ALEN);
}
struct ether_addr WirelessDevice::getMachwsim() const {
return _machwsim ;
}
bool WirelessDevice::checkif_wireless_device(){
if (std::regex_match(_name,wlan))
return true ;
else
return false;
}
int WirelessDevice::getIndex() const {
return _index ;
}
int WirelessDevice::getTxPower() const {
return _txpower ;
}
// friend functions
std::ostream & operator<< ( std::ostream & os , const WirelessDevice & wdevice ){
char macstring[18];
char machwsimstring[18];
sprintf(macstring, "%02X:%02X:%02X:%02X:%02X:%02X",
wdevice._macaddr.ether_addr_octet[0], wdevice._macaddr.ether_addr_octet[1], wdevice._macaddr.ether_addr_octet[2],
wdevice._macaddr.ether_addr_octet[3], wdevice._macaddr.ether_addr_octet[4], wdevice._macaddr.ether_addr_octet[5]);
sprintf(machwsimstring, "%02X:%02X:%02X:%02X:%02X:%02X",
wdevice._machwsim.ether_addr_octet[0], wdevice._machwsim.ether_addr_octet[1], wdevice._machwsim.ether_addr_octet[2],
wdevice._machwsim.ether_addr_octet[3], wdevice._machwsim.ether_addr_octet[4], wdevice._machwsim.ether_addr_octet[5]);
os << "name: " << wdevice._name << std::endl ;
os << "index: " << wdevice._index << std::endl ;
/* ARPHRD_ETHER normal, ARPHRD_IEEE80211_RADIOTAP as monitor */
if (wdevice._iftype == ARPHRD_ETHER)
os << "iftype: ARPHRD_ETHER" << std::endl ;
else if (wdevice._iftype == ARPHRD_IEEE80211_RADIOTAP)
os << "iftype: ARPHRD_IEEE80211_RADIOTAP" << std::endl;
else
os << "iftype: UNKNOWN" << std::endl;
os << "mac:" << macstring << std::endl ;
os << "mac hwsim:" << machwsimstring << std::endl ;
os << "Tx-Power : " << wdevice._txpower / 100 << "." << wdevice._txpower % 100 << "dBm" << std::endl ;
return os ;
}
+60
View File
@@ -0,0 +1,60 @@
#ifndef _WIRELESSDEVICE_H
#define _WIRELESSDEVICE_H
#include <net/ethernet.h>
#include <string>
#include <iostream>
class WirelessDevice {
std::string _name;
int _index;
int _iftype;
//unsigned char _macaddr[ETH_ALEN];
int _txpower ;
struct ether_addr _macaddr ;
struct ether_addr _machwsim = {0x00,0X00,0x00,0X00,0x00,0X00};
public:
WirelessDevice();
~WirelessDevice();
/**
* \fn WirelessDevice(std::string n,int i,int t,const struct ether_addr & m,const struct ether_addr & h);
* \biref Constructor
* \param n - interface name
* i - index
* t - type
* m - wireless net device mac address
* h - wireless net device mac address in hwsim driver
*/
WirelessDevice(const std::string &,int,int,const struct ether_addr &,const struct ether_addr &,int);
/**
* \fn WirelessDevice(std::string n,int i,int t,const struct ether_addr & m);
* \biref Constructor
* \param n - interface name
* i - index
* t - type
* m - wireless net device mac address
*/
WirelessDevice(const std::string &,int,int,const struct ether_addr &,int);
friend std::ostream & operator<< ( std::ostream & , const WirelessDevice &);
struct ether_addr getMacaddr() const ;
struct ether_addr getMachwsim() const ;
void setMachwsim(const struct ether_addr &);
std::string getName() const ;
bool checkif_wireless_device();
int getIndex() const ;
int getTxPower() const ;
};
#endif
+102
View File
@@ -0,0 +1,102 @@
/**
* \file cwirelessdevicelist.cc
* \brief manage std::list of WirelessDevice objects
* \author
* \version
*/
#include "cwirelessdevicelist.h"
#include <cstring>
#include <algorithm> // std::transform
WirelessDeviceList::WirelessDeviceList(){
}
WirelessDeviceList::~WirelessDeviceList(){
}
bool WirelessDeviceList::get_device_by_mac(WirelessDevice & wdev , struct ether_addr macaddr) {
_listaccess.lock();
for (auto & wd : _wdevices_list){
struct ether_addr mac = wd.second.getMacaddr() ;
if(std::memcmp(&mac,&macaddr,ETH_ALEN) == 0){
wdev = wd.second ;
_listaccess.unlock();
return true ;
}
}
_listaccess.unlock();
return false ;
}
void WirelessDeviceList::add_device(const WirelessDevice & wdevice){
_listaccess.lock();
_wdevices_list[wdevice.getIndex()] = wdevice ;
_listaccess.unlock();
}
void WirelessDeviceList::delete_device(const WirelessDevice & wdevice){
_listaccess.lock();
_wdevices_list.erase(wdevice.getIndex()) ;
_listaccess.unlock();
}
void WirelessDeviceList::delete_device(int index){
_listaccess.lock();
_wdevices_list.erase(index);
_listaccess.unlock();
}
std::vector<WirelessDevice> & WirelessDeviceList::list_devices() {
std::vector<WirelessDevice> * list_wd = new std::vector<WirelessDevice>();
list_wd->reserve(_wdevices_list.size());
_listaccess.lock();
std::transform (_wdevices_list.begin(),
_wdevices_list.end(),
back_inserter(*list_wd),
[] (std::pair<int, WirelessDevice> const & pair)
{
return pair.second;
}
);
_listaccess.unlock();
return *(list_wd) ;
}
/** friend functions */
std::ostream & operator<< ( std::ostream & os , WirelessDeviceList & wdlist ){
wdlist._listaccess.lock();
for (const auto & wd : wdlist._wdevices_list){
os << wd.second;
os << std::endl ;
}
wdlist._listaccess.unlock();
return os ;
}
+85
View File
@@ -0,0 +1,85 @@
/**
* \file cwirelessdevicelist.h
* \brief manage std::list of WirelessDevice objects
* \author
* \version
*/
#ifndef _CWIRELESSDEVICELIST_H_
#define _CWIRELESSDEVICELIST_H_
#include <map>
#include <mutex>
#include <vector>
#include "cwirelessdevice.h"
/**
* \class WirelessDeviceList
* \brief This class represents a std::list of WirelessDevice objects
*/
class WirelessDeviceList {
/**
* \brief manage threads access to wdevices_list
*/
std::mutex _listaccess ;
/**
* \brief list of existing wireless network interfaces
*/
std::map<int,WirelessDevice> _wdevices_list;
public:
WirelessDeviceList();
~WirelessDeviceList();
/**
* \fn add_device(int)
* \brief Add to _wdevices_list a wireless network device
* \param wdevice Wireless network device
* \return void
*/
void add_device(const WirelessDevice & wdevice);
/**
* \fn delete_device(int)
* \brief Remove from _wdevice_list a wireless network device by index
* \param index Ifindex of wireless network device
* \return void
*/
void delete_device(int index);
/**
* \fn delete_device(const WirelessDevice & wdevice)
* \brief Remove from _wdevice_list a wireless network device by index
* \param wdevice wireless network device to remove from _wdevices_list
* \return void
*/
void delete_device(const WirelessDevice & wdevice);
/**
* \fn list_devices()
* \brief Get a list of all wireless network devices
* \return std::vector List of all devices
*/
std::vector<WirelessDevice> & list_devices() ;
/**
* \fn get_device_by_mac(struct ether_addr macaddr)
* \brief Get a device related to mac address
* \param wdev : WirelessDevice to find
* \param macaddr : mac address to find
* \return true if found and false otherwise
*/
bool get_device_by_mac(WirelessDevice & wdev , struct ether_addr macaddr);
/**
* \brief << operator overidden
*/
friend std::ostream & operator<< ( std::ostream & , WirelessDeviceList &);
};
#endif
+16
View File
@@ -0,0 +1,16 @@
#ifndef _HWSIM_H_
#define _HWSIM_H_
#include "types.h"
#define __packed __attribute__((packed))
#define BIT(x) (1 << (x))
#include "mac80211_hwsim.h"
#define VERSION_NR 1
#endif /* _HWSIM_H_ */
+8
View File
@@ -0,0 +1,8 @@
#ifndef IEEE80211_H_
#define IEEE80211_H_
// From Kernel : include/net/mac80211.h
#define IEEE80211_TX_MAX_RATES 4
#endif /* IEEE80211_H_ */
+344
View File
@@ -0,0 +1,344 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* mac80211_hwsim - software simulator of 802.11 radio(s) for mac80211
* Copyright (c) 2008, Jouni Malinen <j@w1.fi>
* Copyright (c) 2011, Javier Lopez <jlopex@gmail.com>
* Copyright (C) 2020, 2022-2024 Intel Corporation
*/
#ifndef __MAC80211_HWSIM_H
#define __MAC80211_HWSIM_H
/**
* enum hwsim_tx_control_flags - flags to describe transmission info/status
*
* These flags are used to give the wmediumd extra information in order to
* modify its behavior for each frame
*
* @HWSIM_TX_CTL_REQ_TX_STATUS: require TX status callback for this frame.
* @HWSIM_TX_CTL_NO_ACK: tell the wmediumd not to wait for an ack
* @HWSIM_TX_STAT_ACK: Frame was acknowledged
*
*/
enum hwsim_tx_control_flags {
HWSIM_TX_CTL_REQ_TX_STATUS = BIT(0),
HWSIM_TX_CTL_NO_ACK = BIT(1),
HWSIM_TX_STAT_ACK = BIT(2),
};
/**
* DOC: Frame transmission/registration support
*
* Frame transmission and registration support exists to allow userspace
* entities such as wmediumd to receive and process all broadcasted
* frames from a mac80211_hwsim radio device.
*
* This allow user space applications to decide if the frame should be
* dropped or not and implement a wireless medium simulator at user space.
*
* Registration is done by sending a register message to the driver and
* will be automatically unregistered if the user application doesn't
* responds to sent frames.
* Once registered the user application has to take responsibility of
* broadcasting the frames to all listening mac80211_hwsim radio
* interfaces.
*
* For more technical details, see the corresponding command descriptions
* below.
*/
/**
* enum hwsim_commands - supported hwsim commands
*
* @HWSIM_CMD_UNSPEC: unspecified command to catch errors
*
* @HWSIM_CMD_REGISTER: request to register and received all broadcasted
* frames by any mac80211_hwsim radio device.
* @HWSIM_CMD_FRAME: send/receive a broadcasted frame from/to kernel/user
* space, uses:
* %HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_ADDR_RECEIVER,
* %HWSIM_ATTR_FRAME, %HWSIM_ATTR_FLAGS, %HWSIM_ATTR_RX_RATE,
* %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE, %HWSIM_ATTR_FREQ (optional)
* @HWSIM_CMD_TX_INFO_FRAME: Transmission info report from user space to
* kernel, uses:
* %HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_FLAGS,
* %HWSIM_ATTR_TX_INFO, %WSIM_ATTR_TX_INFO_FLAGS,
* %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE
* @HWSIM_CMD_NEW_RADIO: create a new radio with the given parameters,
* returns the radio ID (>= 0) or negative on errors, if successful
* then multicast the result, uses optional parameter:
* %HWSIM_ATTR_REG_STRICT_REG, %HWSIM_ATTR_SUPPORT_P2P_DEVICE,
* %HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE, %HWSIM_ATTR_CHANNELS,
* %HWSIM_ATTR_NO_VIF, %HWSIM_ATTR_RADIO_NAME, %HWSIM_ATTR_USE_CHANCTX,
* %HWSIM_ATTR_REG_HINT_ALPHA2, %HWSIM_ATTR_REG_CUSTOM_REG,
* %HWSIM_ATTR_PERM_ADDR
* @HWSIM_CMD_DEL_RADIO: destroy a radio, reply is multicasted
* @HWSIM_CMD_GET_RADIO: fetch information about existing radios, uses:
* %HWSIM_ATTR_RADIO_ID
* @HWSIM_CMD_ADD_MAC_ADDR: add a receive MAC address (given in the
* %HWSIM_ATTR_ADDR_RECEIVER attribute) to a device identified by
* %HWSIM_ATTR_ADDR_TRANSMITTER. This lets wmediumd forward frames
* to this receiver address for a given station.
* @HWSIM_CMD_DEL_MAC_ADDR: remove the MAC address again, the attributes
* are the same as to @HWSIM_CMD_ADD_MAC_ADDR.
* @HWSIM_CMD_START_PMSR: request to start peer measurement with the
* %HWSIM_ATTR_PMSR_REQUEST. Result will be sent back asynchronously
* with %HWSIM_CMD_REPORT_PMSR.
* @HWSIM_CMD_ABORT_PMSR: Abort previously started peer measurement.
* @HWSIM_CMD_REPORT_PMSR: Report peer measurement data.
* @__HWSIM_CMD_MAX: enum limit
*/
enum hwsim_commands {
HWSIM_CMD_UNSPEC,
HWSIM_CMD_REGISTER,
HWSIM_CMD_FRAME,
HWSIM_CMD_TX_INFO_FRAME,
HWSIM_CMD_NEW_RADIO,
HWSIM_CMD_DEL_RADIO,
HWSIM_CMD_GET_RADIO,
HWSIM_CMD_ADD_MAC_ADDR,
HWSIM_CMD_DEL_MAC_ADDR,
HWSIM_CMD_START_PMSR,
HWSIM_CMD_ABORT_PMSR,
HWSIM_CMD_REPORT_PMSR,
__HWSIM_CMD_MAX,
};
#define HWSIM_CMD_MAX (_HWSIM_CMD_MAX - 1)
#define HWSIM_CMD_CREATE_RADIO HWSIM_CMD_NEW_RADIO
#define HWSIM_CMD_DESTROY_RADIO HWSIM_CMD_DEL_RADIO
/**
* enum hwsim_attrs - hwsim netlink attributes
*
* @HWSIM_ATTR_UNSPEC: unspecified attribute to catch errors
*
* @HWSIM_ATTR_ADDR_RECEIVER: MAC address of the radio device that
* the frame is broadcasted to
* @HWSIM_ATTR_ADDR_TRANSMITTER: MAC address of the radio device that
* the frame was broadcasted from
* @HWSIM_ATTR_FRAME: Data array
* @HWSIM_ATTR_FLAGS: mac80211 transmission flags, used to process
* properly the frame at user space
* @HWSIM_ATTR_RX_RATE: estimated rx rate index for this frame at user
* space
* @HWSIM_ATTR_SIGNAL: estimated RX signal for this frame at user
* space
* @HWSIM_ATTR_TX_INFO: ieee80211_tx_rate array
* @HWSIM_ATTR_COOKIE: sk_buff cookie to identify the frame
* @HWSIM_ATTR_CHANNELS: u32 attribute used with the %HWSIM_CMD_CREATE_RADIO
* command giving the number of channels supported by the new radio
* @HWSIM_ATTR_RADIO_ID: u32 attribute used with %HWSIM_CMD_DESTROY_RADIO
* only to destroy a radio
* @HWSIM_ATTR_REG_HINT_ALPHA2: alpha2 for regulatoro driver hint
* (nla string, length 2)
* @HWSIM_ATTR_REG_CUSTOM_REG: custom regulatory domain index (u32 attribute)
* @HWSIM_ATTR_REG_STRICT_REG: request REGULATORY_STRICT_REG (flag attribute)
* @HWSIM_ATTR_SUPPORT_P2P_DEVICE: support P2P Device virtual interface (flag)
* @HWSIM_ATTR_USE_CHANCTX: used with the %HWSIM_CMD_CREATE_RADIO
* command to force use of channel contexts even when only a
* single channel is supported
* @HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE: used with the %HWSIM_CMD_CREATE_RADIO
* command to force radio removal when process that created the radio dies
* @HWSIM_ATTR_RADIO_NAME: Name of radio, e.g. phy666
* @HWSIM_ATTR_NO_VIF: Do not create vif (wlanX) when creating radio.
* @HWSIM_ATTR_PAD: padding attribute for 64-bit values, ignore
* @HWSIM_ATTR_FREQ: Frequency at which packet is transmitted or received.
* @HWSIM_ATTR_TX_INFO_FLAGS: additional flags for corresponding
* rates of %HWSIM_ATTR_TX_INFO
* @HWSIM_ATTR_PERM_ADDR: permanent mac address of new radio
* @HWSIM_ATTR_IFTYPE_SUPPORT: u32 attribute of supported interface types bits
* @HWSIM_ATTR_CIPHER_SUPPORT: u32 array of supported cipher types
* @HWSIM_ATTR_MLO_SUPPORT: claim MLO support (exact parameters TBD) for
* the new radio
* @HWSIM_ATTR_PMSR_SUPPORT: nested attribute used with %HWSIM_CMD_CREATE_RADIO
* to provide peer measurement capabilities. (nl80211_peer_measurement_attrs)
* @HWSIM_ATTR_PMSR_REQUEST: nested attribute used with %HWSIM_CMD_START_PMSR
* to provide details about peer measurement request (nl80211_peer_measurement_attrs)
* @HWSIM_ATTR_PMSR_RESULT: nested attributed used with %HWSIM_CMD_REPORT_PMSR
* to provide peer measurement result (nl80211_peer_measurement_attrs)
* @HWSIM_ATTR_MULTI_RADIO: Register multiple wiphy radios (flag).
* Adds one radio for each band. Number of supported channels will be set for
* each radio instead of for the wiphy.
* @__HWSIM_ATTR_MAX: enum limit
*/
enum hwsim_attrs {
HWSIM_ATTR_UNSPEC,
HWSIM_ATTR_ADDR_RECEIVER,
HWSIM_ATTR_ADDR_TRANSMITTER,
HWSIM_ATTR_FRAME,
HWSIM_ATTR_FLAGS,
HWSIM_ATTR_RX_RATE,
HWSIM_ATTR_SIGNAL,
HWSIM_ATTR_TX_INFO,
HWSIM_ATTR_COOKIE,
HWSIM_ATTR_CHANNELS,
HWSIM_ATTR_RADIO_ID,
HWSIM_ATTR_REG_HINT_ALPHA2,
HWSIM_ATTR_REG_CUSTOM_REG,
HWSIM_ATTR_REG_STRICT_REG,
HWSIM_ATTR_SUPPORT_P2P_DEVICE,
HWSIM_ATTR_USE_CHANCTX,
HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE,
HWSIM_ATTR_RADIO_NAME,
HWSIM_ATTR_NO_VIF,
HWSIM_ATTR_FREQ,
HWSIM_ATTR_PAD,
HWSIM_ATTR_TX_INFO_FLAGS,
HWSIM_ATTR_PERM_ADDR,
HWSIM_ATTR_IFTYPE_SUPPORT,
HWSIM_ATTR_CIPHER_SUPPORT,
HWSIM_ATTR_MLO_SUPPORT,
HWSIM_ATTR_PMSR_SUPPORT,
HWSIM_ATTR_PMSR_REQUEST,
HWSIM_ATTR_PMSR_RESULT,
HWSIM_ATTR_MULTI_RADIO,
__HWSIM_ATTR_MAX,
};
#define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1)
/**
* struct hwsim_tx_rate - rate selection/status
*
* @idx: rate index to attempt to send with
* @count: number of tries in this rate before going to the next rate
*
* A value of -1 for @idx indicates an invalid rate and, if used
* in an array of retry rates, that no more rates should be tried.
*
* When used for transmit status reporting, the driver should
* always report the rate and number of retries used.
*
*/
struct hwsim_tx_rate {
s8 idx;
u8 count;
} __packed;
/**
* enum hwsim_tx_rate_flags - per-rate flags set by the rate control algorithm.
* Inspired by structure mac80211_rate_control_flags. New flags may be
* appended, but old flags not deleted, to keep compatibility for
* userspace.
*
* These flags are set by the Rate control algorithm for each rate during tx,
* in the @flags member of struct ieee80211_tx_rate.
*
* @MAC80211_HWSIM_TX_RC_USE_RTS_CTS: Use RTS/CTS exchange for this rate.
* @MAC80211_HWSIM_TX_RC_USE_CTS_PROTECT: CTS-to-self protection is required.
* This is set if the current BSS requires ERP protection.
* @MAC80211_HWSIM_TX_RC_USE_SHORT_PREAMBLE: Use short preamble.
* @MAC80211_HWSIM_TX_RC_MCS: HT rate.
* @MAC80211_HWSIM_TX_RC_VHT_MCS: VHT MCS rate, in this case the idx field is
* split into a higher 4 bits (Nss) and lower 4 bits (MCS number)
* @MAC80211_HWSIM_TX_RC_GREEN_FIELD: Indicates whether this rate should be used
* in Greenfield mode.
* @MAC80211_HWSIM_TX_RC_40_MHZ_WIDTH: Indicates if the Channel Width should be
* 40 MHz.
* @MAC80211_HWSIM_TX_RC_80_MHZ_WIDTH: Indicates 80 MHz transmission
* @MAC80211_HWSIM_TX_RC_160_MHZ_WIDTH: Indicates 160 MHz transmission
* (80+80 isn't supported yet)
* @MAC80211_HWSIM_TX_RC_DUP_DATA: The frame should be transmitted on both of
* the adjacent 20 MHz channels, if the current channel type is
* NL80211_CHAN_HT40MINUS or NL80211_CHAN_HT40PLUS.
* @MAC80211_HWSIM_TX_RC_SHORT_GI: Short Guard interval should be used for this
* rate.
*/
enum hwsim_tx_rate_flags {
MAC80211_HWSIM_TX_RC_USE_RTS_CTS = BIT(0),
MAC80211_HWSIM_TX_RC_USE_CTS_PROTECT = BIT(1),
MAC80211_HWSIM_TX_RC_USE_SHORT_PREAMBLE = BIT(2),
/* rate index is an HT/VHT MCS instead of an index */
MAC80211_HWSIM_TX_RC_MCS = BIT(3),
MAC80211_HWSIM_TX_RC_GREEN_FIELD = BIT(4),
MAC80211_HWSIM_TX_RC_40_MHZ_WIDTH = BIT(5),
MAC80211_HWSIM_TX_RC_DUP_DATA = BIT(6),
MAC80211_HWSIM_TX_RC_SHORT_GI = BIT(7),
MAC80211_HWSIM_TX_RC_VHT_MCS = BIT(8),
MAC80211_HWSIM_TX_RC_80_MHZ_WIDTH = BIT(9),
MAC80211_HWSIM_TX_RC_160_MHZ_WIDTH = BIT(10),
};
/**
* struct hwsim_tx_rate_flag - rate selection/status
*
* @idx: rate index to attempt to send with
* @flags: the rate flags according to &enum hwsim_tx_rate_flags
*
* A value of -1 for @idx indicates an invalid rate and, if used
* in an array of retry rates, that no more rates should be tried.
*
* When used for transmit status reporting, the driver should
* always report the rate and number of retries used.
*
*/
struct hwsim_tx_rate_flag {
s8 idx;
u16 flags;
} __packed;
/**
* DOC: Frame transmission support over virtio
*
* Frame transmission is also supported over virtio to allow communication
* with external entities.
*/
/**
* enum hwsim_vqs - queues for virtio frame transmission
*
* @HWSIM_VQ_TX: send frames to external entity
* @HWSIM_VQ_RX: receive frames and transmission info reports
* @HWSIM_NUM_VQS: enum limit
*/
enum hwsim_vqs {
HWSIM_VQ_TX,
HWSIM_VQ_RX,
HWSIM_NUM_VQS,
};
/**
* enum hwsim_rate_info_attributes - bitrate information.
*
* Information about a receiving or transmitting bitrate
* that can be mapped to struct rate_info
*
* @__HWSIM_RATE_INFO_ATTR_INVALID: reserved, netlink attribute 0 is invalid
* @HWSIM_RATE_INFO_ATTR_FLAGS: bitflag of flags from &enum rate_info_flags
* @HWSIM_RATE_INFO_ATTR_MCS: mcs index if struct describes an HT/VHT/HE rate
* @HWSIM_RATE_INFO_ATTR_LEGACY: bitrate in 100kbit/s for 802.11abg
* @HWSIM_RATE_INFO_ATTR_NSS: number of streams (VHT & HE only)
* @HWSIM_RATE_INFO_ATTR_BW: bandwidth (from &enum rate_info_bw)
* @HWSIM_RATE_INFO_ATTR_HE_GI: HE guard interval (from &enum nl80211_he_gi)
* @HWSIM_RATE_INFO_ATTR_HE_DCM: HE DCM value
* @HWSIM_RATE_INFO_ATTR_HE_RU_ALLOC: HE RU allocation (from &enum nl80211_he_ru_alloc,
* only valid if bw is %RATE_INFO_BW_HE_RU)
* @HWSIM_RATE_INFO_ATTR_N_BOUNDED_CH: In case of EDMG the number of bonded channels (1-4)
* @HWSIM_RATE_INFO_ATTR_EHT_GI: EHT guard interval (from &enum nl80211_eht_gi)
* @HWSIM_RATE_INFO_ATTR_EHT_RU_ALLOC: EHT RU allocation (from &enum nl80211_eht_ru_alloc,
* only valid if bw is %RATE_INFO_BW_EHT_RU)
* @NUM_HWSIM_RATE_INFO_ATTRS: internal
* @HWSIM_RATE_INFO_ATTR_MAX: highest attribute number
*/
enum hwsim_rate_info_attributes {
__HWSIM_RATE_INFO_ATTR_INVALID,
HWSIM_RATE_INFO_ATTR_FLAGS,
HWSIM_RATE_INFO_ATTR_MCS,
HWSIM_RATE_INFO_ATTR_LEGACY,
HWSIM_RATE_INFO_ATTR_NSS,
HWSIM_RATE_INFO_ATTR_BW,
HWSIM_RATE_INFO_ATTR_HE_GI,
HWSIM_RATE_INFO_ATTR_HE_DCM,
HWSIM_RATE_INFO_ATTR_HE_RU_ALLOC,
HWSIM_RATE_INFO_ATTR_N_BOUNDED_CH,
HWSIM_RATE_INFO_ATTR_EHT_GI,
HWSIM_RATE_INFO_ATTR_EHT_RU_ALLOC,
/* keep last */
NUM_HWSIM_RATE_INFO_ATTRS,
HWSIM_RATE_INFO_ATTR_MAX = NUM_HWSIM_RATE_INFO_ATTRS - 1
};
#endif /* __MAC80211_HWSIM_H */
+71
View File
@@ -0,0 +1,71 @@
#include <cstddef> // NULL
#include <arpa/inet.h> // struct sockaddr_in & inet_ntoa & ntohs
#include "tools.h"
#include <assert.h> // assert
bool HashUsesPort=false;
unsigned long hash_ipaddr(struct sockaddr_in* addr)
{
unsigned long res;
assert( addr != NULL );
res = (((addr->sin_addr.s_addr >> 24) & 0xff) * 256) +
(((addr->sin_addr.s_addr >> 16) & 0xff) * 256) +
(((addr->sin_addr.s_addr >> 8) & 0xff)* 256) +
(addr->sin_addr.s_addr & 0xff);
if( HashUsesPort )
res += addr->sin_port;
return res;
}
bool isInt(const char *str) {
if( *str == '-' || *str == '+' )
str++;
while (*str) {
if( *str < '0' || *str > '9' )
return false;
str++;
}
return true;
}
bool isPositiveInt(const char *str)
{
if( *str == '-' )
return false;
return isInt(str);
}
bool isIntOrFloat(const char *str) {
bool seeDot=false;
bool seeDigit=false;
if (*str == '-' || *str == '+')
str++;
while (*str) {
if( *str == '.' )
{
if( seeDot )
return false;
seeDot=true;
}
else
{
if( *str < '0' || *str > '9' )
return false;
seeDigit=true;
}
str++;
}
return seeDigit;
}
+14
View File
@@ -0,0 +1,14 @@
#ifndef _TOOLS_H_
#define _TOOLS_H_
extern bool HashUsesPort;
unsigned long hash_ipaddr(struct sockaddr_in* addr);
bool isInt(const char *str);
bool isPositiveInt(const char *str);
bool isIntOrFloat(const char *str);
#endif
+54
View File
@@ -0,0 +1,54 @@
#ifndef _TYPES_H_
#define _TYPES_H_
#include <stdint.h>
typedef int8_t s8;
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint64_t u64;
typedef int32_t s32;
typedef uint32_t u32;
// int
typedef s32 TValue;
// unsigned int
typedef u32 TCID;
enum TOrder {
TORDER_NO, TORDER_LIST, TORDER_SHOW, TORDER_CHANGE_COORDINATE, TORDER_SETNAME, TORDER_PACKET_LOSS, TORDER_STATUS, TORDER_DISTANCE_BETWEEN_CID, TORDER_SET_SCALE, TORDER_CLOSE_ALL_CLIENT
};
// int
typedef s32 TDescriptor;
// unsigned int
typedef u32 TIndex;
// int
typedef s32 TSocket;
// AF_INET : use IP
// AF_VSOCK : use vsock
// unsigned short
typedef u16 TPort;
// char
typedef s8 TPower; // empirical observed values with int : [-123,20]
const TPower TPower_MAX=-10; // dBm is always negative. -10 is an empirical value
const TPower TPower_MIN=INT8_MIN;
// double
typedef double TDistance; // in meters
typedef double TScale;
// u32
typedef u32 TFrequency; // Hz
// unsigned short
typedef u16 TMinimalSize;
typedef u8 TByte;
#endif
+107
View File
@@ -0,0 +1,107 @@
/*
From : https://android.googlesource.com/device/generic/goldfish/+/refs/heads/master/wifi/mac80211_create_radios/main.cpp
Licence http://www.apache.org/licenses/LICENSE-2.0
*/
#include <memory>
#include <netlink/genl/ctrl.h>
#include <netlink/genl/genl.h>
#include <netlink/netlink.h>
#include <net/ethernet.h>
#include <climits>
#include <stdio.h>
#include <unistd.h> // getuid
#include "config_hwsim.h"
#include "addinterfaces.h"
#include "config.h" // DEFAULT_MAC_PREFIX
int ParseInt(const char* str, int* result)
{
return sscanf(str, "%d", result);
}
int help(FILE* dst, const int ret)
{
fprintf(dst, "%s",
"Usage:\n"
" vwifi-add-interfaces [-h] [-v] n_radios mac_prefix\n"
" vwifi-add-interfaces [--help] [--version] n_radios mac_prefix\n"
" where\n"
" n_radios - int, [1,100], e.g. 2\n"
" mac_prefix - xx:xx:xx:xx:xx (if n_radios > 1 then only the first 5 bytes are used\n"
" then all bytes are used)\n\n"
" vwifi-add-interfaces will create n_radios with MAC addresses xx:xx:xx:xx:xx:nn\n"
" where xx:xx:xx:xx:xx is the mac_prefix specified\n"
" and nn is incremented (from zero, and only if n_radios > 1)\n");
return ret;
}
int main(int argc, char* argv[])
{
int nRadios;
TByte macPrefix[ETH_ALEN]= {};
if( argc == 1 )
return help(stdout,0);
if( ! ParseAddress(DEFAULT_MAC_PREFIX,macPrefix) )
return help(stderr, 6);
if( strlen(DEFAULT_MAC_PREFIX) <= 8 )
{ // if possible, randomize the 4th byte
srand(time(NULL));
macPrefix[3]=rand()%100;
}
int arg_idx = 1;
int arg_used = 1;
while (arg_idx < argc)
{
if( ! strcmp("-v", argv[arg_idx]) || ! strcmp("--version", argv[arg_idx]) )
{
fprintf(stdout,"Version : %s\n",VERSION);
return 0;
}
if( ! strcmp("-h", argv[arg_idx]) || ! strcmp("--help", argv[arg_idx]) )
{
return help(stdout,0);
}
if( argv[arg_idx][0] == '-' )
{
fprintf(stderr,"Error : unknown parameter : %s\n",argv[arg_idx]);
return help(stderr, 1);
}
switch ( arg_used )
{
case 1 :
if (!ParseInt(argv[arg_idx], &nRadios))
return help(stderr, 2);
if (nRadios < 1)
return help(stderr, 3);
if (nRadios > 100)
return help(stderr, 4);
arg_used++;
break;
case 2 :
if( strlen(argv[arg_idx]) > 17 )
return help(stderr, 5);
if( ! ParseAddress(argv[arg_idx],macPrefix) )
return help(stderr, 6);
arg_used++;
break;
}
arg_idx++;
}
if( getuid() )
{
fprintf(stderr,"Error : This program must be run as root!!\n");
return 2;
}
return ManageRadios(nRadios, macPrefix);
}
+223
View File
@@ -0,0 +1,223 @@
#include <signal.h>
#include <unistd.h>
#include <iostream>
#include <string.h> // strcmp
#include <memory>
#include "config.h" // DEFAULT_WIFI_CLIENT_PORT_VHOST / DEFAULT_WIFI_CLIENT_PORT_INET
#include "tools.h" // isInt
#include "cwificlient.h"
#ifdef ENABLE_VHOST
#include "csocketclientvtcp.h"
#endif
#include "csocketclientitcp.h"
#include "addinterfaces.h"
enum STATE {
STARTED=1,
STOPPED ,
SUSPENDED
};
CKernelWifi* wifiClient;
enum STATE _state = STOPPED ;
void signal_handler(int signal_num)
{
switch(signal_num)
{
case SIGINT :
case SIGTERM :
case SIGQUIT :
std::cout << signal_num << std::endl ;
wifiClient->stop() ;
_state = STOPPED ;
break ;
case SIGTSTP:
std::cout << "This signal is ignored" << std::endl ;
break ;
default :
std::cerr << "Signal not handled" << std::endl ;
}
std::cout << "OUT SWITCH" << std::endl ;
}
void help()
{
#ifdef ENABLE_VHOST
std::cout<<"Usage: vwifi-client [-h] [-v] [-s] [IP_ADDR] [-p PORT] [-u] [-n NUMBER_INTERFACE] [-m MAC_PREFIX]"<<std::endl;
std::cout<<" [--help] [--version] [--spy] [IP_ADDR] [--port PORT] [--use-port-in-hash] [--number NUMBER_INTERFACE] [--mac MAC_PREFIX]"<<std::endl;
std::cout<<" By default : client mode : TCP : IP_ADDR="<<DEFAULT_ADDRESS_IP <<" PORT="<< DEFAULT_WIFI_CLIENT_PORT_INET << std::endl;
std::cout<<" client mode : VHOST : PORT="<< DEFAULT_WIFI_CLIENT_PORT_VHOST << std::endl;
std::cout<<" spy mode (--spy) : IP_ADDR="<< DEFAULT_ADDRESS_IP <<" PORT="<< DEFAULT_WIFI_SPY_PORT << std::endl;
std::cout<<" NUMBER_INTERFACE="<< DEFAULT_NUMBER_WLAN_INTERFACE <<" MAC_PREFIX="<< DEFAULT_MAC_PREFIX << std::endl;
#else
std::cout<<"Usage: vwifi-client [-h] [-v] [-s] IP_ADDR [-p PORT] [-u] [-n NUMBER_INTERFACE] [-m MAC_PREFIX]"<<std::endl;
std::cout<<" [--help] [--version] [--spy] IP_ADDR [--port PORT] [--use-port-in-hash] [--number NUMBER_INTERFACE] [--mac MAC_PREFIX]"<<std::endl;
std::cout<<" By default : client mode : TCP : IP_ADDR="<<DEFAULT_ADDRESS_IP <<" PORT="<< DEFAULT_WIFI_CLIENT_PORT_INET << std::endl;
std::cout<<" spy mode (--spy) : IP_ADDR="<< DEFAULT_ADDRESS_IP <<" PORT="<< DEFAULT_WIFI_SPY_PORT << std::endl;
std::cout<<" NUMBER_INTERFACE="<< DEFAULT_NUMBER_WLAN_INTERFACE <<" MAC_PREFIX="<< DEFAULT_MAC_PREFIX << std::endl;
#endif
}
int main (int argc , char ** argv){
bool spy = false;
std::string ip_addr;
TPort port_number = 0;
int number_interface=DEFAULT_NUMBER_WLAN_INTERFACE;
TByte mac_prefix[ETH_ALEN]={};
ParseAddress(DEFAULT_MAC_PREFIX, mac_prefix);
if( strlen(DEFAULT_MAC_PREFIX) <= 8 )
{ // if possible, randomize the 4th byte
srand(time(NULL));
mac_prefix[3]=rand()%100;
}
int arg_idx = 1;
while (arg_idx < argc)
{
if( ! strcmp("-v", argv[arg_idx]) || ! strcmp("--version", argv[arg_idx]) )
{
std::cout<<"Version : "<<VERSION<<std::endl;
return 0;
}
if( ! strcmp("-h", argv[arg_idx]) || ! strcmp("--help", argv[arg_idx]) )
{
help();
return 0;
}
if( ( ! strcmp("-p", argv[arg_idx]) || ! strcmp("--port", argv[arg_idx]) ) && (arg_idx + 1) < argc && isPositiveInt(argv[arg_idx+1]) )
{
port_number = std::stoi(argv[arg_idx+1]);
arg_idx++;
}
else if( ! strcmp("-u", argv[arg_idx]) || ! strcmp("--use-port-in-hash", argv[arg_idx]) )
{
HashUsesPort=true;
}
else if( ! strcmp("-s", argv[arg_idx]) || ! strcmp("--spy", argv[arg_idx]) )
{
spy=true;
}
else if( ( ! strcmp("-n", argv[arg_idx]) || ! strcmp("--number", argv[arg_idx]) ) && (arg_idx + 1) < argc && isPositiveInt(argv[arg_idx+1]) )
{
number_interface = std::stoi(argv[arg_idx+1]);
if (number_interface > 100)
{
std::cerr<<"Error : NUMBER > 100"<<std::endl;
return 4;
}
arg_idx++;
}
else if( ( ! strcmp("-m", argv[arg_idx]) || ! strcmp("--mac", argv[arg_idx]) ) && (arg_idx + 1) < argc)
{
std::string string = std::string(argv[arg_idx+1]);
if( string.size() > 17 )
{
std::cerr<<"Error : the MAC_PREFIX is too long"<<std::endl;
return 5;
}
if( ! ParseAddress(string.c_str(), mac_prefix) )
return 6;
arg_idx++;
}
else
{
if( ip_addr.empty() )
ip_addr = std::string(argv[arg_idx]);
else
{
std::cerr<<"Error : problem with this parameter : "<< argv[arg_idx] <<std::endl;
help();
return 1;
}
}
arg_idx++;
}
if( getuid() )
{
std::cerr<<"Error : This program must be run as root!!"<<std::endl;
return 2;
}
if( number_interface )
if( ManageRadios(number_interface,mac_prefix) )
return 7;
/* Handle signals */
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
signal(SIGQUIT, signal_handler);
signal(SIGHUP, SIG_IGN);
signal(SIGTSTP, signal_handler);
//signal(SIGCONT, signal_handler);
if( spy )
{ // mode TCP
if( ip_addr.empty() )
ip_addr = std::string(DEFAULT_ADDRESS_IP);
if( ! port_number )
port_number = DEFAULT_WIFI_SPY_PORT;
std::cout<<"Type : AF_INET"<<std::endl;
wifiClient=new CWifiClient<CSocketClientITCP>;
static_cast<CWifiClient<CSocketClientITCP>*>(wifiClient)->Init(ip_addr.c_str(), port_number);
}
else
{
if( ip_addr.empty() )
{ // IP not set -> mode VHOST
#ifdef ENABLE_VHOST
if( ! port_number )
port_number = DEFAULT_WIFI_CLIENT_PORT_VHOST;
std::cout<<"Type : AF_VSOCK"<<std::endl;
wifiClient=new CWifiClient<CSocketClientVTCP>;
static_cast<CWifiClient<CSocketClientVTCP>*>(wifiClient)->Init(port_number);
#else
std::cerr<<"Error : This program is not build with VHOST!!"<<std::endl;
return 8;
#endif
}
else
{ // mode TCP
if( ! port_number )
port_number = DEFAULT_WIFI_CLIENT_PORT_INET;
std::cout<<"Type : AF_INET"<<std::endl;
wifiClient=new CWifiClient<CSocketClientITCP>;
static_cast<CWifiClient<CSocketClientITCP>*>(wifiClient)->Init(ip_addr.c_str(), port_number);
}
}
if(!wifiClient->start())
std::cout << "Starting process aborted" << std::endl ;
std::cout << "Good Bye (:-)" << std::endl ;
_exit(EXIT_SUCCESS);
}
+807
View File
@@ -0,0 +1,807 @@
#include <iostream> // cout
#include <string.h> //strlen
#include "config.h"
#include "tools.h" // isInt isPositiveInt isIntOrFloat
#include "csocketclientitcp.h"
#include "types.h"
#include "ccoordinate.h" // CCoordinate
#include "cinfowifi.h"
using namespace std;
std::string IP_Ctrl = std::string(DEFAULT_ADDRESS_IP);
TPort Port_Ctrl = DEFAULT_CTRL_PORT;
char* NameOfProg;
void Help()
{
cout<<NameOfProg<<" [order]"<<endl;
cout<<" with [order] :"<<endl;
cout<<" ls"<<endl;
cout<<" - List the Clients"<<endl;
cout<<" set CID X Y Z"<<endl;
cout<<" - Change the coordinate of the Client with CID"<<endl;
cout<<" setname CID NAME"<<endl;
cout<<" - Set the NAME of the Client with CID"<<endl;
cout<<" loss yes/no"<<endl;
cout<<" - loss yes : packets can be lost"<<endl;
cout<<" - loss no : no packets can be lost"<<endl;
cout<<" show"<<endl;
cout<<" - Display the status of loss and list of Clients"<<endl;
cout<<" status"<<endl;
cout<<" - Display the status of the configuration of vwifi-server"<<endl;
cout<<" distance CID1 CID2"<<endl;
cout<<" - Display the distance in meters between the Client with CID1 and the Client with CID2"<<endl;
cout<<" scale VALUE"<<endl;
cout<<" - Set the scale of the distances between the clients to VALUE"<<endl;
cout<<" - VALUE can be a decimal number"<<endl;
cout<<" close"<<endl;
cout<<" - Close all the connections with Wifi Clients"<<endl;
cout<<endl;
cout<<" [-p PORT] or [--port PORT] : Set the port used by the vwifi-server (by default PORT="<< Port_Ctrl <<")"<<endl;
cout<<" [-i IP] or [--ip IP] : Set the IP used by the vwifi-server (by default IP="<< IP_Ctrl <<")"<<endl;
cout<<" [-v] or [--version] : Display the version of "<<NameOfProg<<endl;
cout<<" [-h] or [--help] : this help"<<endl;
}
int GetCInfoWifi(CSocketClientITCP & socket, CInfoWifi* infoWifi)
{
int err;
TCID cid;
err=socket.Read(reinterpret_cast<char*>(&cid),sizeof(cid));
if( err == SOCKET_ERROR )
{
cerr<<"Error : GetCInfoWifi : socket.Read : cid"<<endl;
return 1;
}
CCoordinate coo;
err=socket.Read(reinterpret_cast<char*>(&coo),sizeof(coo));
if( err == SOCKET_ERROR )
{
cerr<<"Error : GetCInfoWifi : socket.Read : CCoordinate (cid:"<<cid<<")"<<endl;
return 1;
}
int sizeName;
err=socket.Read(reinterpret_cast<char*>(&sizeName),sizeof(sizeName));
if( err == SOCKET_ERROR )
{
cerr<<"Error : GetCInfoWifi : socket.Read : size of name (cid:"<<cid<<")"<<endl;
return 1;
}
if( sizeName > MAX_SIZE_NAME )
{
cerr<<"Error : GetCInfoWifi : size of name > "<<MAX_SIZE_NAME<<" (cid:"<<cid<<")"<<endl;
return 1;
}
char strName[MAX_SIZE_NAME+1]; // +1 : \0
if( sizeName > 0 )
{
err=socket.Read(reinterpret_cast<char*>(strName),sizeName+1); // +1 : \0
if( err == SOCKET_ERROR )
{
cerr<<"Error : GetCInfoWifi : socket.Read : size of name (cid:"<<cid<<")"<<endl;
return 1;
}
}
else
strName[0]='\0';
infoWifi->SetCid(cid);
infoWifi->Set(coo);
string name(strName);
infoWifi->SetName(name);
return 0;
}
int AskList()
{
CSocketClientITCP socket;
socket.Init(IP_Ctrl.c_str(),Port_Ctrl);
if( ! socket.ConnectLoop() )
{
cerr<<"Error : ls : socket.Connect error"<<endl;
return 1;
}
int err;
TOrder order=TORDER_LIST;
err=socket.Send(reinterpret_cast<char*>(&order),sizeof(order));
if( err == SOCKET_ERROR )
{
cerr<<"Error : ls : socket.Send : order"<<endl;
return 1;
}
// Spies :
TIndex number;
err=socket.Read(reinterpret_cast<char*>(&number),sizeof(number));
if( err == SOCKET_ERROR )
{
cerr<<"Error : ls : socket.Read : number"<<endl;
return 1;
}
CInfoWifi info;
for(TIndex i=0; i<number;i++)
{
err=GetCInfoWifi(socket,&info);
if( err == SOCKET_ERROR )
{
cerr<<"Error : ls : socket.Read : CInfoWifi"<<endl;
return 1;
}
cout<<"S:"<<info.GetCid();
if( info.HasName() )
cout<<" ("<<info.GetName()<<")";
cout<<endl;
}
// Clients :
err=socket.Read(reinterpret_cast<char*>(&number),sizeof(number));
if( err == SOCKET_ERROR )
{
cerr<<"Error : ls : socket.Read : number"<<endl;
return 1;
}
for(TIndex i=0; i<number;i++)
{
err=GetCInfoWifi(socket,&info);
if( err == SOCKET_ERROR )
{
cerr<<"Error : ls : socket.Read : CInfoWifi"<<endl;
return 1;
}
cout<<info<<endl;
}
socket.Close();
return 0;
}
int ChangeCoordinate(int argc, char *argv[])
{
if( argc != 5 )
{
cerr<<"Error : set : the number of parameter is uncorrect"<<endl;
Help();
return 1;
}
if( ! isPositiveInt(argv[1]) )
{
cerr<<"Error : set : the CID is not an integer"<<endl;
return 1;
}
TCID cid=atoi(argv[1]);
if( cid < TCID_GUEST_MIN )
{
cerr<<"Error : set : the CID must be greater than or equal to "<<TCID_GUEST_MIN<<endl;
return 1;
}
if( ! isInt(argv[2]) )
{
cerr<<"Error : set : the x coordinate is not an integer"<<endl;
return 1;
}
if( ! isInt(argv[3]) )
{
cerr<<"Error : set : the y coordinate is not an integer"<<endl;
return 1;
}
if( ! isInt(argv[4]) )
{
cerr<<"Error : set : the z coordinate is not an integer"<<endl;
return 1;
}
TValue x=atoi(argv[2]);
TValue y=atoi(argv[3]);
TValue z=atoi(argv[4]);
CCoordinate coo(x,y,z);
cout<<cid<<" "<<coo<<" "<<endl;
CSocketClientITCP socket;
socket.Init(IP_Ctrl.c_str(),Port_Ctrl);
if( ! socket.ConnectLoop() )
{
cerr<<"Error : set : socket.Connect error"<<endl;
return 1;
}
int err;
TOrder order=TORDER_CHANGE_COORDINATE;
err=socket.Send(reinterpret_cast<char*>(&order),sizeof(order));
if( err == SOCKET_ERROR )
{
cerr<<"Error : set : socket.Send : order"<<endl;
return 1;
}
err=socket.Send(reinterpret_cast<char*>(&cid),sizeof(cid));
if( err == SOCKET_ERROR )
{
cerr<<"Error : set : socket.Send : cid"<<endl;
return 1;
}
err=socket.Send(reinterpret_cast<char*>(&coo),sizeof(coo));
if( err == SOCKET_ERROR )
{
cerr<<"Error : set : socket.Send : "<<coo<<endl;
return 1;
}
socket.Close();
return 0;
}
int SetName(int argc, char *argv[])
{
if( argc != 3 )
{
cerr<<"Error : setname : the number of parameter is uncorrect"<<endl;
Help();
return 1;
}
if( ! isPositiveInt(argv[1]) )
{
cerr<<"Error : setname : the CID is not an integer"<<endl;
return 1;
}
TCID cid=atoi(argv[1]);
if( cid < TCID_GUEST_MIN )
{
cerr<<"Error : setname : the CID must be greater than or equal to "<<TCID_GUEST_MIN<<endl;
return 1;
}
string name(argv[2]);
int sizeName=name.size();
if( name.length() > MAX_SIZE_NAME )
{
name.resize(MAX_SIZE_NAME);
sizeName=MAX_SIZE_NAME;
}
cout<<cid<<" "<<name<<" "<<endl;
CSocketClientITCP socket;
socket.Init(IP_Ctrl.c_str(),Port_Ctrl);
if( ! socket.ConnectLoop() )
{
cerr<<"Error : setname : socket.Connect error"<<endl;
return 1;
}
int err;
TOrder order=TORDER_SETNAME;
err=socket.Send(reinterpret_cast<char*>(&order),sizeof(order));
if( err == SOCKET_ERROR )
{
cerr<<"Error : setname : socket.Send : order"<<endl;
return 1;
}
err=socket.Send(reinterpret_cast<char*>(&cid),sizeof(cid));
if( err == SOCKET_ERROR )
{
cerr<<"Error : setname : socket.Send : cid"<<endl;
return 1;
}
err=socket.Send(reinterpret_cast<char*>(&sizeName),sizeof(sizeName));
if( err == SOCKET_ERROR )
{
cerr<<"Error : setname : socket.Send : size of name"<<endl;
return 1;
}
err=socket.Send(const_cast<char*>(name.c_str()),sizeName+1); // +1 : \0
if( err == SOCKET_ERROR )
{
cerr<<"Error : setname : socket.Send : name"<<name<<endl;
return 1;
}
socket.Close();
return 0;
}
int ChangePacketLoss(int argc, char *argv[])
{
if( argc != 2 )
{
cerr<<"Error : loss : the number of parameter is uncorrect"<<endl;
Help();
return 1;
}
int value;
if ( ! strcmp(argv[1],"yes") )
value=1;
else if ( ! strcmp(argv[1],"no") )
value=0;
else
{
cerr<<"Error : loss : the value can only be \"yes\" or \"no\""<<endl;
return 1;
}
CSocketClientITCP socket;
socket.Init(IP_Ctrl.c_str(),Port_Ctrl);
if( ! socket.ConnectLoop() )
{
cerr<<"Error : loss : socket.Connect error"<<endl;
return 1;
}
int err;
TOrder order=TORDER_PACKET_LOSS;
err=socket.Send(reinterpret_cast<char*>(&order),sizeof(order));
if( err == SOCKET_ERROR )
{
cerr<<"Error : loss : socket.Send : order"<<endl;
return 1;
}
err=socket.Send(reinterpret_cast<char*>(&value),sizeof(value));
if( err == SOCKET_ERROR )
{
if ( value )
cerr<<"Error : loss : socket.Send : yes"<<endl;
else
cerr<<"Error : loss : socket.Send : no"<<endl;
return 1;
}
socket.Close();
return 0;
}
int AskStatus()
{
cout<<"CTRL : IP : "<<IP_Ctrl.c_str()<<endl;
cout<<"CTRL : Port : "<<Port_Ctrl<<endl;
CSocketClientITCP socket;
socket.Init(IP_Ctrl.c_str(),Port_Ctrl);
if( ! socket.ConnectLoop() )
{
cerr<<"Error : status : socket.Connect error"<<endl;
return 1;
}
int err;
TOrder order=TORDER_STATUS;
err=socket.Send(reinterpret_cast<char*>(&order),sizeof(order));
if( err == SOCKET_ERROR )
{
cerr<<"Error : status : socket.Send : Order"<<endl;
return 1;
}
bool loss;
err=socket.Read(reinterpret_cast<char*>(&loss),sizeof(loss));
if( err == SOCKET_ERROR )
{
cerr<<"Error : status : socket.Read : Loss"<<endl;
return 1;
}
cout<<"SRV : PacketLoss : ";
if ( loss )
cout<<"Enable"<<endl;
else
cout<<"Disable"<<endl;
TScale scale;
err=socket.Read(reinterpret_cast<char*>(&scale),sizeof(scale));
if( err == SOCKET_ERROR )
{
cerr<<"Error : status : socket.Read : scale"<<endl;
return 1;
}
cout<<"SRV : Scale : "<<scale<<endl;
// VHOST
TPort port;
err=socket.Read(reinterpret_cast<char*>(&port),sizeof(port));
if( err == SOCKET_ERROR )
{
cerr<<"Error : status : socket.Read : Port VHOST"<<endl;
return 1;
}
cout<<"SRV VHOST : Port : "<<port<<endl;
// INET
err=socket.Read(reinterpret_cast<char*>(&port),sizeof(port));
if( err == SOCKET_ERROR )
{
cerr<<"Error : status : socket.Read : Port INET"<<endl;
return 1;
}
cout<<"SRV INET : Port : "<<port<<endl;
// SizeOfDisconnected
// becareful : the same List is shared by WifiServerVTCP and WifiServerITCP
TIndex size;
err=socket.Read(reinterpret_cast<char*>(&size),sizeof(size));
if( err == SOCKET_ERROR )
{
cerr<<"Error : status : socket.Read : Size INET"<<endl;
return 1;
}
cout<<"SRV : SizeOfDisconnected : "<<size<<endl;
// SPY
bool spyIsConnected;
err=socket.Read(reinterpret_cast<char*>(&spyIsConnected),sizeof(spyIsConnected));
if( err == SOCKET_ERROR )
{
cerr<<"Error : status : socket.Read : spyIsConnected"<<endl;
return 1;
}
cout<<"SPY : ";
if ( spyIsConnected )
cout<<"Connected"<<endl;
else
cout<<"Disconnected"<<endl;
socket.Close();
return 0;
}
int AskShow()
{
CSocketClientITCP socket;
socket.Init(IP_Ctrl.c_str(),Port_Ctrl);
if( ! socket.ConnectLoop() )
{
cerr<<"Error : show : socket.Connect error"<<endl;
return 1;
}
int err;
TOrder order=TORDER_SHOW;
err=socket.Send(reinterpret_cast<char*>(&order),sizeof(order));
if( err == SOCKET_ERROR )
{
cerr<<"Error : show : socket.Send : Order"<<endl;
return 1;
}
bool loss;
err=socket.Read(reinterpret_cast<char*>(&loss),sizeof(loss));
if( err == SOCKET_ERROR )
{
cerr<<"Error : show : socket.Read : Loss"<<endl;
return 1;
}
cout<<"PacketLoss : ";
if ( loss )
cout<<"Enable"<<endl;
else
cout<<"Disable"<<endl;
TScale scale;
err=socket.Read(reinterpret_cast<char*>(&scale),sizeof(scale));
if( err == SOCKET_ERROR )
{
cerr<<"Error : show : socket.Read : scale"<<endl;
return 1;
}
cout<<"Scale : "<<scale<<endl;
bool spyIsConnected;
err=socket.Read(reinterpret_cast<char*>(&spyIsConnected),sizeof(spyIsConnected));
if( err == SOCKET_ERROR )
{
cerr<<"Error : show : socket.Read : spyIsConnected"<<endl;
return 1;
}
cout<<"Spy : ";
if ( spyIsConnected )
cout<<"Connected"<<endl;
else
cout<<"Disconnected"<<endl;
socket.Close();
cout<<"----------------"<<endl;
return AskList();
}
int DistanceBetweenCID(int argc, char *argv[])
{
if( argc != 3 )
{
cerr<<"Error : distance : the number of parameter is uncorrect"<<endl;
Help();
return 1;
}
if( ! isPositiveInt(argv[1]) )
{
cerr<<"Error : distance : the CID 1 is not an integer"<<endl;
return 1;
}
TCID cid1=atoi(argv[1]);
if( cid1 < TCID_GUEST_MIN )
{
cerr<<"Error : distance : the CID 1 must be greater than or equal to "<<TCID_GUEST_MIN<<endl;
return 1;
}
if( ! isPositiveInt(argv[2]) )
{
cerr<<"Error : distance : the CID 2 is not an integer"<<endl;
return 1;
}
TCID cid2=atoi(argv[2]);
if( cid2 < TCID_GUEST_MIN )
{
cerr<<"Error : distance : the CID2 must be greater than or equal to "<<TCID_GUEST_MIN<<endl;
return 1;
}
CSocketClientITCP socket;
socket.Init(IP_Ctrl.c_str(),Port_Ctrl);
if( ! socket.ConnectLoop() )
{
cerr<<"Error : distance : socket.Connect error"<<endl;
return 1;
}
int err;
TOrder order=TORDER_DISTANCE_BETWEEN_CID;
err=socket.Send(reinterpret_cast<char*>(&order),sizeof(order));
if( err == SOCKET_ERROR )
{
cerr<<"Error : distance : socket.Send : order"<<endl;
return 1;
}
err=socket.Send(reinterpret_cast<char*>(&cid1),sizeof(cid1));
if( err == SOCKET_ERROR )
{
cerr<<"Error : distance : socket.Send : cid 1"<<endl;
return 1;
}
err=socket.Send(reinterpret_cast<char*>(&cid2),sizeof(cid2));
if( err == SOCKET_ERROR )
{
cerr<<"Error : distance : socket.Send : cid 2"<<endl;
return 1;
}
int codeError;
err=socket.Read(reinterpret_cast<char*>(&codeError),sizeof(codeError));
if( err == SOCKET_ERROR )
{
cerr<<"Error : distance : socket.Read : codeError"<<endl;
return 1;
}
if ( codeError == -1 )
{
cerr<<"Error : distance : unknown cid 1 : "<<cid1<<endl;
return 1;
}
if ( codeError == -2 )
{
cerr<<"Error : distance : unknown cid 2 : "<<cid2<<endl;
return 1;
}
TDistance distance;
err=socket.Read(reinterpret_cast<char*>(&distance),sizeof(distance));
if( err == SOCKET_ERROR )
{
cerr<<"Error : distance : socket.Read : distance"<<endl;
return 1;
}
cout<<distance<<endl;
socket.Close();
return 0;
}
int SetScale(int argc, char *argv[])
{
if( argc != 2)
{
cerr<<"Error : scale : the number of parameter is uncorrect"<<endl;
Help();
return 1;
}
if( ! isIntOrFloat(argv[1]) )
{
cerr<<"Error : scale : the format of the value is uncorrect"<<endl;
return 1;
}
TScale scale=atof(argv[1]);
if( scale <= 0 )
{
cerr<<"Error : scale : the value must be greater than 0"<<endl;
return 1;
}
CSocketClientITCP socket;
socket.Init(IP_Ctrl.c_str(),Port_Ctrl);
if( ! socket.ConnectLoop() )
{
cerr<<"Error : scale : socket.Connect error"<<endl;
return 1;
}
int err;
TOrder order=TORDER_SET_SCALE;
err=socket.Send(reinterpret_cast<char*>(&order),sizeof(order));
if( err == SOCKET_ERROR )
{
cerr<<"Error : scale : socket.Send : order"<<endl;
return 1;
}
err=socket.Send(reinterpret_cast<char*>(&scale),sizeof(scale));
if( err == SOCKET_ERROR )
{
cerr<<"Error : scale : socket.Send : scale"<<endl;
return 1;
}
socket.Close();
return 0;
}
int CloseAllClient()
{
CSocketClientITCP socket;
socket.Init(IP_Ctrl.c_str(),Port_Ctrl);
if( ! socket.ConnectLoop() )
{
cerr<<"Error : close : socket.Connect error"<<endl;
return 1;
}
int err;
TOrder order=TORDER_CLOSE_ALL_CLIENT;
err=socket.Send(reinterpret_cast<char*>(&order),sizeof(order));
if( err == SOCKET_ERROR )
{
cerr<<"Error : close : socket.Send : order"<<endl;
return 1;
}
socket.Close();
return 0;
}
int main(int argc , char *argv[])
{
char** param_cmd = new char*[argc];
int nbr_param_cmd=0;
NameOfProg=argv[0];
int arg_idx = 1;
while (arg_idx < argc)
{
if( ! strcmp("-v", argv[arg_idx]) || ! strcmp("--version", argv[arg_idx]) )
{
std::cout<<"Version : "<<VERSION<<std::endl;
return 0;
}
if( ! strcmp("-h", argv[arg_idx]) || ! strcmp("--help", argv[arg_idx]) )
{
Help();
return 1;
}
if( ( ! strcmp("-p", argv[arg_idx]) || ! strcmp("--port", argv[arg_idx]) ) && (arg_idx + 1) < argc && isPositiveInt(argv[arg_idx+1]) )
{
Port_Ctrl = std::stoi(argv[arg_idx+1]);
arg_idx++;
}
else if( ( ! strcmp("-i", argv[arg_idx]) || ! strcmp("--ip", argv[arg_idx]) ) && (arg_idx + 1) < argc)
{
IP_Ctrl = std::string(argv[arg_idx+1]);
arg_idx++;
}
else
{
param_cmd[nbr_param_cmd++]=argv[arg_idx];
}
arg_idx++;
}
if( nbr_param_cmd == 0 )
{
Help();
return 0;
}
if( ! strcasecmp(param_cmd[0],"ls") )
return AskList();
if( ! strcasecmp(param_cmd[0],"set") )
return ChangeCoordinate(nbr_param_cmd, param_cmd);
if( ! strcasecmp(param_cmd[0],"setname") )
return SetName(nbr_param_cmd, param_cmd);
if( ! strcasecmp(param_cmd[0],"loss") )
return ChangePacketLoss(nbr_param_cmd, param_cmd);
if( ! strcasecmp(param_cmd[0],"show") )
return AskShow();
if( ! strcasecmp(param_cmd[0],"status") )
return AskStatus();
if( ! strcasecmp(param_cmd[0],"distance") )
return DistanceBetweenCID(nbr_param_cmd, param_cmd);
if( ! strcasecmp(param_cmd[0],"scale") )
return SetScale(nbr_param_cmd, param_cmd);
if( ! strcasecmp(param_cmd[0],"close") )
return CloseAllClient();
cerr<<NameOfProg<<" : Error : unknown order : "<<param_cmd[0]<<endl;
return 1;
}
+54
View File
@@ -0,0 +1,54 @@
#include "cwirelessdevice.h"
#include "cmonwirelessdevice.h"
#include <iostream>
#include <unistd.h>
#include <signal.h>
MonitorWirelessDevice monitor ;
void signal_handler([[maybe_unused]] int signal_num)
{
std::cout << __func__ << std::endl ;
monitor.stop();
}
int main (){
/* Handle signals */
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
signal(SIGQUIT, signal_handler);
signal(SIGHUP, SIG_IGN);
/* struct ether_addr mac { 0xff, 0x00, 0x00,0x00, 0xfe, 0x00 };
struct ether_addr mac3 { 0xaa, 0xbb, 0x00,0x00, 0xfe, 0x00 };
WirelessDevice wdevice("wlan0",4,5,mac);
std::cout << wdevice << std::endl ;
WirelessDevice wdevice2 ;
wdevice2 = wdevice;
wdevice.setMacaddr(mac3);
std::cout << wdevice2 << std::endl ;
std::cout << wdevice << std::endl ;
*/
monitor.start();
pause();
std::cout << "end" << std::endl ;
return 0 ;
}
+309
View File
@@ -0,0 +1,309 @@
#include <iostream> // cout
#include <string.h> // strcmp
#include "config.h"
#include "tools.h" // isPositiveInt
#include "cwifiserveritcp.h"
#ifdef ENABLE_VHOST
#include "cwifiservervtcp.h"
#endif
#include "cctrlserver.h"
#include "cselect.h"
#include "cdynbuffer.h"
using namespace std;
CDynBuffer Buffer; // Buffer to stock received values
#ifdef ENABLE_VHOST
TPort Port_VHOST = DEFAULT_WIFI_CLIENT_PORT_VHOST;
#endif
TPort Port_TCP = DEFAULT_WIFI_CLIENT_PORT_INET;
TPort Port_Spy = DEFAULT_WIFI_SPY_PORT;
TPort Port_Ctrl = DEFAULT_CTRL_PORT;
CSelect Scheduler;
void RemoveClient(CWifiServer* srv, bool srvIsSpy, TIndex i, TDescriptor socket)
{
if( ! srvIsSpy )
{
cout<<"Client disconnected : "; srv->ShowInfoWifi(i) ; cout<<endl;
}
else
cout<<"Spy disconnected : "<< srv->GetReferenceOnInfoWifiByIndex(i)->GetCid() <<endl;
srv->CloseClient(i);
//del master socket to set
Scheduler.DelNode(socket);
}
void ForwardData(bool srcIsSpy, CWifiServer* src, CWifiServer* otherDst)
{
int valread;
TPower power;
for ( TIndex i = 0 ; i < src->GetNumberClient() ; )
{
TDescriptor socket = (*src)[i];
if( ! src->IsEnable(i) )
{
RemoveClient(src, srcIsSpy , i, socket);
continue;
}
if( Scheduler.DescriptorHasAction(socket) )
{
//Check if it was for closing , and also read the
//incoming message
valread=src->RecvSignal(socket,&power,&Buffer);
if( valread <=0 )
{
RemoveClient(src, srcIsSpy , i, socket);
continue;
}
if( ! srcIsSpy )
{
src->SendAllOtherClients(i,power,Buffer.GetBuffer(),valread);
otherDst->SendAllClientsWithoutLoss(power,Buffer.GetBuffer(),valread);
}
else
{
src->SendAllOtherClientsWithoutLoss(i,power,Buffer.GetBuffer(),valread);
otherDst->SendAllClientsWithoutLoss(power,Buffer.GetBuffer(),valread);
}
}
i++;
}
}
int vwifi_server()
{
TDescriptor socket;
CListInfo<CInfoSocket> infoSockets;
CListInfo<CInfoWifi> infoWifis;
CListInfo<CInfoWifi> infoWifisDeconnected;
#ifdef ENABLE_VHOST
CWifiServerVTCP wifiServerVTCP(&infoSockets,&infoWifis,&infoWifisDeconnected);
cout<<"CLIENT VHOST : ";
wifiServerVTCP.Init(Port_VHOST);
if( ! wifiServerVTCP.Listen(WIFI_MAX_DECONNECTED_CLIENT) )
{
cerr<<"Error : wifiServerVTCP.Listen"<<endl;
exit(EXIT_FAILURE);
}
#endif
CWifiServerITCP wifiServerITCP(&infoSockets,&infoWifis,&infoWifisDeconnected);
cout<<"CLIENT TCP : ";
wifiServerITCP.Init(Port_TCP);
if( ! wifiServerITCP.Listen(WIFI_MAX_DECONNECTED_CLIENT) )
{
cerr<<"Error : wifiServerITCP.Listen"<<endl;
exit(EXIT_FAILURE);
}
CWifiServer* wifiServer=&wifiServerITCP; // or wifiServerVTCP, if exist, it doesn't change anything
cout<<"SPY : ";
CWifiServerITCP wifiServerSPY;
wifiServerSPY.Init(Port_Spy);
if( ! wifiServerSPY.Listen(1) )
{
cerr<<"Error : wifiServerSPY.Listen"<<endl;
exit(EXIT_FAILURE);
}
cout<<"CTRL : ";
#ifdef ENABLE_VHOST
CCTRLServer ctrlServer(&wifiServerVTCP, &wifiServerITCP, &wifiServerSPY,&Scheduler);
#else
CCTRLServer ctrlServer(NULL, &wifiServerITCP, &wifiServerSPY,&Scheduler);
#endif
ctrlServer.Init(Port_Ctrl);
if( ! ctrlServer.Listen() )
{
cerr<<"Error : ctrlServer.Listen"<<endl;
exit(EXIT_FAILURE);
}
cout<<"Size of disconnected : "<<WIFI_MAX_DECONNECTED_CLIENT<<endl;
if( CanLostPackets )
cout<<"Packet loss : Enable"<<endl;
else
cout<<"Packet loss : disable"<<endl;
cout<<"Scale : "<<Scale<<endl;
//add master socket to set
#ifdef ENABLE_VHOST
Scheduler.AddNode(wifiServerVTCP);
#endif
Scheduler.AddNode(wifiServerITCP);
Scheduler.AddNode(wifiServerSPY);
Scheduler.AddNode(ctrlServer);
while( true )
{
//wait for an activity on one of the sockets , timeout is NULL ,
//so wait indefinitely
if( Scheduler.Wait() == SCHEDULER_ERROR )
{
cerr<<"Error : scheduler.Wait"<<endl;
return 1;
}
else {
//If something happened on the master socket ,
//then its an incoming connection
#ifdef ENABLE_VHOST
if( Scheduler.DescriptorHasAction(wifiServerVTCP) )
{
socket = wifiServerVTCP.Accept();
if ( socket == SOCKET_ERROR )
{
cerr<<"Error : wifiServerVTCP.Accept"<<endl;
exit(EXIT_FAILURE);
}
//add child sockets to set
Scheduler.AddNode(socket);
//inform user of socket number - used in send and receive commands
cout<<"New connection from Client VHost : "; wifiServer->ShowInfoWifi(wifiServer->GetNumberClient()-1) ; cout<<endl;
}
#endif
if( Scheduler.DescriptorHasAction(wifiServerITCP) )
{
socket = wifiServerITCP.Accept();
if ( socket == SOCKET_ERROR )
{
cerr<<"Error : wifiServerITCP.Accept"<<endl;
exit(EXIT_FAILURE);
}
//add child sockets to set
Scheduler.AddNode(socket);
//inform user of socket number - used in send and receive commands
cout<<"New connection from Client TCP : "; wifiServer->ShowInfoWifi(wifiServer->GetNumberClient()-1) ; cout<<endl;
}
if( Scheduler.DescriptorHasAction(wifiServerSPY) )
{
socket = wifiServerSPY.Accept();
if ( socket == SOCKET_ERROR )
{
cerr<<"Error : wifiSpyServer.Accept"<<endl;
exit(EXIT_FAILURE);
}
//add child sockets to set
Scheduler.AddNode(socket);
//inform user of socket number - used in send and receive commands
cout<<"New connection from Spy : "<<wifiServerSPY.GetReferenceOnInfoWifiByIndex(wifiServerSPY.GetNumberClient()-1)->GetCid()<<endl;
}
if( Scheduler.DescriptorHasAction(ctrlServer) )
{
ctrlServer.ReceiveOrder();
}
//else its some IO operation on some other socket
ForwardData(false, wifiServer, &wifiServerSPY);
ForwardData(true, &wifiServerSPY, wifiServer);
}
}
return 0;
}
void help()
{
#ifdef ENABLE_VHOST
cout<<"Usage: vwifi-server [-h] [-v] [-l] [-u] [-p PORT_VHOST] [-t PORT_TCP] [-s PORT_SPY] [-c PORT_CTRL]"<<endl;
cout<<" [--help] [--version] [--lost-packets] [--use-port-in-hash] [--port-vhost PORT_VHOST] [--port-tcp PORT_TCP] [--port-spy PORT_SPY] [--port-ctrl PORT_CTRL]"<<endl;
cout<<" By default : PORT_VHOST="<< DEFAULT_WIFI_CLIENT_PORT_VHOST <<
" PORT_TCP=" << DEFAULT_WIFI_CLIENT_PORT_INET <<
" PORT_SPY=" << DEFAULT_WIFI_SPY_PORT <<
" PORT_CTRL=" << DEFAULT_CTRL_PORT <<endl;
#else
cout<<"Usage: vwifi-server [-h] [-v] [-l] [-u] [-t PORT_TCP] [-s PORT_SPY] [-c PORT_CTRL]"<<endl;
cout<<" [--help] [--version] [--lost-packets] [--use-port-in-hash] [--port-tcp PORT_TCP] [--port-spy PORT_SPY] [--port-ctrl PORT_CTRL]"<<endl;
cout<<" By default : PORT_TCP=" << DEFAULT_WIFI_CLIENT_PORT_INET <<
" PORT_SPY=" << DEFAULT_WIFI_SPY_PORT <<
" PORT_CTRL=" << DEFAULT_CTRL_PORT <<endl;
#endif
}
int main(int argc, char** argv)
{
int arg_idx = 1;
while (arg_idx < argc)
{
if( ! strcmp("-v", argv[arg_idx]) || ! strcmp("--version", argv[arg_idx]) )
{
cout<<"Version : "<<VERSION<<endl;
return 0;
}
if( ! strcmp("-h", argv[arg_idx]) || ! strcmp("--help", argv[arg_idx]) )
{
help();
return 0;
}
if( ! strcmp("-l", argv[arg_idx]) || ! strcmp("--lost-packets", argv[arg_idx]) )
{
CanLostPackets=true;
}
else if( ! strcmp("-u", argv[arg_idx]) || ! strcmp("--use-port-in-hash", argv[arg_idx]) )
{
HashUsesPort=true;
}
#ifdef ENABLE_VHOST
else if( ( ! strcmp("-p", argv[arg_idx]) || ! strcmp("--port-vhost", argv[arg_idx]) ) && (arg_idx + 1) < argc && isPositiveInt(argv[arg_idx+1]) )
{
Port_VHOST = stoi(argv[arg_idx+1]);
arg_idx++;
}
#endif
else if( ( ! strcmp("-t", argv[arg_idx]) || ! strcmp("--port-tcp", argv[arg_idx]) ) && (arg_idx + 1) < argc && isPositiveInt(argv[arg_idx+1]) )
{
Port_TCP = stoi(argv[arg_idx+1]);
arg_idx++;
}
else if( ( ! strcmp("-s", argv[arg_idx]) || ! strcmp("--port-spy", argv[arg_idx]) ) && (arg_idx + 1) < argc && isPositiveInt(argv[arg_idx+1]) )
{
Port_Spy = stoi(argv[arg_idx+1]);
arg_idx++;
}
else if( ( ! strcmp("-c", argv[arg_idx]) || ! strcmp("--port-ctrl", argv[arg_idx]) ) && (arg_idx + 1) < argc && isPositiveInt(argv[arg_idx+1]) )
{
Port_Ctrl = stoi(argv[arg_idx+1]);
arg_idx++;
}
else
{
cerr<<"Error : problem with this parameter : "<< argv[arg_idx] <<endl;
help();
return 1;
}
arg_idx++;
}
return vwifi_server();
}