3.10.2013 - PIPeer release, PIConsole now can work as server and remote client. Remote console test program in directory "remote_console"

This commit is contained in:
peri4
2013-10-03 16:04:02 +04:00
parent 9111640ca8
commit 4b90f2818e
56 changed files with 6422 additions and 673 deletions

View File

@@ -83,7 +83,7 @@ bool PIEthernet::init() {
closeSocket(sock);
int st = 0, pr = 0;;
#ifdef WINDOWS
int flags = 0;
int flags = WSA_FLAG_OVERLAPPED;
#else
int so = 1;
#endif
@@ -96,18 +96,21 @@ bool PIEthernet::init() {
}
#ifdef WINDOWS
if (type_ == UDP) flags = WSA_FLAG_MULTIPOINT_C_LEAF | WSA_FLAG_MULTIPOINT_D_LEAF;
if (params[ReuseAddress]) flags |= WSA_FLAG_OVERLAPPED;
sock = WSASocket(AF_INET, st, pr, NULL, 0, flags);
#else
sock = socket(AF_INET, st, pr);
#endif
if (sock == -1) {
piCout << "[PIEthernet] Cant`t create socket, " << ethErrorString();
piCoutObj << "[PIEthernet] Can`t create socket, " << ethErrorString();
return false;
}
#ifndef WINDOWS
if (params[PIEthernet::ReuseAddress]) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &so, sizeof(so));
if (params[PIEthernet::Broadcast]) setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &so, sizeof(so));
#else
BOOL bv = TRUE;
if (params[PIEthernet::ReuseAddress]) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char * )&bv, sizeof(bv));
setsockopt(sock, SOL_SOCKET, SO_DONTLINGER, (const char * )&bv, sizeof(bv));
#endif
//cout << "inited " << sock << ": bc = " << params << endl;
//fcntl(sock, F_SETFL, 0/*O_NONBLOCK*/);
@@ -128,7 +131,7 @@ bool PIEthernet::openDevice() {
parseAddress(path_, &ip_, &port_);
if (type_ != UDP)
return true;
//cout << " bind to " << sock << ": " << (params[PIEthernet::Broadcast] ? "0.0.0.0" : path_) << ": " << port_ << " ..." <<endl;
//piCout << "bind to" << (params[PIEthernet::Broadcast] ? "bc" : ip_) << ":" << port_ << " ...";
memset(&addr_, 0, sizeof(addr_));
addr_.sin_family = AF_INET;
addr_.sin_port = htons(port_);
@@ -143,7 +146,7 @@ bool PIEthernet::openDevice() {
tries++;
}
if (tries == 10) {
piCout << "[PIEthernet] Cant`t bind to " << ip_ << ":" << port_ << ", " << ethErrorString();
piCoutObj << "[PIEthernet] Can`t bind to " << ip_ << ":" << port_ << ", " << ethErrorString();
return false;
}
opened_ = true;
@@ -156,7 +159,6 @@ bool PIEthernet::openDevice() {
bool PIEthernet::closeDevice() {
//cout << "close\n";
if (sock != -1) shutdown(sock, SHUT_RDWR);
closeSocket(sock);
piForeach (PIEthernet * i, clients_)
delete i;
@@ -172,7 +174,7 @@ bool PIEthernet::joinMulticastGroup(const PIString & group) {
if (sock == -1) init();
if (sock == -1) return false;
if (type_ != UDP) {
piCout << "[PIEthernet] Only UDP sockets can join multicast groups";
piCoutObj << "[PIEthernet] Only UDP sockets can join multicast groups";
return false;
}
if (!opened_) {
@@ -185,27 +187,36 @@ bool PIEthernet::joinMulticastGroup(const PIString & group) {
parseAddress(path_, &ip_, &port_);
memset(&addr_, 0, sizeof(addr_));
addr_.sin_family = AF_INET;
addr_.sin_port = htons(port_);
addr_.sin_addr.s_addr = inet_addr(group.data());
//int so = 1;
//setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, (char * )&so, sizeof(so));
SOCKET ret = WSAJoinLeaf(sock, (sockaddr *)&addr_, sizeof(addr_), NULL, NULL, NULL, NULL, JL_BOTH);
if (ret == INVALID_SOCKET) {
piCout << "[PIEthernet] Cant`t join multicast group " << group << ", " << ethErrorString();
piCoutObj << "[PIEthernet] Can`t join multicast group " << group << ", " << ethErrorString();
return false;
}
leafs.insert(group, ret);
#else
# ifndef QNX
if (!params[Broadcast])
piCout << "[PIEthernet] Warning: \"Broadcast\" parameter not set, \"joinMulticastGroup(\"" << group << "\")\" may be useless!";
piCoutObj << "[PIEthernet] Warning: \"Broadcast\" parameter not set, \"joinMulticastGroup(\"" << group << "\")\" may be useless!";
parseAddress(path_, &ip_, &port_);
struct ip_mreqn mreq;
memset(&mreq, 0, sizeof(mreq));
/*if (params[PIEthernet::Broadcast]) mreq.imr_address.s_addr = INADDR_ANY;
else*/ mreq.imr_address.s_addr = inet_addr(ip_.data());
mreq.imr_multiaddr.s_addr = inet_addr(group.data());
mreq.imr_ifindex = 0;
if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1) {
piCout << "[PIEthernet] Cant`t join multicast group " << group << ", " << ethErrorString();
if (params[PIEthernet::Broadcast]) mreq.imr_address.s_addr = INADDR_ANY;
else mreq.imr_address.s_addr = inet_addr(ip_.data());
PIEthernet::InterfaceList il = interfaces();
const PIEthernet::Interface * ci = il.getByAddress(ip_);
if (ci != 0) mreq.imr_ifindex = ci->index;
//piCout << "join group" << group << "ip" << ip_ << "with index" << mreq.imr_ifindex;
mreq.imr_multiaddr.s_addr = inet_addr(group.data());
int so = 1;
//setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &so, sizeof(so));
setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, &so, sizeof(so));
setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, &mreq, sizeof(mreq));
if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) != 0) {
piCoutObj << "[PIEthernet] Can`t join multicast group " << group << ", " << ethErrorString();
return false;
}
# endif
@@ -218,7 +229,7 @@ bool PIEthernet::leaveMulticastGroup(const PIString & group) {
if (sock == -1) init();
if (sock == -1) return false;
if (type_ != UDP) {
piCout << "[PIEthernet] Only UDP sockets can leave multicast groups";
piCoutObj << "[PIEthernet] Only UDP sockets can leave multicast groups";
return false;
}
#ifdef WINDOWS
@@ -237,7 +248,7 @@ bool PIEthernet::leaveMulticastGroup(const PIString & group) {
mreq.imr_multiaddr.s_addr = inet_addr(group.data());
mreq.imr_ifindex = 0;
if (setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) == -1) {
piCout << "[PIEthernet] Cant`t leave multicast group " << group << ", " << ethErrorString();
piCoutObj << "[PIEthernet] Can`t leave multicast group " << group << ", " << ethErrorString();
return false;
}
#endif
@@ -256,10 +267,10 @@ bool PIEthernet::connect() {
#ifdef QNX
addr_.sin_len = sizeof(addr_);
#endif
//piCout << "[PIEthernet] connect to " << ip << ":" << port_;
//piCoutObj << "[PIEthernet] connect to " << ip << ":" << port_;
connected_ = (::connect(sock, (sockaddr * )&addr_, sizeof(addr_)) == 0);
if (!connected_)
piCout << "[PIEthernet] Cant`t connect to " << ip_ << ":" << port_ << ", " << ethErrorString();
piCoutObj << "[PIEthernet] Can`t connect to " << ip_ << ":" << port_ << ", " << ethErrorString();
opened_ = connected_;
if (connected_) connected();
return connected_;
@@ -283,14 +294,14 @@ bool PIEthernet::listen() {
tries++;
}
if (tries == 10) {
piCout << "[PIEthernet] Cant`t bind to " << ip_ << ":" << port_ << ", " << ethErrorString();
piCoutObj << "[PIEthernet] Can`t bind to " << ip_ << ":" << port_ << ", " << ethErrorString();
return false;
}
if (::listen(sock, 64) == -1) {
piCout << "[PIEthernet] Can`t listen on "<< ip_ << ":" << port_ << ", " << ethErrorString();
piCoutObj << "[PIEthernet] Can`t listen on "<< ip_ << ":" << port_ << ", " << ethErrorString();
return false;
}
//piCout << "[PIEthernet] listen on " << ip_ << ":" << port_;
//piCoutObj << "[PIEthernet] listen on " << ip_ << ":" << port_;
server_thread_.start(server_func);
return true;
}
@@ -303,13 +314,14 @@ int PIEthernet::read(void * read_to, int max_size) {
int rs = 0, s = 0;
sockaddr_in client_addr;
socklen_t slen = sizeof(client_addr);
//piCout << "[PIEthernet] read from " << ip_ << ":" << port_ << endl;
//piCoutObj << "[PIEthernet] read from " << ip_ << ":" << port_ << endl;
switch (type_) {
case TCP_SingleTCP:
::listen(sock, 64);
s = accept(sock, (sockaddr * )&client_addr, &slen);
if (s == -1) {
piCout << "[PIEthernet] Cant`t accept new connection, " << ethErrorString();
//piCoutObj << "[PIEthernet] Can`t accept new connection, " << ethErrorString();
msleep(1);
return -1;
}
rs = recv(s, (char * )read_to, max_size, 0);
@@ -323,11 +335,11 @@ int PIEthernet::read(void * read_to, int max_size) {
#else
rs = recv(sock, read_to, max_size, 0);
#endif
piCout << "eth" << path_ << "read return" << rs << errno;
if (rs <= 0) {
//piCout << "eth" << path_ << "read return" << rs << errno;
if (rs <= 0 && type_ == TCP_Client) {
connected_ = false;
disconnected(rs < 0);
piCout << "eth" << path_ << "disconnected";
//piCoutObj << "eth" << path_ << "disconnected";
}
if (rs > 0) received(read_to, rs);
return rs;
@@ -342,10 +354,10 @@ int PIEthernet::read(void * read_to, int max_size) {
int PIEthernet::write(const void * data, int max_size) {
if (sock == -1) init();
if (sock == -1 || !isWriteable()) {
//piCout << "[PIEthernet] Can`t send to uninitialized socket";
//piCoutObj << "[PIEthernet] Can`t send to uninitialized socket";
return -1;
}
//piCout << "[PIEthernet] sending to " << ip_s << ":" << port_s << " " << max_size << " bytes";
//piCoutObj << "[PIEthernet] sending to " << ip_s << ":" << port_s << " " << max_size << " bytes";
int ret = 0;
switch (type_) {
case TCP_SingleTCP:
@@ -356,21 +368,22 @@ int PIEthernet::write(const void * data, int max_size) {
#ifdef QNX
addr_.sin_len = sizeof(addr_);
#endif
//piCout << "connect SingleTCP" << ip_s << ":" << port_s << "...";
//piCoutObj << "connect SingleTCP" << ip_s << ":" << port_s << "...";
if (::connect(sock, (sockaddr * )&addr_, sizeof(addr_)) != 0) {
piCout << "[PIEthernet] Cant`t connect to " << ip_s << ":" << port_s << ", " << ethErrorString();
//piCoutObj << "[PIEthernet] Can`t connect to " << ip_s << ":" << port_s << ", " << ethErrorString();
msleep(1);
return -1;
}
//piCout << "ok, write SingleTCP" << int(data) << max_size << "bytes ...";
//piCoutObj << "ok, write SingleTCP" << int(data) << max_size << "bytes ...";
ret = ::send(sock, (const char *)data, max_size, 0);
//piCout << "ok, ret" << ret;
//piCoutObj << "ok, ret" << ret;
closeSocket(sock);
init();
return ret;
case UDP:
saddr_.sin_port = htons(port_s);
if (params[PIEthernet::Broadcast]) saddr_.sin_addr.s_addr = INADDR_BROADCAST;
else saddr_.sin_addr.s_addr = inet_addr(ip_s.data());
/*if (params[PIEthernet::Broadcast]) saddr_.sin_addr.s_addr = INADDR_BROADCAST;
else*/ saddr_.sin_addr.s_addr = inet_addr(ip_s.data());
saddr_.sin_family = AF_INET;
#ifdef WINDOWS
return sendto(sock, (const char * )data, max_size, 0, (sockaddr * )&saddr_, sizeof(saddr_));
@@ -391,7 +404,7 @@ void PIEthernet::server_func(void * eth) {
socklen_t slen = sizeof(client_addr);
int s = accept(ce->sock, (sockaddr * )&client_addr, &slen);
if (s == -1) {
piCout << "[PIEthernet] Cant`t accept new connection, " << ethErrorString();
if (ce->debug_) piCout << "[PIEthernet] Can`t accept new connection, " << ethErrorString();
return;
}
PIString ip(inet_ntoa(client_addr.sin_addr));
@@ -406,19 +419,60 @@ void PIEthernet::server_func(void * eth) {
}
PIStringList PIEthernet::interfaces() {
PIEthernet::InterfaceList PIEthernet::interfaces() {
#ifdef WINDOWS
piCout << "[PIEthernet] Not implemented on Windows, use \"PIEthernet::allAddresses\" instead";
return PIStringList();
#else
# ifdef QNX
PIStringList il, sl;
/*struct if_nameindex * ni = if_nameindex();
for (int i = 0; ; ++i) {
if (ni[i].if_name == 0 || ni[i].if_index == 0) break;
sl << PIString(ni[i].if_name);
PIEthernet::InterfaceList il;
Interface ci;
PIP_ADAPTER_INFO pAdapterInfo, pAdapter = 0;
int ret = 0;
ulong ulOutBufLen = sizeof(IP_ADAPTER_INFO);
pAdapterInfo = (IP_ADAPTER_INFO * ) HeapAlloc(GetProcessHeap(), 0, (sizeof (IP_ADAPTER_INFO)));
if (pAdapterInfo == 0) {
piCout << "[PIEthernet] Error allocating memory needed to call GetAdaptersinfo";
return il;
}
if_freenameindex(ni);*/
if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) {
HeapFree(GetProcessHeap(), 0, (pAdapterInfo));
pAdapterInfo = (IP_ADAPTER_INFO *) HeapAlloc(GetProcessHeap(), 0, (ulOutBufLen));
if (pAdapterInfo == 0) {
piCout << "[PIEthernet] Error allocating memory needed to call GetAdaptersinfo";
return il;
}
}
if ((ret = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) {
pAdapter = pAdapterInfo;
while (pAdapter) {
ci.name = PIString(pAdapter->AdapterName);
ci.index = pAdapter->Index;
ci.address = PIString(pAdapter->IpAddressList.IpAddress.String);
if (ci.address == "0.0.0.0") {
pAdapter = pAdapter->Next;
continue;
}
ci.mac = macFromBytes(PIByteArray(pAdapter->Address, pAdapter->AddressLength));
ci.netmask = PIString(pAdapter->IpAddressList.IpMask.String);
ci.flags = PIEthernet::ifActive | PIEthernet::ifRunning;
//if (ret->ifa_flags & IFF_BROADCAST) ci.flags |= PIEthernet::ifBroadcast;
//if (ret->ifa_flags & IFF_MULTICAST) ci.flags |= PIEthernet::ifMulticast;
if (pAdapter->Type == MIB_IF_TYPE_PPP) ci.flags |= PIEthernet::ifPTP;
if (pAdapter->Type == MIB_IF_TYPE_LOOPBACK) ci.flags |= PIEthernet::ifLoopback;
ci.broadcast.clear();
ci.ptp.clear();
/*if (ci.flags[PIEthernet::ifBroadcast])
ci.broadcast = getSockAddr(ret->ifa_broadaddr);
if (ci.flags[PIEthernet::ifPTP])
ci.ptp = getSockAddr(ret->ifa_dstaddr);*/
il << ci;
pAdapter = pAdapter->Next;
}
} else
piCout << "[PIEthernet] GetAdaptersInfo failed with error: " << ret;
if (pAdapterInfo)
HeapFree(GetProcessHeap(), 0, (pAdapterInfo));
return il;
#else
/*# ifdef QNX
PIStringList il, sl;
PIProcess proc;
proc.setGrabOutput(true);
proc.exec(ifconfigPath.c_str(), "-l");
@@ -436,38 +490,70 @@ PIStringList PIEthernet::interfaces() {
for (int j = 0; j < al; ++j)
sl << i.trimmed() + ":" + PIString::fromNumber(j);
}
//cout << out;
//cout << sl << endl;
return sl;
# else
PIStringList sl;
/*struct if_nameindex * ni = if_nameindex();
for (int i = 0; ; ++i) {
if (ni[i].if_name == 0 || ni[i].if_index == 0) break;
sl << PIString(ni[i].if_name);
}
if_freenameindex(ni);*/
PIProcess proc;
proc.setGrabOutput(true);
proc.exec(ifconfigPath.c_str(), "-s");
if (!proc.waitForFinish(1000)) return sl;
PIString out(proc.readOutput());
//cout << out << endl;
out.cutLeft(out.find('\n') + 1);
while (!out.isEmpty()) {
sl << out.left(out.find(' '));
out.cutLeft(out.find('\n') + 1);
}
//cout << sl << endl;
return sl;
# endif
# endif*/
PIEthernet::InterfaceList il;
Interface ci;
struct ifaddrs * ret;
int s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (getifaddrs(&ret) == 0) {
while (ret != 0) {
if (ret->ifa_addr->sa_family != AF_INET) {
ret = ret->ifa_next;
continue;
}
ci.name = PIString(ret->ifa_name);
ci.address = getSockAddr(ret->ifa_addr);
ci.netmask = getSockAddr(ret->ifa_netmask);
ci.mac.clear();
if (s != -1) {
struct ifreq ir;
strcpy(ir.ifr_name, ret->ifa_name);
if (ioctl(s, SIOCGIFHWADDR, &ir) == 0)
ci.mac = macFromBytes(PIByteArray(ir.ifr_hwaddr.sa_data, 6));
}
ci.flags = 0;
if (ret->ifa_flags & IFF_UP) ci.flags |= PIEthernet::ifActive;
if (ret->ifa_flags & IFF_RUNNING) ci.flags |= PIEthernet::ifRunning;
if (ret->ifa_flags & IFF_BROADCAST) ci.flags |= PIEthernet::ifBroadcast;
if (ret->ifa_flags & IFF_MULTICAST) ci.flags |= PIEthernet::ifMulticast;
if (ret->ifa_flags & IFF_LOOPBACK) ci.flags |= PIEthernet::ifLoopback;
if (ret->ifa_flags & IFF_POINTOPOINT) ci.flags |= PIEthernet::ifPTP;
ci.broadcast.clear();
ci.ptp.clear();
if (ci.flags[PIEthernet::ifBroadcast])
ci.broadcast = getSockAddr(ret->ifa_broadaddr);
if (ci.flags[PIEthernet::ifPTP])
ci.ptp = getSockAddr(ret->ifa_dstaddr);
ci.index = if_nametoindex(ret->ifa_name);
il << ci;
ret = ret->ifa_next;
}
freeifaddrs(ret);
} else
piCout << "[PIEthernet] Can`t get interfaces:" << errorString();
if (s != -1) ::close(s);
return il;
#endif
}
PIString PIEthernet::interfaceAddress(const PIString & interface_) {
#ifdef WINDOWS
piCout << "[PIEthernet] Not implemented on Windows, use \"PIEthernet::allAddresses\" instead";
piCout << "[PIEthernet] Not implemented on Windows, use \"PIEthernet::allAddresses\" or \"PIEthernet::interfaces\" instead";
return PIString();
#else
struct ifreq ifr;
@@ -484,7 +570,7 @@ PIString PIEthernet::interfaceAddress(const PIString & interface_) {
PIStringList PIEthernet::allAddresses() {
#ifdef WINDOWS
/*#ifdef WINDOWS
PIStringList al;
PIString ca;
PIP_ADAPTER_INFO pAdapterInfo, pAdapter = 0;
@@ -506,10 +592,6 @@ PIStringList PIEthernet::allAddresses() {
if ((ret = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) {
pAdapter = pAdapterInfo;
while (pAdapter) {
/*if (pAdapter->Type != MIB_IF_TYPE_ETHERNET && pAdapter->Type != MIB_IF_TYPE_LOOPBACK) {
pAdapter = pAdapter->Next;
continue;
}*/
ca = PIString(pAdapter->IpAddressList.IpAddress.String);
if (ca != "0.0.0.0") al << ca;
pAdapter = pAdapter->Next;
@@ -519,10 +601,11 @@ PIStringList PIEthernet::allAddresses() {
if (pAdapterInfo)
HeapFree(GetProcessHeap(), 0, (pAdapterInfo));
return al;
#else
PIStringList il = interfaces(), al;
piForeachC (PIString & i, il)
al << interfaceAddress(i);
#else*/
PIEthernet::InterfaceList il = interfaces();
PIStringList al;
piForeachC (PIEthernet::Interface & i, il)
al << i.address;
return al.removeStrings("0.0.0.0");
#endif
//#endif
}