git-svn-id: svn://db.shs.com.ru/pip@542 12ceb7fc-bf1f-11e4-8940-5bc7170c53b5
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user