git-svn-id: svn://db.shs.com.ru/pip@542 12ceb7fc-bf1f-11e4-8940-5bc7170c53b5

This commit is contained in:
2017-09-05 15:20:33 +00:00
parent b67512d38c
commit 6f54f501cd
7 changed files with 324 additions and 131 deletions

View File

@@ -1,16 +1,61 @@
#include "pip.h"
#include "pivector2d.h"
#include "pistring.h"
#ifdef QNX
# include <net/if.h>
# include <net/if_dl.h>
# include <hw/nicinfo.h>
# include <netdb.h>
# include <sys/socket.h>
# include <sys/time.h>
# include <sys/types.h>
# include <sys/ioctl.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <ifaddrs.h>
# include <fcntl.h>
# ifdef BLACKBERRY
# include <netinet/in.h>
# else
# include <sys/dcmd_io-net.h>
# endif
# define ip_mreqn ip_mreq
# define imr_address imr_interface
#else
# ifdef WINDOWS
# include <io.h>
# include <winsock2.h>
# include <iphlpapi.h>
# include <psapi.h>
# include <ws2tcpip.h>
# define ip_mreqn ip_mreq
# define imr_address imr_interface
# else
# include <fcntl.h>
# include <sys/ioctl.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <sys/socket.h>
# include <net/if.h>
# include <netdb.h>
# ifndef ANDROID
# include <ifaddrs.h>
# endif
# endif
#endif
#include <errno.h>
int main(int argc, char *argv[]) {
PIString s = PIString::fromUTF8("hello, привет");
/*PIString s = PIString::fromUTF8("hello, привет");
piCout << s;
PIByteArray ba = s.toUTF8();
piCout << ba.toHex();
PIString s2;
s2 = PIString::fromUTF8(ba);
piCout << s2;
piCout << s2;*/
PIEthernet::Address a("127.1", -1);
piCout << a << PICoutManipulators::Hex << a.ip();
return 0;
}

View File

