/* PIP - Platform Independent Primitives Ethernet, UDP Copyright (C) 2011 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 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 . */ #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; }