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:
2015-03-10 10:13:18 +00:00
parent b1f651ab62
commit c11bc3b3b8
697 changed files with 18150 additions and 18839 deletions

View File

@@ -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
}