version 0.5.0_alpha
git-svn-id: svn://db.shs.com.ru/pip@8 12ceb7fc-bf1f-11e4-8940-5bc7170c53b5
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Ethernet, UDP/TCP Broadcast/Multicast
|
||||
Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com
|
||||
Copyright (C) 2015 Ivan Pelipenko peri4ko@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -19,16 +19,32 @@
|
||||
|
||||
#include "piethernet.h"
|
||||
#include "piconfig.h"
|
||||
#include "pisysteminfo.h"
|
||||
#ifdef QNX
|
||||
# include <net/if_dl.h>
|
||||
# include <hw/nicinfo.h>
|
||||
# include <sys/dcmd_io-net.h>
|
||||
#endif
|
||||
#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>
|
||||
# ifndef ANDROID
|
||||
# include <ifaddrs.h>
|
||||
# endif
|
||||
#endif
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
/** \class PIEthernet
|
||||
@@ -51,9 +67,23 @@
|
||||
*
|
||||
* */
|
||||
|
||||
#ifndef WINDOWS
|
||||
PIString getSockAddr(sockaddr * s) {
|
||||
return s == 0 ? PIString() : PIString(inet_ntoa(((sockaddr_in*)s)->sin_addr));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
REGISTER_DEVICE(PIEthernet);
|
||||
|
||||
|
||||
PRIVATE_DEFINITION_START(PIEthernet)
|
||||
sockaddr_in addr_;
|
||||
sockaddr_in saddr_;
|
||||
sockaddr_in raddr_;
|
||||
PRIVATE_DEFINITION_END(PIEthernet)
|
||||
|
||||
|
||||
PIEthernet::PIEthernet(): PIIODevice("", ReadWrite) {
|
||||
construct();
|
||||
setType(UDP);
|
||||
@@ -140,11 +170,45 @@ 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) {
|
||||
r += PIString::fromNumber(mac[i], 16).expandLeftTo(2, '0');
|
||||
if (i < mac.size_s() - 1) r += ":";
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
PIByteArray PIEthernet::macToBytes(const PIString & mac) {
|
||||
PIByteArray r;
|
||||
PIStringList sl = mac.split(":");
|
||||
piForeachC (PIString & i, sl)
|
||||
r << uchar(i.toInt(16));
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
PIString PIEthernet::applyMask(const PIString & ip, const PIString & mask) {
|
||||
struct in_addr ia;
|
||||
ia.s_addr = inet_addr(ip.data()) & inet_addr(mask.data());
|
||||
return PIString(inet_ntoa(ia));
|
||||
}
|
||||
|
||||
|
||||
PIString PIEthernet::getBroadcast(const PIString & ip, const PIString & mask) {
|
||||
struct in_addr ia;
|
||||
ia.s_addr = inet_addr(ip.data()) | ~inet_addr(mask.data());
|
||||
return PIString(inet_ntoa(ia));
|
||||
}
|
||||
|
||||
|
||||
bool PIEthernet::openDevice() {
|
||||
if (connected_) return true;
|
||||
init();
|
||||
@@ -154,18 +218,18 @@ bool PIEthernet::openDevice() {
|
||||
connecting_ = true;
|
||||
if (type() != UDP || mode() == PIIODevice::WriteOnly)
|
||||
return true;
|
||||
memset(&addr_, 0, sizeof(addr_));
|
||||
addr_.sin_family = AF_INET;
|
||||
addr_.sin_port = htons(port_);
|
||||
memset(&PRIVATE->addr_, 0, sizeof(PRIVATE->addr_));
|
||||
PRIVATE->addr_.sin_family = AF_INET;
|
||||
PRIVATE->addr_.sin_port = htons(port_);
|
||||
PIFlags<Parameters> params = parameters();
|
||||
if (params[PIEthernet::Broadcast]) addr_.sin_addr.s_addr = INADDR_ANY;
|
||||
else addr_.sin_addr.s_addr = inet_addr(ip_.data());
|
||||
if (params[PIEthernet::Broadcast]) PRIVATE->addr_.sin_addr.s_addr = INADDR_ANY;
|
||||
else PRIVATE->addr_.sin_addr.s_addr = inet_addr(ip_.data());
|
||||
#ifdef QNX
|
||||
addr_.sin_len = sizeof(addr_);
|
||||
PRIVATE->addr_.sin_len = sizeof(PRIVATE->addr_);
|
||||
#endif
|
||||
//piCout << "bind to" << (params[PIEthernet::Broadcast] ? "255.255.255.255" : ip_) << ":" << port_ << " ...";
|
||||
int tries = 0;
|
||||
while ((bind(sock, (sockaddr * )&addr_, sizeof(addr_)) == -1) && (tries < 10)) {
|
||||
while ((bind(sock, (sockaddr * )&PRIVATE->addr_, sizeof(PRIVATE->addr_)) == -1) && (tries < 10)) {
|
||||
init();
|
||||
tries++;
|
||||
}
|
||||
@@ -328,16 +392,16 @@ bool PIEthernet::connect() {
|
||||
connecting_ = true;
|
||||
return true;
|
||||
/*if (sock == -1) return false;
|
||||
memset(&addr_, 0, sizeof(addr_));
|
||||
memset(addr_, 0, sizeof(*addr_));
|
||||
parseAddress(path_, &ip_, &port_);
|
||||
addr_.sin_port = htons(port_);
|
||||
addr_.sin_addr.s_addr = inet_addr(ip_.data());
|
||||
addr_.sin_family = AF_INET;
|
||||
PRIVATE->addr_.sin_port = htons(port_);
|
||||
PRIVATE->addr_.sin_addr.s_addr = inet_addr(ip_.data());
|
||||
PRIVATE->addr_.sin_family = AF_INET;
|
||||
#ifdef QNX
|
||||
addr_.sin_len = sizeof(addr_);
|
||||
PRIVATE->addr_.sin_len = sizeof(*addr_);
|
||||
#endif
|
||||
//piCoutObj << "connect to " << ip << ":" << port_;
|
||||
connected_ = (::connect(sock, (sockaddr * )&addr_, sizeof(addr_)) == 0);
|
||||
connected_ = (::connect(sock, (sockaddr * )addr_, sizeof(*addr_)) == 0);
|
||||
if (!connected_)
|
||||
piCoutObj << "Can`t connect to " << ip_ << ":" << port_ << ", " << ethErrorString();
|
||||
opened_ = connected_;
|
||||
@@ -363,16 +427,16 @@ bool PIEthernet::listen(bool threaded) {
|
||||
}
|
||||
listen_threaded = server_bounded = false;
|
||||
parseAddress(path(), &ip_, &port_);
|
||||
memset(&addr_, 0, sizeof(addr_));
|
||||
addr_.sin_port = htons(port_);
|
||||
addr_.sin_addr.s_addr = inet_addr(ip_.data());
|
||||
addr_.sin_family = AF_INET;
|
||||
memset(&PRIVATE->addr_, 0, sizeof(PRIVATE->addr_));
|
||||
PRIVATE->addr_.sin_port = htons(port_);
|
||||
PRIVATE->addr_.sin_addr.s_addr = inet_addr(ip_.data());
|
||||
PRIVATE->addr_.sin_family = AF_INET;
|
||||
#ifdef QNX
|
||||
addr_.sin_len = sizeof(addr_);
|
||||
PRIVATE->addr_.sin_len = sizeof(*addr_);
|
||||
#endif
|
||||
opened_ = false;
|
||||
int tries = 0;
|
||||
while ((bind(sock, (sockaddr * )&addr_, sizeof(addr_)) == -1) && (tries < 10)) {
|
||||
while ((bind(sock, (sockaddr * )&PRIVATE->addr_, sizeof(PRIVATE->addr_)) == -1) && (tries < 10)) {
|
||||
init();
|
||||
tries++;
|
||||
}
|
||||
@@ -413,16 +477,16 @@ int PIEthernet::read(void * read_to, int max_size) {
|
||||
return rs;
|
||||
case TCP_Client:
|
||||
if (connecting_) {
|
||||
memset(&addr_, 0, sizeof(addr_));
|
||||
memset(&PRIVATE->addr_, 0, sizeof(PRIVATE->addr_));
|
||||
parseAddress(path(), &ip_, &port_);
|
||||
addr_.sin_port = htons(port_);
|
||||
addr_.sin_addr.s_addr = inet_addr(ip_.data());
|
||||
addr_.sin_family = AF_INET;
|
||||
PRIVATE->addr_.sin_port = htons(port_);
|
||||
PRIVATE->addr_.sin_addr.s_addr = inet_addr(ip_.data());
|
||||
PRIVATE->addr_.sin_family = AF_INET;
|
||||
#ifdef QNX
|
||||
addr_.sin_len = sizeof(addr_);
|
||||
PRIVATE->addr_.sin_len = sizeof(PRIVATE->addr_);
|
||||
#endif
|
||||
//piCoutObj << "connect to " << ip_ << ":" << port_ << "...";
|
||||
connected_ = (::connect(sock, (sockaddr * )&addr_, sizeof(addr_)) == 0);
|
||||
connected_ = (::connect(sock, (sockaddr * )&PRIVATE->addr_, sizeof(PRIVATE->addr_)) == 0);
|
||||
//piCoutObj << "connect to " << ip_ << ":" << port_ << connected_;
|
||||
if (!connected_)
|
||||
piCoutObj << "Can`t connect to " << ip_ << ":" << port_ << ", " << ethErrorString();
|
||||
@@ -459,12 +523,12 @@ int PIEthernet::read(void * read_to, int max_size) {
|
||||
if (rs > 0) received(read_to, rs);
|
||||
return rs;
|
||||
case UDP:
|
||||
memset(&raddr_, 0, sizeof(raddr_));
|
||||
rs = ethRecvfrom(sock, read_to, max_size, 0, (sockaddr*)&raddr_);
|
||||
memset(&PRIVATE->raddr_, 0, sizeof(PRIVATE->raddr_));
|
||||
rs = ethRecvfrom(sock, read_to, max_size, 0, (sockaddr*)&PRIVATE->raddr_);
|
||||
//piCout << "eth" << path() << "read return" << rs << errorString();
|
||||
if (rs > 0) {
|
||||
port_r = ntohs(raddr_.sin_port);
|
||||
ip_r = inet_ntoa(raddr_.sin_addr);
|
||||
port_r = ntohs(PRIVATE->raddr_.sin_port);
|
||||
ip_r = inet_ntoa(PRIVATE->raddr_.sin_addr);
|
||||
//piCout << "received from" << lastReadAddress();
|
||||
received(read_to, rs);
|
||||
}
|
||||
@@ -487,15 +551,15 @@ int PIEthernet::write(const void * data, int max_size) {
|
||||
int ret = 0;
|
||||
switch (type()) {
|
||||
case TCP_SingleTCP:
|
||||
memset(&addr_, 0, sizeof(addr_));
|
||||
addr_.sin_port = htons(port_s);
|
||||
addr_.sin_addr.s_addr = inet_addr(ip_s.data());
|
||||
addr_.sin_family = AF_INET;
|
||||
memset(&PRIVATE->addr_, 0, sizeof(PRIVATE->addr_));
|
||||
PRIVATE->addr_.sin_port = htons(port_s);
|
||||
PRIVATE->addr_.sin_addr.s_addr = inet_addr(ip_s.data());
|
||||
PRIVATE->addr_.sin_family = AF_INET;
|
||||
#ifdef QNX
|
||||
addr_.sin_len = sizeof(addr_);
|
||||
PRIVATE->addr_.sin_len = sizeof(*addr_);
|
||||
#endif
|
||||
//piCoutObj << "connect SingleTCP" << ip_s << ":" << port_s << "...";
|
||||
if (::connect(sock, (sockaddr * )&addr_, sizeof(addr_)) != 0) {
|
||||
if (::connect(sock, (sockaddr * )&PRIVATE->addr_, sizeof(PRIVATE->addr_)) != 0) {
|
||||
//piCoutObj << "Can`t connect to " << ip_s << ":" << port_s << ", " << ethErrorString();
|
||||
msleep(1);
|
||||
return -1;
|
||||
@@ -507,25 +571,25 @@ int PIEthernet::write(const void * data, int max_size) {
|
||||
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());
|
||||
saddr_.sin_family = AF_INET;
|
||||
PRIVATE->saddr_.sin_port = htons(port_s);
|
||||
/*if (params[PIEthernet::Broadcast]) PRIVATE->saddr_.sin_addr.s_addr = INADDR_BROADCAST;
|
||||
else*/ PRIVATE->saddr_.sin_addr.s_addr = inet_addr(ip_s.data());
|
||||
PRIVATE->saddr_.sin_family = AF_INET;
|
||||
//piCout << "[PIEth] write to" << ip_s << ":" << port_s << "socket" << sock_s << max_size << "bytes ...";
|
||||
return ethSendto(sock_s, data, max_size, 0, (sockaddr * )&saddr_, sizeof(saddr_));
|
||||
return ethSendto(sock_s, data, max_size, 0, (sockaddr * )&PRIVATE->saddr_, sizeof(PRIVATE->saddr_));
|
||||
//piCout << "[PIEth] write to" << ip_s << ":" << port_s << "ok";
|
||||
case TCP_Client:
|
||||
if (connecting_) {
|
||||
memset(&addr_, 0, sizeof(addr_));
|
||||
memset(&PRIVATE->addr_, 0, sizeof(PRIVATE->addr_));
|
||||
parseAddress(path(), &ip_, &port_);
|
||||
addr_.sin_port = htons(port_);
|
||||
addr_.sin_addr.s_addr = inet_addr(ip_.data());
|
||||
addr_.sin_family = AF_INET;
|
||||
PRIVATE->addr_.sin_port = htons(port_);
|
||||
PRIVATE->addr_.sin_addr.s_addr = inet_addr(ip_.data());
|
||||
PRIVATE->addr_.sin_family = AF_INET;
|
||||
#ifdef QNX
|
||||
addr_.sin_len = sizeof(addr_);
|
||||
PRIVATE->addr_.sin_len = sizeof(*addr_);
|
||||
#endif
|
||||
//piCoutObj << "connect to " << ip << ":" << port_;
|
||||
connected_ = (::connect(sock, (sockaddr * )&addr_, sizeof(addr_)) == 0);
|
||||
connected_ = (::connect(sock, (sockaddr * )&PRIVATE->addr_, sizeof(PRIVATE->addr_)) == 0);
|
||||
if (!connected_)
|
||||
piCoutObj << "Can`t connect to " << ip_ << ":" << port_ << ", " << ethErrorString();
|
||||
opened_ = connected_;
|
||||
@@ -892,7 +956,6 @@ int PIEthernet::ethErrorCore() {
|
||||
#else
|
||||
return errno;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user