@@ -92,6 +92,114 @@ PIString getSockAddr(sockaddr * s) {
#endif
PIEthernet::Address::Address(uint _ip, ushort _port) {
set(_ip, _port);
}
PIEthernet::Address::Address(const PIString & ip_port) {
set(ip_port);
}
PIEthernet::Address::Address(const PIString & _ip, ushort _port) {
set(_ip, _port);
}
PIString PIEthernet::Address::ipString() const {
PIString ret = PIString::fromNumber(ip_b[0]);
ret << "." << PIString::fromNumber(ip_b[1]);
ret << "." << PIString::fromNumber(ip_b[2]);
ret << "." << PIString::fromNumber(ip_b[3]);
return ret;
}
PIString PIEthernet::Address::toString() const {
return ipString() + ":" + PIString::fromNumber(port_);
}
void PIEthernet::Address::setIP(uint _ip) {
ip_ = _ip;
}
void PIEthernet::Address::setIP(const PIString & _ip) {
initIP(_ip);
}
void PIEthernet::Address::setPort(ushort _port) {
port_ = _port;
}
void PIEthernet::Address::set(const PIString & ip_port) {
PIString _ip; int p(0);
splitIPPort(ip_port, &_ip, &p);
port_ = p;
initIP(_ip);
}
void PIEthernet::Address::set(const PIString & _ip, ushort _port) {
initIP(_ip);
port_ = _port;
}
void PIEthernet::Address::set(uint _ip, ushort _port) {
ip_ = _ip;
port_ = _port;
}
void PIEthernet::Address::clear() {
ip_ = 0;
port_ = 0;
}
PIString PIEthernet::Address::resolve(const PIString & host) {
PIString ip(host), port;
int i = host.find(':');
if (i >= 0) {
ip = host.left(i);
port = host.right(host.length() - i - 1);
}
PIString ret = PIStringAscii("0.0.0.0");
if (!port.isEmpty()) ret += PIStringAscii(":") + port;
//#ifdef WINDOWS
hostent * he = gethostbyname(ip.dataAscii());
if (!he)
return ret;
struct in_addr addr;
if (he->h_addr_list[0]) {
addr.s_addr = *((uint*)(he->h_addr_list[0]));
ret = inet_ntoa(addr);
if (!port.isEmpty()) ret += PIStringAscii(":") + port;
}
//#else
//#endif
return ret;
}
void PIEthernet::Address::splitIPPort(const PIString & ipp, PIString * _ip, int * _port) {
//piCout << "parse" << ipp;
int sp = ipp.find(":");
if (_ip != 0) *_ip = (sp >= 0 ? ipp.left(sp) : ipp);
if (_port != 0 && sp >= 0) *_port = ipp.right(ipp.length() - ipp.find(":") - 1).toInt();
}
void PIEthernet::Address::initIP(const PIString & _ip) {
ip_ = inet_addr(_ip.dataAscii());
}
REGISTER_DEVICE(PIEthernet)
@@ -112,7 +220,7 @@ PIEthernet::PIEthernet(): PIIODevice("", ReadWrite) {
PIEthernet::PIEthernet(PIEthernet::Type type_, const PIString & ip_port, const PIFlags<PIEthernet::Parameters> params_): PIIODevice(ip_port, ReadWrite) {
construct();
parseAddress(ip_port, &ip_, &port_);
addr_r.set(ip_port);
setType(type_);
setParameters(params_);
if (type_ != UDP) init();
@@ -121,7 +229,7 @@ PIEthernet::PIEthernet(PIEthernet::Type type_, const PIString & ip_port, const P
PIEthernet::PIEthernet(int sock_, PIString ip_port): PIIODevice("", ReadWrite) {
construct();
parseAddress(ip_port, &ip_s, &port_s);
addr_s.set(ip_port);
sock = sock_;
opened_ = connected_ = true;
init();
@@ -146,7 +254,6 @@ void PIEthernet::construct() {
setOption(BlockingWrite);
piMonitor.ethernets++;
connected_ = connecting_ = listen_threaded = server_bounded = false;
port_ = port_s = port_r = 0;
sock = sock_s = -1;
setReadTimeout(10000.);
setWriteTimeout(10000.);
@@ -197,13 +304,6 @@ bool PIEthernet::init() {
}
void PIEthernet::parseAddress(const PIString & ipp, PIString * ip, int * port) {
//piCout << "parse" << ipp;
if (ip != 0) *ip = ipp.left(ipp.find(":"));
if (port != 0) *port = ipp.right(ipp.length() - ipp.find(":") - 1).toInt();
}
PIString PIEthernet::macFromBytes(const PIByteArray & mac) {
PIString r;
for (int i = 0; i < mac.size_s(); ++i) {
@@ -230,6 +330,13 @@ PIString PIEthernet::applyMask(const PIString & ip, const PIString & mask) {
}
PIEthernet::Address PIEthernet::applyMask(const PIEthernet::Address & ip, const PIEthernet::Address & mask) {
Address ret(ip);
ret.ip_ &= mask.ip_;
return ret;
}
PIString PIEthernet::getBroadcast(const PIString & ip, const PIString & mask) {
struct in_addr ia;
ia.s_addr = inet_addr(ip.dataAscii()) | ~inet_addr(mask.dataAscii());
@@ -237,21 +344,29 @@ PIString PIEthernet::getBroadcast(const PIString & ip, const PIString & mask) {
}
PIEthernet::Address PIEthernet::getBroadcast(const PIEthernet::Address & ip, const PIEthernet::Address & mask) {
Address ret(ip);
ret.ip_ |= ~mask.ip_;
return ret;
}
bool PIEthernet::openDevice() {
if (connected_) return true;
init();
if (sock == -1 || path().isEmpty()) return false;
parseAddress(path(), &ip_, &port_);
addr_r.set(path());
//Address::splitIPPort(path(), &ip_, &port_);
if (type() == TCP_Client)
connecting_ = true;
if (type() != UDP || mode() == PIIODevice::WriteOnly)
return true;
memset(&PRIVATE->addr_, 0, sizeof(PRIVATE->addr_));
PRIVATE->addr_.sin_family = AF_INET;
PRIVATE->addr_.sin_port = htons(port_);
PRIVATE->addr_.sin_port = htons(addr_r.port());
PIFlags<Parameters> params = parameters();
if (params[PIEthernet::Broadcast]) PRIVATE->addr_.sin_addr.s_addr = INADDR_ANY;
else PRIVATE->addr_.sin_addr.s_addr = inet_addr(ip_.dataAscii());
else PRIVATE->addr_.sin_addr.s_addr = addr_r.ip();
#ifdef QNX
PRIVATE->addr_.sin_len = sizeof(PRIVATE->addr_);
#endif
@@ -262,7 +377,7 @@ bool PIEthernet::openDevice() {
tries++;
}
if (tries == 2) {
piCoutObj << "Can`t bind to " << ip_ << ":" << port_ << ", " << ethErrorString();
piCoutObj << "Can`t bind to " << addr_r << ", " << ethErrorString();
return false;
}
opened_ = true;
@@ -271,8 +386,7 @@ bool PIEthernet::openDevice() {
//cout << "!" << endl;
applyTimeouts();
applyOptInt(IPPROTO_IP, IP_TTL, TTL());
port_r = 0;
ip_r.clear();
addr_lr.clear();
return true;
}
@@ -363,7 +477,7 @@ bool PIEthernet::joinMulticastGroup(const PIString & group) {
//#ifndef QNX
//if (!params[Broadcast])
//;piCoutObj << "Warning: \"Broadcast\" parameter not set, \"joinMulticastGroup(\"" << group << "\")\" may be useless!";
parseAddress(path(), &ip_, &port_);
addr_r.set(path());
struct ip_mreqn mreq;
memset(&mreq, 0, sizeof(mreq));
#ifdef LINUX
@@ -373,7 +487,7 @@ bool PIEthernet::joinMulticastGroup(const PIString & group) {
if (ci != 0) mreq.imr_ifindex = ci->index;*/
#endif
if (params[PIEthernet::Broadcast]) mreq.imr_address.s_addr = INADDR_ANY;
else mreq.imr_address.s_addr = inet_addr(ip_.dataAscii());
else mreq.imr_address.s_addr = addr_r.ip();
/*#ifndef WINDOWS
PIEthernet::InterfaceList il = interfaces();
const PIEthernet::Interface * ci = il.getByAddress(ip_);
@@ -415,11 +529,11 @@ bool PIEthernet::leaveMulticastGroup(const PIString & group) {
}
PIFlags<Parameters> params = parameters();
/// TODO windows
parseAddress(path(), &ip_, &port_);
addr_r.set(path());
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_.dataAscii());
else mreq.imr_address.s_addr = addr_r.ip();
mreq.imr_multiaddr.s_addr = inet_addr(group.dataAscii());
if (ethSetsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) == -1) {
piCoutObj << "Can`t leave multicast group " << group << ", " << ethErrorString();
@@ -468,10 +582,10 @@ bool PIEthernet::listen(bool threaded) {
return true;
}
listen_threaded = server_bounded = false;
parseAddress(path(), &ip_, &port_);
addr_r.set(path());
memset(&PRIVATE->addr_, 0, sizeof(PRIVATE->addr_));
PRIVATE->addr_.sin_port = htons(port_);
PRIVATE->addr_.sin_addr.s_addr = inet_addr(ip_.dataAscii());
PRIVATE->addr_.sin_port = htons(addr_r.port());
PRIVATE->addr_.sin_addr.s_addr = addr_r.ip();
PRIVATE->addr_.sin_family = AF_INET;
#ifdef QNX
PRIVATE->addr_.sin_len = sizeof(PRIVATE->addr_);
@@ -483,11 +597,11 @@ bool PIEthernet::listen(bool threaded) {
tries++;
}
if (tries == 2) {
piCoutObj << "Can`t bind to " << ip_ << ":" << port_ << ", " << ethErrorString();
piCoutObj << "Can`t bind to " << addr_r << ", " << ethErrorString();
return false;
}
if (::listen(sock, 64) == -1) {
piCoutObj << "Can`t listen on "<< ip_ << ":" << port_ << ", " << ethErrorString();
piCoutObj << "Can`t listen on "<< addr_r << ", " << ethErrorString();
return false;
}
opened_ = server_bounded = true;
@@ -528,9 +642,9 @@ int PIEthernet::readDevice(void * read_to, int max_size) {
qDebug() << "init() in read thread";*/
#endif
memset(&PRIVATE->addr_, 0, sizeof(PRIVATE->addr_));
parseAddress(path(), &ip_, &port_);
PRIVATE->addr_.sin_port = htons(port_);
PRIVATE->addr_.sin_addr.s_addr = inet_addr(ip_.dataAscii());
addr_r.set(path());
PRIVATE->addr_.sin_port = htons(addr_r.port());
PRIVATE->addr_.sin_addr.s_addr = addr_r.ip();
PRIVATE->addr_.sin_family = AF_INET;
#ifdef QNX
PRIVATE->addr_.sin_len = sizeof(PRIVATE->addr_);
@@ -541,7 +655,7 @@ int PIEthernet::readDevice(void * read_to, int max_size) {
//piCoutObj << "connect to " << ip_ << ":" << port_ << connected_;
//qDebug() << "connect to " << ip_.data() << ":" << port_ << connected_;
if (!connected_)
piCoutObj << "Can`t connect to " << ip_ << ":" << port_ << ", " << ethErrorString();
piCoutObj << "Can`t connect to " << addr_r << ", " << ethErrorString();
opened_ = connected_;
if (connected_) {
connecting_ = false;
@@ -584,8 +698,7 @@ int PIEthernet::readDevice(void * read_to, int max_size) {
memset(&PRIVATE->raddr_, 0, sizeof(PRIVATE->raddr_));
rs = ethRecvfrom(sock, read_to, max_size, 0, (sockaddr*)&PRIVATE->raddr_);
if (rs > 0) {
port_r = ntohs(PRIVATE->raddr_.sin_port);
ip_r = PIStringAscii(inet_ntoa(PRIVATE->raddr_.sin_addr));
addr_lr.set(uint(PRIVATE->raddr_.sin_addr.s_addr), ntohs(PRIVATE->raddr_.sin_port));
//piCoutObj << "read from" << ip_r << ":" << port_r << rs << "bytes";
//piCout << "received from" << lastReadAddress();
received(read_to, rs);
@@ -611,8 +724,8 @@ int PIEthernet::writeDevice(const void * data, int max_size) {
switch (type()) {
case TCP_SingleTCP:
memset(&PRIVATE->addr_, 0, sizeof(PRIVATE->addr_));
PRIVATE->addr_.sin_port = htons(port_s);
PRIVATE->addr_.sin_addr.s_addr = inet_addr(ip_s.dataAscii());
PRIVATE->addr_.sin_port = htons(addr_s.port());
PRIVATE->addr_.sin_addr.s_addr = addr_s.ip();
PRIVATE->addr_.sin_family = AF_INET;
#ifdef QNX
PRIVATE->addr_.sin_len = sizeof(PRIVATE->addr_);
@@ -630,9 +743,9 @@ int PIEthernet::writeDevice(const void * data, int max_size) {
init();
return ret;
case UDP:
PRIVATE->saddr_.sin_port = htons(port_s);
PRIVATE->saddr_.sin_port = htons(addr_s.port());
/*if (params[PIEthernet::Broadcast]) PRIVATE->saddr_.sin_addr.s_addr = INADDR_BROADCAST;
else*/ PRIVATE->saddr_.sin_addr.s_addr = inet_addr(ip_s.dataAscii());
else*/ PRIVATE->saddr_.sin_addr.s_addr = addr_s.ip();
PRIVATE->saddr_.sin_family = AF_INET;
//piCoutObj << "write to" << ip_s << ":" << port_s << "socket" << sock_s << max_size << "bytes ...";
return ethSendto(sock_s, data, max_size,
@@ -646,9 +759,9 @@ int PIEthernet::writeDevice(const void * data, int max_size) {
case TCP_Client:
if (connecting_) {
memset(&PRIVATE->addr_, 0, sizeof(PRIVATE->addr_));
parseAddress(path(), &ip_, &port_);
PRIVATE->addr_.sin_port = htons(port_);
PRIVATE->addr_.sin_addr.s_addr = inet_addr(ip_.dataAscii());
addr_r.set(path());
PRIVATE->addr_.sin_port = htons(addr_r.port());
PRIVATE->addr_.sin_addr.s_addr = addr_r.ip();
PRIVATE->addr_.sin_family = AF_INET;
#ifdef QNX
PRIVATE->addr_.sin_len = sizeof(PRIVATE->addr_);
@@ -656,7 +769,7 @@ int PIEthernet::writeDevice(const void * data, int max_size) {
//piCoutObj << "connect to " << ip << ":" << port_;
connected_ = (::connect(sock, (sockaddr * )&PRIVATE->addr_, sizeof(PRIVATE->addr_)) == 0);
if (!connected_)
piCoutObj << "Can`t connect to " << ip_ << ":" << port_ << ", " << ethErrorString();
piCoutObj << "Can`t connect to " << addr_r << ", " << ethErrorString();
opened_ = connected_;
if (connected_) {
connecting_ = false;
@@ -980,10 +1093,10 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
}
PIString PIEthernet::interfaceAddress(const PIString & interface_) {
PIEthernet::Address PIEthernet::interfaceAddress(const PIString & interface_) {
#ifdef WINDOWS
piCout << "[PIEthernet] Not implemented on Windows, use \"PIEthernet::allAddresses\" or \"PIEthernet::interfaces\" instead";
return PIString();
return Address();
#else
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
@@ -992,13 +1105,13 @@ PIString PIEthernet::interfaceAddress(const PIString & interface_) {
ioctl(s, SIOCGIFADDR, &ifr);
::close(s);
struct sockaddr_in * sa = (struct sockaddr_in * )&ifr.ifr_addr;
return PIStringAscii(inet_ntoa(sa->sin_addr));
return Address(uint(sa->sin_addr));
#endif
}
PIStringList PIEthernet::allAddresses() {
PIVector<PIEthernet::Address> PIEthernet::allAddresses() {
/*#ifdef WINDOWS
PIStringList al;
PIString ca;
@@ -1032,38 +1145,18 @@ PIStringList PIEthernet::allAddresses() {
return al;
#else*/
PIEthernet::InterfaceList il = interfaces();
PIStringList al;
piForeachC (PIEthernet::Interface & i, il)
al << i.address;
PIVector<Address> ret;
bool has_127 = false;
piForeachC (PIEthernet::Interface & i, il) {
if (i.address == "127.0.0.1") has_127 = true;
Address a(i.address);
if (a.ip() == 0) continue;
ret << a;
}
// piCout << "[PIEthernet::allAddresses]" << al;
if (!al.contains("127.0.0.1")) al << "127.0.0.1";
return al.removeStrings("0.0.0.0");
//#endif
}
PIString PIEthernet::resolve(const PIString & host) {
PIString ip(host), port;
int i = host.find(':');
if (i >= 0) {
ip = host.left(i);
port = host.right(host.length() - i - 1);
}
PIString ret = PIStringAscii("0.0.0.0");
if (!port.isEmpty()) ret += PIStringAscii(":") + port;
//#ifdef WINDOWS
hostent * he = gethostbyname(ip.dataAscii());
if (!he)
return ret;
struct in_addr addr;
if (he->h_addr_list[0]) {
addr.s_addr = *((uint*)(he->h_addr_list[0]));
ret = inet_ntoa(addr);
if (!port.isEmpty()) ret += PIStringAscii(":") + port;
}
//#else
//#endif
if (!has_127) ret << Address("127.0.0.1");
return ret;
//#endif
}

View File

@@ -61,6 +61,43 @@ public:
DisonnectOnTimeout /** Disconnect TCP connection on read timeout expired. Disabled by default */ = 0x20
};
//! \brief IPv4 network address, ip and port
class Address {
friend class PIEthernet;
friend inline PIByteArray & operator <<(PIByteArray & s, const PIEthernet::Address & v);
friend inline PIByteArray & operator >>(PIByteArray & s, PIEthernet::Address & v);
public:
//! Contructs %Address with binary representation of ip and port
Address(uint ip = 0, ushort port = 0);
Address(const PIString & ip_port);
Address(const PIString & ip, ushort port);
uint ip() const {return ip_;}
ushort port() const {return port_;}
PIString ipString() const;
PIString toString() const;
void setIP(uint ip);
void setIP(const PIString & ip);
void setPort(ushort port);
void set(const PIString & ip_port);
void set(const PIString & ip, ushort port);
void set(uint ip, ushort port);
void clear();
//! Resolve hostname "host" and return it IPv4 address or "0.0.0.0" on error
static PIString resolve(const PIString & host);
static void splitIPPort(const PIString & ipp, PIString * ip, int * port);
private:
void initIP(const PIString & _ip);
union {
uint ip_;
uchar ip_b[4];
};
ushort port_;
};
//! Contructs %PIEthernet with type "type", read address "ip_port" and parameters "params"
explicit PIEthernet(Type type, const PIString & ip_port = PIString(), const PIFlags<Parameters> params = PIEthernet::ReuseAddress | PIEthernet::MulticastLoop | PIEthernet::KeepConnection);
@@ -68,59 +105,65 @@ public:
//! Set read address
void setReadAddress(const PIString & ip, int port) {setPath(ip + PIStringAscii(":") + PIString::fromNumber(port));}
void setReadAddress(const PIString & ip, int port) {addr_r.set(ip, port); setPath(addr_r.toString());}
//! Set read address in format "i.i.i.i:p"
void setReadAddress(const PIString & ip_port) {setPath(ip_port);}
void setReadAddress(const PIString & ip_port) {addr_r.set(ip_port); setPath(addr_r.toString());}
//! Set read address
void setReadAddress(const Address & addr) {addr_r = addr; setPath(addr_r.toString());}
//! Set read IP
void setReadIP(const PIString & ip) {parseAddress(path(), &ip_, &port_); setPath(ip + PIStringAscii(":") + PIString::fromNumber(port_));}
void setReadIP(const PIString & ip) {addr_r.setIP(ip); setPath(addr_r.toString());}
//! Set read port
void setReadPort(int port) {parseAddress(path(), &ip_, &port_); setPath(ip_ + PIStringAscii(":") + PIString::fromNumber(port));}
void setReadPort(int port) {addr_r.setPort(port); setPath(addr_r.toString());}
//! Set send address
void setSendAddress(const PIString & ip, int port) {ip_s = ip; port_s = port;}
void setSendAddress(const PIString & ip, int port) {addr_s.set(ip, port);}
//! Set send address in format "i.i.i.i:p"
void setSendAddress(const PIString & ip_port) {parseAddress(ip_port, &ip_s, &port_s);}
void setSendAddress(const PIString & ip_port) {addr_s.set(ip_port);}
//! Set send address
void setSendAddress(const Address & addr) {addr_s = addr;}
//! Set send IP
void setSendIP(const PIString & ip) {ip_s = ip;}
void setSendIP(const PIString & ip) {addr_s.setIP(ip);}
//! Set send port
void setSendPort(int port) {port_s = port;}
void setSendPort(int port) {addr_s.setPort(port);}
//! Returns read address in format "i.i.i.i:p"
PIString readAddress() const {return path();}
Address readAddress() const {return addr_r;}
//! Returns read IP
PIString readIP() const {parseAddress(path(), &ip_, &port_); return ip_;}
PIString readIP() const {return addr_r.ipString();}
//! Returns read port
int readPort() const {parseAddress(path(), &ip_, &port_); return port_;}
int readPort() const {return addr_r.port();}
//! Returns send address in format "i.i.i.i:p"
PIString sendAddress() const {return ip_s + PIStringAscii(":") + PIString::fromNumber(port_s);}
Address sendAddress() const {return addr_s;}
//! Returns send IP
PIString sendIP() const {return ip_s;}
PIString sendIP() const {return addr_s.ipString();}
//! Returns send port
int sendPort() const {return port_s;}
int sendPort() const {return addr_s.port();}
//! Returns address of last received UDP packet in format "i.i.i.i:p"
PIString lastReadAddress() const {return ip_r + PIStringAscii(":") + PIString::fromNumber(port_r);}
Address lastReadAddress() const {return addr_lr;}
//! Returns IP of last received UDP packet
PIString lastReadIP() const {return ip_r;}
PIString lastReadIP() const {return addr_lr.ipString();}
//! Returns port of last received UDP packet
int lastReadPort() const {return port_r;}
int lastReadPort() const {return addr_lr.port();}
//! Set parameters to "parameters_". You should to reopen %PIEthernet to apply them
@@ -210,19 +253,25 @@ public:
bool send(const void * data, int size, bool threaded = false) {if (threaded) {writeThreaded(data, size); return true;} return (write(data, size) == size);}
//! Send data "data" with size "size" to address "ip":"port"
bool send(const PIString & ip, int port, const void * data, int size, bool threaded = false) {ip_s = ip; port_s = port; if (threaded) {writeThreaded(data, size); return true;} return send(data, size);}
bool send(const PIString & ip, int port, const void * data, int size, bool threaded = false) {addr_s.set(ip, port); if (threaded) {writeThreaded(data, size); return true;} return send(data, size);}
//! Send data "data" with size "size" to address "ip_port"
bool send(const PIString & ip_port, const void * data, int size, bool threaded = false) {parseAddress(ip_port, &ip_s, &port_s); if (threaded) {writeThreaded(data, size); return true;} return send(data, size);}
bool send(const PIString & ip_port, const void * data, int size, bool threaded = false) {addr_s.set(ip_port); if (threaded) {writeThreaded(data, size); return true;} return send(data, size);}
//! Send data "data" with size "size" to address "addr"
bool send(const Address & addr, const void * data, int size, bool threaded = false) {addr_s = addr; if (threaded) {writeThreaded(data, size); return true;} return send(data, size);}
//! Send data "data" to address \a sendAddress() for UDP or \a readAddress() for TCP_Client
bool send(const PIByteArray & data, bool threaded = false) {if (threaded) {writeThreaded(data); return true;} return (write(data) == data.size_s());}
//! Send data "data" to address "ip":"port" for UDP
bool send(const PIString & ip, int port, const PIByteArray & data, bool threaded = false) {ip_s = ip; port_s = port; if (threaded) {writeThreaded(data); return true;} return send(data);}
bool send(const PIString & ip, int port, const PIByteArray & data, bool threaded = false) {addr_s.set(ip, port); if (threaded) {writeThreaded(data); return true;} return send(data);}
//! Send data "data" to address "ip_port" for UDP
bool send(const PIString & ip_port, const PIByteArray & data, bool threaded = false) {parseAddress(ip_port, &ip_s, &port_s); if (threaded) {writeThreaded(data); return true;} return (write(data) == data.size_s());}
bool send(const PIString & ip_port, const PIByteArray & data, bool threaded = false) {addr_s.set(ip_port); if (threaded) {writeThreaded(data); return true;} return (write(data) == data.size_s());}
//! Send data "data" to address "addr" for UDP
bool send(const Address & addr, const PIByteArray & data, bool threaded = false) {addr_s = addr; if (threaded) {writeThreaded(data); return true;} return (write(data) == data.size_s());}
virtual bool canWrite() const {return mode() & WriteOnly;}
@@ -317,19 +366,17 @@ public:
//! Returns all system network interfaces
static InterfaceList interfaces();
static PIString interfaceAddress(const PIString & interface_);
static PIEthernet::Address interfaceAddress(const PIString & interface_);
//! Returns all system network IP addresses
static PIStringList allAddresses();
//! Resolve hostname "host" and return it IPv4 address or "0.0.0.0" on error
static PIString resolve(const PIString & host);
static PIVector<PIEthernet::Address> allAddresses();
static void parseAddress(const PIString & ipp, PIString * ip, int * port);
static PIString macFromBytes(const PIByteArray & mac);
static PIByteArray macToBytes(const PIString & mac);
static PIString applyMask(const PIString & ip, const PIString & mask);
static Address applyMask(const Address & ip, const Address & mask);
static PIString getBroadcast(const PIString & ip, const PIString & mask);
static Address getBroadcast(const Address & ip, const Address & mask);
//! \events
//! \{
@@ -396,9 +443,8 @@ protected:
PRIVATE_DECLARATION
int sock, sock_s;
mutable int port_, port_s, port_r;
bool connected_, connecting_, listen_threaded, server_bounded;
mutable PIString ip_, ip_s, ip_r;
mutable Address addr_r, addr_s, addr_lr;
PIThread server_thread_;
PIMutex clients_mutex;
PIVector<PIEthernet * > clients_;
@@ -425,5 +471,11 @@ private:
inline bool operator <(const PIEthernet::Interface & v0, const PIEthernet::Interface & v1) {return (v0.name < v1.name);}
inline bool operator ==(const PIEthernet::Interface & v0, const PIEthernet::Interface & v1) {return (v0.name == v1.name && v0.address == v1.address && v0.netmask == v1.netmask);}
inline bool operator !=(const PIEthernet::Interface & v0, const PIEthernet::Interface & v1) {return (v0.name != v1.name || v0.address != v1.address || v0.netmask != v1.netmask);}
inline PICout operator <<(PICout s, const PIEthernet::Address & v) {s.setControl(0, true); s << "Address(" << v.toString() << ")"; s.restoreControl(); return s;}
inline bool operator ==(const PIEthernet::Address & v0, const PIEthernet::Address & v1) {return (v0.ip() == v1.ip() && v0.port() == v1.port());}
inline bool operator !=(const PIEthernet::Address & v0, const PIEthernet::Address & v1) {return (v0.ip() != v1.ip() || v0.port() != v1.port());}
inline PIByteArray & operator <<(PIByteArray & s, const PIEthernet::Address & v) {s << v.ip_ << v.port_; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIEthernet::Address & v) {s >> v.ip_ >> v.port_; return s;}
#endif // PIETHERNET_H

View File

@@ -112,7 +112,7 @@ void PIPeer::PeerData::setDist(int dist) {
PIPeer::PeerInfo::Address::Address(const PIString & a, const PIString & m): address(a), netmask(m) {
PIPeer::PeerInfo::PeerAddress::PeerAddress(const PIEthernet::Address & a, const PIEthernet::Address & m): address(a), netmask(m) {
ping = -1.;
wait_ping = false;
last_ping = PISystemTime::current(true);
@@ -121,7 +121,7 @@ PIPeer::PeerInfo::Address::Address(const PIString & a, const PIString & m): addr
int PIPeer::PeerInfo::ping() const {
int ret = -1;
piForeachC (Address & a, addresses)
piForeachC (PeerAddress & a, addresses)
if (a.ping > 0.) {
if (ret < 0) ret = piRoundd(a.ping);
else ret = piMini(ret, piRoundd(a.ping));
@@ -141,10 +141,10 @@ void PIPeer::PeerInfo::destroy() {
}
PIString PIPeer::PeerInfo::fastestAddress() const {
PIEthernet::Address PIPeer::PeerInfo::fastestAddress() const {
double mp = -1.;
PIString ret;
piForeachC (Address & a, addresses) {
PIEthernet::Address ret;
piForeachC (PeerAddress & a, addresses) {
if (a.ping <= 0.) continue;
if ((mp < 0) || (mp > a.ping)) {
mp = a.ping;
@@ -248,7 +248,7 @@ void PIPeer::initEths(PIStringList al) {
if (ce->open()) {
eths_traffic << ce;
cint = prev_ifaces.getByAddress(a);
self_info.addresses << PeerInfo::Address(ce->path(), cint == 0 ? "255.255.255.0" : cint->netmask);
self_info.addresses << PeerInfo::PeerAddress(ce->path(), cint == 0 ? "255.255.255.0" : cint->netmask);
CONNECTU(ce, threadedReadEvent, this, dataRead);
ce->startThreadedRead();
// piCoutObj << "dc binded to" << ce->path();
@@ -473,7 +473,7 @@ bool PIPeer::dataRead(uchar * readed, int size) {
eth_mutex.lock();
// piCout << "dataRead lock";
if (type == 5) { // ping request
PIString addr;
PIEthernet::Address addr;
PISystemTime time;
ba >> to >> from >> addr >> time;
// piCout << "ping request" << to << from << addr;
@@ -485,7 +485,7 @@ bool PIPeer::dataRead(uchar * readed, int size) {
sba << int(6) << to << from << addr << time;
// piCout << " ping from" << from << addr << ", send back to" << pi->name;
send_mutex.lock();
piForeachC (PeerInfo::Address & a, pi->addresses) {
piForeachC (PeerInfo::PeerAddress & a, pi->addresses) {
if (eth_send.send(a.address, sba))
diag_s.received(sba.size_s());
}
@@ -497,7 +497,7 @@ bool PIPeer::dataRead(uchar * readed, int size) {
return true;
}
if (type == 6) { // ping request
PIString addr;
PIEthernet::Address addr;
PISystemTime time, ptime, ctime = PISystemTime::current(true);
ba >> to >> from >> addr >> time;
// piCout << "ping reply" << to << from << addr;
@@ -506,7 +506,7 @@ bool PIPeer::dataRead(uchar * readed, int size) {
piForeach (PeerInfo & p, peers) {
if (!p.isNeighbour()) continue;
if (p.name != from) continue;
piForeach (PeerInfo::Address & a, p.addresses) {
piForeach (PeerInfo::PeerAddress & a, p.addresses) {
if (a.address != addr) continue;
if (a.last_ping >= time) piBreak;
ptime = ctime - time;
@@ -674,9 +674,9 @@ bool PIPeer::mbcastRead(uchar * data, int size) {
if (isPeerRecent(peer, rpeer)) {
//piCout << "synced " << peer.name;
for (int z = 0; z < rpeer.addresses.size_s(); ++z) {
PeerInfo::Address & ra(rpeer.addresses[z]);
PeerInfo::PeerAddress & ra(rpeer.addresses[z]);
for (int k = 0; k < peer.addresses.size_s(); ++k) {
PeerInfo::Address & a(peer.addresses[k]);
PeerInfo::PeerAddress & a(peer.addresses[k]);
if (ra.address == a.address) {
ra.ping = a.ping;
ra.wait_ping = a.wait_ping;
@@ -727,7 +727,7 @@ bool PIPeer::mbcastRead(uchar * data, int size) {
bool PIPeer::sendToNeighbour(PIPeer::PeerInfo * peer, const PIByteArray & ba) {
//if (peer->_neth == 0) return false;
PIString addr = peer->fastestAddress();
PIEthernet::Address addr = peer->fastestAddress();
//piCout << "[PIPeer] sendToNeighbour" << peer->name << addr << ba.size_s() << "bytes ...";
//bool ok = peer->_neth->send(peer->_naddress, ba.data(), ba.size_s());
send_mutex.lock();
@@ -828,7 +828,7 @@ void PIPeer::pingNeighbours() {
if (!p.isNeighbour()) continue;
//piCout << " ping neighbour" << p.name << p.ping();
send_mutex.lock();
piForeach (PeerInfo::Address & a, p.addresses) {
piForeach (PeerInfo::PeerAddress & a, p.addresses) {
// piCout << " address" << a.address << a.wait_ping;
if (a.wait_ping) {
if ((PISystemTime::current(true) - a.last_ping).abs().toSeconds() <= _PIPEER_PING_TIMEOUT)
@@ -1030,7 +1030,10 @@ void PIPeer::initNetwork() {
piMSleep(100);
// piCoutObj << self_info.addresses.size();
self_info.addresses.clear();
PIStringList sl = PIEthernet::allAddresses();
PIVector<PIEthernet::Address> al = PIEthernet::allAddresses();
PIStringList sl;
piForeachC (PIEthernet::Address & a, al)
sl << a.ipString();
initEths(sl);
// piCoutObj << sl << self_info.addresses.size();
sl.removeAll("127.0.0.1");

View File

@@ -44,25 +44,25 @@ public:
PeerInfo() {dist = sync = cnt = 0; trace = -1; was_update = false; _data = 0;}
~PeerInfo() {}
struct Address {
Address(const PIString & a = PIString(), const PIString & m = "255.255.255.0");
struct PeerAddress {
PeerAddress(const PIEthernet::Address & a = PIEthernet::Address(), const PIEthernet::Address & m = PIEthernet::Address("255.255.255.0"));
bool isAvailable() const {return ping > 0;}
//inline const Address & operator =(const Address & v) {address = v.address; netmask = v.netmask; piCout << "!!!!!!!!!" << last_ping; return *this;}
PIString address;
PIString netmask;
PIEthernet::Address address;
PIEthernet::Address netmask;
double ping; // ms
bool wait_ping;
PISystemTime last_ping;
};
PIString name;
PIVector<Address> addresses;
PIVector<PeerAddress> addresses;
int dist;
PIStringList neighbours;
bool isNeighbour() const {return dist == 0;}
int ping() const;
PIString fastestAddress() const;
PIEthernet::Address fastestAddress() const;
protected:
void addNeighbour(const PIString & n) {if (!neighbours.contains(n)) neighbours << n;}
@@ -203,11 +203,11 @@ private:
PIMutex mc_mutex, eth_mutex, peers_mutex, send_mutex, send_mc_mutex;
};
inline PICout operator <<(PICout c, const PIPeer::PeerInfo::Address & v) {c.space(); c << "PeerAddress(" << v.address << ", " << v.netmask << ", " << v.ping << ")"; return c;}
inline PICout operator <<(PICout c, const PIPeer::PeerInfo::PeerAddress & v) {c.space(); c << "PeerAddress(" << v.address << ", " << v.netmask << ", " << v.ping << ")"; return c;}
inline PICout operator <<(PICout c, const PIPeer::PeerInfo & v) {c.space(); c << "PeerInfo(" << v.name << ", " << v.dist << ", " << v.addresses << ")"; return c;}
inline PIByteArray & operator <<(PIByteArray & s, const PIPeer::PeerInfo::Address & v) {s << v.address << v.netmask << v.ping; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIPeer::PeerInfo::Address & v) {s >> v.address >> v.netmask >> v.ping; return s;}
inline PIByteArray & operator <<(PIByteArray & s, const PIPeer::PeerInfo::PeerAddress & v) {s << v.address << v.netmask << v.ping; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIPeer::PeerInfo::PeerAddress & v) {s >> v.address >> v.netmask >> v.ping; return s;}
inline PIByteArray & operator <<(PIByteArray & s, const PIPeer::PeerInfo & v) {s << v.name << v.addresses << v.dist << v.neighbours << v.cnt << v.time; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIPeer::PeerInfo & v) {s >> v.name >> v.addresses >> v.dist >> v.neighbours >> v.cnt >> v.time; return s;}

View File

@@ -5,6 +5,6 @@
#define PIP_VERSION_MAJOR 1
#define PIP_VERSION_MINOR 0
#define PIP_VERSION_REVISION 0
#define PIP_VERSION_SUFFIX "_rc5"
#define PIP_VERSION_SUFFIX "_rc6"
#endif // PIVERSION_H

View File

@@ -192,8 +192,8 @@ public:
peerinfo_tl->content << TileSimple::Row("Name: " + pi.name, CellFormat());
peerinfo_tl->content << TileSimple::Row("Addreses: " + PIString::fromNumber(pi.addresses.size()), CellFormat());
peerinfo_tl->content << TileSimple::Row("Neighbours: " + pi.neighbours.join(", "), CellFormat());
piForeachC(PIPeer::PeerInfo::Address &a , pi.addresses)
addrs_tl->content << TileList::Row(a.address +
piForeachC(PIPeer::PeerInfo::PeerAddress &a , pi.addresses)
addrs_tl->content << TileList::Row(a.address.toString() +
" | p = " + PIString::fromNumber(a.ping) +
" | a = " + PIString::fromBool(a.isAvailable()), CellFormat());
typedef PIPair<PIString, PIVector <PIPeer::PeerInfo* > > PeerPair;