202 lines
4.7 KiB
C++
202 lines
4.7 KiB
C++
/*
|
|
PIP - Platform Independent Primitives
|
|
Ethernet, UDP
|
|
Copyright (C) 2011 Ivan Pelipenko peri4@rambler.ru
|
|
|
|
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
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "piethernet.h"
|
|
|
|
|
|
PIEthernet::PIEthernet(PIString ip, int port, void * data_, EthernetFunc slot): PIThread() {
|
|
piMonitor.ethernets++;
|
|
setPriority(piHigh);
|
|
data = data_;
|
|
ip_ = ip_s = ip;
|
|
port_ = port_s = port;
|
|
sock = sock_s = -1;
|
|
ret_func = slot;
|
|
tries = 0;
|
|
//buffer_ = new char[BUFFER_SIZE];
|
|
#ifdef WINDOWS
|
|
WSADATA wsaData;
|
|
WSAStartup(MAKEWORD(2, 2), &wsaData);
|
|
#endif
|
|
initSend();
|
|
}
|
|
|
|
|
|
PIEthernet::~PIEthernet() {
|
|
piMonitor.ethernets--;
|
|
terminate();
|
|
#ifdef WINDOWS
|
|
WSACleanup();
|
|
#endif
|
|
if (sock != -1) {
|
|
shutdown(sock, SHUT_RDWR);
|
|
#ifdef WINDOWS
|
|
closesocket(sock);
|
|
#else
|
|
close(sock);
|
|
#endif
|
|
sock = -1;
|
|
}
|
|
if (sock_s != -1) {
|
|
shutdown(sock_s, SHUT_RDWR);
|
|
#ifdef WINDOWS
|
|
closesocket(sock_s);
|
|
#else
|
|
close(sock_s);
|
|
#endif
|
|
sock_s = -1;
|
|
}
|
|
//if (buffer_ != 0) delete buffer_;
|
|
//buffer_ = 0;
|
|
}
|
|
|
|
|
|
void PIEthernet::terminate() {
|
|
if (!receiverInitialized()) return;
|
|
if (isRunning()) {
|
|
stop();
|
|
PIThread::terminate();
|
|
}
|
|
tries = 0;
|
|
/*if (sock != -1) {
|
|
shutdown(sock, SHUT_RDWR);
|
|
shutdown(sock, SHUT_RDWR);
|
|
close(sock);
|
|
sock = -1;
|
|
}
|
|
if (sock_s != -1) {
|
|
shutdown(sock_s, SHUT_RDWR);
|
|
close(sock_s);
|
|
sock_s = -1;
|
|
}*/
|
|
}
|
|
|
|
|
|
void PIEthernet::begin() {
|
|
if (!init()) stop();
|
|
}
|
|
|
|
|
|
void PIEthernet::run() {
|
|
/*#ifdef WINDOWS
|
|
int addr_len = sizeof(sockaddr);
|
|
#else
|
|
socklen_t addr_len = sizeof(sockaddr_storage);
|
|
#endif*/
|
|
//cout << "[PIEthernet] reading from " << &addr_ << endl;
|
|
readed = recv(sock, buffer_, BUFFER_SIZE, 0/*, (sockaddr * )&addr_, &addr_len*/);
|
|
//cout << WSAGetLastError() << endl;
|
|
if (readed < 0) {
|
|
cout << "[PIEthernet] Error while reading, " << errorString() << endl;
|
|
//stop();
|
|
//init();
|
|
return;
|
|
}
|
|
if (ret_func != 0) ret_func(data, buffer_, readed);
|
|
}
|
|
|
|
|
|
void PIEthernet::end() {
|
|
terminate();
|
|
}
|
|
|
|
|
|
bool PIEthernet::init() {
|
|
addr_.sin_addr.s_addr = inet_addr(ip_.data());
|
|
addr_.sin_family = PF_INET;
|
|
addr_.sin_port = htons(port_);
|
|
#ifdef WINDOWS
|
|
closesocket(sock);
|
|
#else
|
|
close(sock);
|
|
#endif
|
|
sock = socket(PF_INET, SOCK_DGRAM, 0);
|
|
if (bind(sock, (sockaddr * )&addr_, sizeof(addr_)) == -1) {
|
|
tries++;
|
|
if (tries < 10) {
|
|
if (init()) {
|
|
tries = 0;
|
|
return true;
|
|
} else return false;
|
|
} else
|
|
cout << "[PIEthernet] Cant`t bind to " << ip_ << ":" << port_ << ", " << errorString() << endl;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
bool PIEthernet::initSend() {
|
|
#ifdef WINDOWS
|
|
closesocket(sock_s);
|
|
#else
|
|
close(sock_s);
|
|
#endif
|
|
sock_s = socket(PF_INET, SOCK_DGRAM, 0);
|
|
if (sock_s == -1) {
|
|
tries++;
|
|
if (tries < 10) {
|
|
if (init()) {
|
|
tries = 0;
|
|
return true;
|
|
} else return false;
|
|
} else
|
|
cout << "[PIEthernet] Unable to create socket, " << errorString() << endl;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
bool PIEthernet::send(PIString ip, int port, char * data, int size) {
|
|
if (sock_s == -1) {
|
|
//cout << "[PIEthernet] Can`t send to uninitialized socket" << endl;
|
|
return false;
|
|
}
|
|
saddr_.sin_port = htons(port);
|
|
saddr_.sin_addr.s_addr = inet_addr(ip.data());
|
|
saddr_.sin_family = PF_INET;
|
|
wrote = sendto(sock_s, data, size, 0, (sockaddr * )&saddr_, sizeof(saddr_));
|
|
if (wrote != size) {
|
|
//cout << "[PIEthernet] Error while sending" << endl;
|
|
return false;
|
|
}
|
|
//cout << "[PIEthernet] Wrote " << wrote << " bytes in " << devName << endl;
|
|
return true;
|
|
}
|
|
|
|
|
|
bool PIEthernet::send(char * data, int size) {
|
|
if (sock_s == -1) {
|
|
//cout << "[PIEthernet] Can`t send to uninitialized socket" << endl;
|
|
return false;
|
|
}
|
|
saddr_.sin_port = htons(port_s);
|
|
saddr_.sin_addr.s_addr = inet_addr(ip_s.data());
|
|
saddr_.sin_family = PF_INET;
|
|
//cout << "[PIEthernet] sending in " << sock_s << endl;
|
|
wrote = sendto(sock_s, data, size, 0, (sockaddr * )&saddr_, sizeof(saddr_));
|
|
if (wrote != size) {
|
|
//cout << "[PIEthernet] Error while sending" << endl;
|
|
return false;
|
|
}
|
|
//cout << "[PIEthernet] Wrote " << wrote << " bytes" << endl;
|
|
return true;
|
|
}
|