29.04.2014 - Version 0.4.0_prealpha. PICodeParser, namespace PICodeInfo, new tool "pip_cmg" in dir "code_model_generator". New feature in PIIODevice - "createFromFullPath", all parameters of all I/O devices now works with PIObjects`s properties.
This commit is contained in:
105
piethernet.cpp
105
piethernet.cpp
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Ethernet, UDP/TCP Broadcast/Multicast
|
||||
Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com
|
||||
Copyright (C) 2014 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
|
||||
@@ -38,58 +38,60 @@
|
||||
*
|
||||
*
|
||||
* \section PIEthernet_sec2 UDP
|
||||
* User Datagram Protocol
|
||||
* User Datagram Protocol
|
||||
*
|
||||
* \section PIEthernet_sec3 TCP
|
||||
* Transmission Control Protocol
|
||||
*
|
||||
* */
|
||||
|
||||
REGISTER_DEVICE(PIEthernet);
|
||||
|
||||
|
||||
PIEthernet::PIEthernet(): PIIODevice("", ReadWrite) {
|
||||
piMonitor.ethernets++;
|
||||
setPriority(piHigh);
|
||||
type_ = UDP;
|
||||
ip_ = ip_s = "";
|
||||
port_ = port_s = 0;
|
||||
sock = sock_s = -1;
|
||||
connected_ = connecting_ = false;
|
||||
params = PIEthernet::ReuseAddress;
|
||||
server_thread_.setData(this);
|
||||
setThreadedReadBufferSize(65536);
|
||||
if (type_ != UDP) init();
|
||||
setPriority(piHigh);
|
||||
setType(UDP);
|
||||
setParameters(PIEthernet::ReuseAddress);
|
||||
//if (type_ != UDP) init();
|
||||
}
|
||||
|
||||
|
||||
PIEthernet::PIEthernet(PIEthernet::Type type, const PIString & ip_port, const PIFlags<PIEthernet::Parameters> params_): PIIODevice(ip_port, ReadWrite) {
|
||||
PIEthernet::PIEthernet(PIEthernet::Type type_, const PIString & ip_port, const PIFlags<PIEthernet::Parameters> params_): PIIODevice(ip_port, ReadWrite) {
|
||||
piMonitor.ethernets++;
|
||||
setPriority(piHigh);
|
||||
type_ = type;
|
||||
parseAddress(ip_port, &ip_, &port_);
|
||||
ip_s = "";
|
||||
port_s = 0;
|
||||
sock = sock_s = -1;
|
||||
connected_ = connecting_ = false;
|
||||
params = params_;
|
||||
server_thread_.setData(this);
|
||||
setThreadedReadBufferSize(65536);
|
||||
setPriority(piHigh);
|
||||
setType(type_);
|
||||
setParameters(params_);
|
||||
if (type_ != UDP) init();
|
||||
}
|
||||
|
||||
|
||||
PIEthernet::PIEthernet(int sock_, PIString ip_port): PIIODevice("", ReadWrite) {
|
||||
piMonitor.ethernets++;
|
||||
setPriority(piHigh);
|
||||
type_ = TCP_Client;
|
||||
path_ = ip_port;
|
||||
parseAddress(ip_port, &ip_s, &port_s);
|
||||
sock = sock_;
|
||||
sock_s = -1;
|
||||
server_thread_.setData(this);
|
||||
params = PIEthernet::ReuseAddress;
|
||||
init_ = opened_ = connected_ = true;
|
||||
connecting_ = false;
|
||||
server_thread_.setData(this);
|
||||
setParameters(PIEthernet::ReuseAddress);
|
||||
setThreadedReadBufferSize(65536);
|
||||
setPriority(piHigh);
|
||||
setType(TCP_Client);
|
||||
setPath(ip_port);
|
||||
}
|
||||
|
||||
|
||||
@@ -114,7 +116,7 @@ bool PIEthernet::init() {
|
||||
#else
|
||||
int so = 1;
|
||||
#endif
|
||||
if (type_ == UDP) {
|
||||
if (type() == UDP) {
|
||||
st = SOCK_DGRAM;
|
||||
pr = IPPROTO_UDP;
|
||||
} else {
|
||||
@@ -122,7 +124,7 @@ bool PIEthernet::init() {
|
||||
pr = IPPROTO_TCP;
|
||||
}
|
||||
#ifdef WINDOWS
|
||||
if (type_ == UDP) flags = WSA_FLAG_MULTIPOINT_C_LEAF | WSA_FLAG_MULTIPOINT_D_LEAF;
|
||||
if (type() == UDP) flags = WSA_FLAG_MULTIPOINT_C_LEAF | WSA_FLAG_MULTIPOINT_D_LEAF;
|
||||
sock = WSASocket(AF_INET, st, pr, NULL, 0, flags);
|
||||
sock_s = WSASocket(AF_INET, st, pr, NULL, 0, WSA_FLAG_OVERLAPPED);
|
||||
#else
|
||||
@@ -133,6 +135,7 @@ bool PIEthernet::init() {
|
||||
piCoutObj << "Can`t create socket, " << ethErrorString();
|
||||
return false;
|
||||
}
|
||||
PIFlags<Parameters> params = parameters();
|
||||
#ifndef WINDOWS
|
||||
timeval to;
|
||||
to.tv_sec = 10;
|
||||
@@ -160,14 +163,15 @@ void PIEthernet::parseAddress(const PIString & ipp, PIString * ip, int * port) {
|
||||
bool PIEthernet::openDevice() {
|
||||
if (connected_) return true;
|
||||
init();
|
||||
if (sock == -1 || path_.isEmpty()) return false;
|
||||
parseAddress(path_, &ip_, &port_);
|
||||
if (type_ != UDP)
|
||||
if (sock == -1 || path().isEmpty()) return false;
|
||||
parseAddress(path(), &ip_, &port_);
|
||||
if (type() != UDP)
|
||||
return true;
|
||||
//piCout << "bind to" << (params[PIEthernet::Broadcast] ? "bc" : ip_) << ":" << port_ << " ...";
|
||||
memset(&addr_, 0, sizeof(addr_));
|
||||
addr_.sin_family = AF_INET;
|
||||
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());
|
||||
#ifdef QNX
|
||||
@@ -218,10 +222,17 @@ void PIEthernet::closeSocket(int & sd) {
|
||||
}
|
||||
|
||||
|
||||
void PIEthernet::setParameter(PIEthernet::Parameters parameter, bool on) {
|
||||
PIFlags<Parameters> cp = (PIFlags<Parameters>)(property("parameters").toInt());
|
||||
cp.setFlag(parameter, on);
|
||||
setParameters(cp);
|
||||
}
|
||||
|
||||
|
||||
bool PIEthernet::joinMulticastGroup(const PIString & group) {
|
||||
if (sock == -1) init();
|
||||
if (sock == -1) return false;
|
||||
if (type_ != UDP) {
|
||||
if (type() != UDP) {
|
||||
piCoutObj << "Only UDP sockets can join multicast groups";
|
||||
return false;
|
||||
}
|
||||
@@ -229,10 +240,12 @@ bool PIEthernet::joinMulticastGroup(const PIString & group) {
|
||||
if (mcast_queue.contains(group))
|
||||
return false;
|
||||
mcast_queue.enqueue(group);
|
||||
if (!mcast_groups.contains(group)) mcast_groups << group;
|
||||
return true;
|
||||
}
|
||||
PIFlags<Parameters> params = parameters();
|
||||
#ifdef WINDOWS
|
||||
parseAddress(path_, &ip_, &port_);
|
||||
parseAddress(path(), &ip_, &port_);
|
||||
memset(&addr_, 0, sizeof(addr_));
|
||||
addr_.sin_family = AF_INET;
|
||||
addr_.sin_addr.s_addr = inet_addr(group.data());
|
||||
@@ -243,12 +256,15 @@ bool PIEthernet::joinMulticastGroup(const PIString & group) {
|
||||
piCoutObj << "Can`t join multicast group " << group << ", " << ethErrorString();
|
||||
return false;
|
||||
}
|
||||
if (ret != sock) leafs.insert(group, ret);
|
||||
if (ret != sock) {
|
||||
leafs.insert(group, ret);
|
||||
if (!mcast_groups.contains(group)) mcast_groups << group;
|
||||
}
|
||||
#else
|
||||
# ifndef QNX
|
||||
if (!params[Broadcast])
|
||||
piCoutObj << "Warning: \"Broadcast\" parameter not set, \"joinMulticastGroup(\"" << group << "\")\" may be useless!";
|
||||
parseAddress(path_, &ip_, &port_);
|
||||
parseAddress(path(), &ip_, &port_);
|
||||
struct ip_mreqn mreq;
|
||||
memset(&mreq, 0, sizeof(mreq));
|
||||
mreq.imr_ifindex = 0;
|
||||
@@ -267,6 +283,7 @@ bool PIEthernet::joinMulticastGroup(const PIString & group) {
|
||||
piCoutObj << "Can`t join multicast group " << group << ", " << ethErrorString();
|
||||
return false;
|
||||
}
|
||||
if (!mcast_groups.contains(group)) mcast_groups << group;
|
||||
# endif
|
||||
#endif
|
||||
return true;
|
||||
@@ -276,19 +293,21 @@ bool PIEthernet::joinMulticastGroup(const PIString & group) {
|
||||
bool PIEthernet::leaveMulticastGroup(const PIString & group) {
|
||||
if (sock == -1) init();
|
||||
if (sock == -1) return false;
|
||||
if (type_ != UDP) {
|
||||
if (type() != UDP) {
|
||||
piCoutObj << "Only UDP sockets can leave multicast groups";
|
||||
return false;
|
||||
}
|
||||
PIFlags<Parameters> params = parameters();
|
||||
#ifdef WINDOWS
|
||||
SOCKET s = leafs[group];
|
||||
if (s != SOCKET()) {
|
||||
leafs.erase(group);
|
||||
closesocket(s);
|
||||
mcast_groups.removeAll(group);
|
||||
}
|
||||
#else
|
||||
# ifndef QNX
|
||||
parseAddress(path_, &ip_, &port_);
|
||||
parseAddress(path(), &ip_, &port_);
|
||||
struct ip_mreqn mreq;
|
||||
memset(&mreq, 0, sizeof(mreq));
|
||||
if (params[PIEthernet::Broadcast]) mreq.imr_address.s_addr = INADDR_ANY;
|
||||
@@ -299,6 +318,7 @@ bool PIEthernet::leaveMulticastGroup(const PIString & group) {
|
||||
piCoutObj << "Can`t leave multicast group " << group << ", " << ethErrorString();
|
||||
return false;
|
||||
}
|
||||
mcast_groups.removeAll(group);
|
||||
#endif
|
||||
#endif
|
||||
return true;
|
||||
@@ -330,7 +350,7 @@ bool PIEthernet::connect() {
|
||||
bool PIEthernet::listen() {
|
||||
if (sock == -1) init();
|
||||
if (sock == -1) return false;
|
||||
parseAddress(path_, &ip_, &port_);
|
||||
parseAddress(path(), &ip_, &port_);
|
||||
memset(&addr_, 0, sizeof(addr_));
|
||||
addr_.sin_port = htons(port_);
|
||||
addr_.sin_addr.s_addr = inet_addr(ip_.data());
|
||||
@@ -367,7 +387,7 @@ int PIEthernet::read(void * read_to, int max_size) {
|
||||
sockaddr_in client_addr;
|
||||
socklen_t slen = sizeof(client_addr);
|
||||
//piCoutObj << "read from " << ip_ << ":" << port_ << endl;
|
||||
switch (type_) {
|
||||
switch (type()) {
|
||||
case TCP_SingleTCP:
|
||||
::listen(sock, 64);
|
||||
s = accept(sock, (sockaddr * )&client_addr, &slen);
|
||||
@@ -382,7 +402,7 @@ int PIEthernet::read(void * read_to, int max_size) {
|
||||
case TCP_Client:
|
||||
if (connecting_) {
|
||||
memset(&addr_, 0, sizeof(addr_));
|
||||
parseAddress(path_, &ip_, &port_);
|
||||
parseAddress(path(), &ip_, &port_);
|
||||
addr_.sin_port = htons(port_);
|
||||
addr_.sin_addr.s_addr = inet_addr(ip_.data());
|
||||
addr_.sin_family = AF_INET;
|
||||
@@ -450,7 +470,7 @@ int PIEthernet::write(const void * data, int max_size) {
|
||||
}
|
||||
//piCoutObj << "sending to " << ip_s << ":" << port_s << " " << max_size << " bytes";
|
||||
int ret = 0;
|
||||
switch (type_) {
|
||||
switch (type()) {
|
||||
case TCP_SingleTCP:
|
||||
memset(&addr_, 0, sizeof(addr_));
|
||||
addr_.sin_port = htons(port_s);
|
||||
@@ -486,7 +506,7 @@ int PIEthernet::write(const void * data, int max_size) {
|
||||
case TCP_Client:
|
||||
if (connecting_) {
|
||||
memset(&addr_, 0, sizeof(addr_));
|
||||
parseAddress(path_, &ip_, &port_);
|
||||
parseAddress(path(), &ip_, &port_);
|
||||
addr_.sin_port = htons(port_);
|
||||
addr_.sin_addr.s_addr = inet_addr(ip_.data());
|
||||
addr_.sin_family = AF_INET;
|
||||
@@ -517,7 +537,7 @@ void PIEthernet::server_func(void * eth) {
|
||||
socklen_t slen = sizeof(client_addr);
|
||||
int s = accept(ce->sock, (sockaddr * )&client_addr, &slen);
|
||||
if (s == -1) {
|
||||
if (ce->debug_) piCout << "[PIEthernet] Can`t accept new connection, " << ethErrorString();
|
||||
if (ce->debug()) piCout << "[PIEthernet] Can`t accept new connection, " << ethErrorString();
|
||||
return;
|
||||
}
|
||||
PIString ip(inet_ntoa(client_addr.sin_addr));
|
||||
@@ -543,6 +563,27 @@ bool PIEthernet::configureDevice(const void * e_main, const void * e_parent) {
|
||||
}
|
||||
|
||||
|
||||
void PIEthernet::configureFromFullPath(const PIString & full_path) {
|
||||
PIStringList pl = full_path.split(":");
|
||||
bool mcast = false;
|
||||
for (int i = 0; i < pl.size_s(); ++i) {
|
||||
PIString p(pl[i]);
|
||||
switch (i) {
|
||||
case 0:
|
||||
p = p.toLowerCase();
|
||||
if (p == "udp") setType(UDP);
|
||||
if (p == "tcp") setType(TCP_Client);
|
||||
break;
|
||||
case 1: setReadIP(p); break;
|
||||
case 2: setReadPort(p.toInt()); break;
|
||||
}
|
||||
if (i <= 2) continue;
|
||||
if (i % 2 == 1) {if (p.toLowerCase() == "mcast") mcast = true;}
|
||||
else {if (mcast) {joinMulticastGroup(p); mcast = false;}}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PIEthernet::InterfaceList PIEthernet::interfaces() {
|
||||
PIEthernet::InterfaceList il;
|
||||
Interface ci;
|
||||
|
||||
Reference in New Issue
Block a user