From 6f54f501cd99b84e9e474654e756fd502fd5d210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=B5=D0=BB=D0=B8=D0=BF=D0=B5=D0=BD=D0=BA=D0=BE=20?= =?UTF-8?q?=D0=98=D0=B2=D0=B0=D0=BD?= Date: Tue, 5 Sep 2017 15:20:33 +0000 Subject: [PATCH] git-svn-id: svn://db.shs.com.ru/pip@542 12ceb7fc-bf1f-11e4-8940-5bc7170c53b5 --- main.cpp | 49 ++++++- src_main/io/piethernet.cpp | 239 ++++++++++++++++++++++++----------- src_main/io/piethernet.h | 110 +++++++++++----- src_main/io/pipeer.cpp | 33 ++--- src_main/io/pipeer.h | 18 +-- src_main/piversion.h | 2 +- utils/system_daemon/main.cpp | 4 +- 7 files changed, 324 insertions(+), 131 deletions(-) diff --git a/main.cpp b/main.cpp index 5488797c..ecc03777 100644 --- a/main.cpp +++ b/main.cpp @@ -1,16 +1,61 @@ #include "pip.h" #include "pivector2d.h" #include "pistring.h" +#ifdef QNX +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# ifdef BLACKBERRY +# include +# else +# include +# endif +# define ip_mreqn ip_mreq +# define imr_address imr_interface +#else +# ifdef WINDOWS +# include +# include +# include +# include +# include +# define ip_mreqn ip_mreq +# define imr_address imr_interface +# else +# include +# include +# include +# include +# include +# include +# include +# ifndef ANDROID +# include +# endif +# endif +#endif +#include 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; } diff --git a/src_main/io/piethernet.cpp b/src_main/io/piethernet.cpp index 1dadd2ca..8686c5b5 100755 --- a/src_main/io/piethernet.cpp +++ b/src_main/io/piethernet.cpp @@ -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 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 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 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::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
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 } diff --git a/src_main/io/piethernet.h b/src_main/io/piethernet.h index 5e970024..99b4885f 100755 --- a/src_main/io/piethernet.h +++ b/src_main/io/piethernet.h @@ -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 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 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 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 diff --git a/src_main/io/pipeer.cpp b/src_main/io/pipeer.cpp index 99a73657..05542384 100755 --- a/src_main/io/pipeer.cpp +++ b/src_main/io/pipeer.cpp @@ -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 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"); diff --git a/src_main/io/pipeer.h b/src_main/io/pipeer.h index 540d8673..673f86c4 100755 --- a/src_main/io/pipeer.h +++ b/src_main/io/pipeer.h @@ -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
addresses; + PIVector 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;} diff --git a/src_main/piversion.h b/src_main/piversion.h index eda29513..b5dc3ca9 100644 --- a/src_main/piversion.h +++ b/src_main/piversion.h @@ -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 diff --git a/utils/system_daemon/main.cpp b/utils/system_daemon/main.cpp index 61a12ef6..bcbd1695 100755 --- a/utils/system_daemon/main.cpp +++ b/utils/system_daemon/main.cpp @@ -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 > PeerPair;