15.10.2012 - version 0.2.0 - PIIODevice - base of file, ethernet, serial and packets extractor. PIEthernet now support also TCP (client and server). PIConsole now can align labels in each column individually.
This commit is contained in:
309
piethernet.cpp
Normal file → Executable file
309
piethernet.cpp
Normal file → Executable file
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Ethernet, UDP
|
||||
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com
|
||||
Copyright (C) 2012 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
|
||||
@@ -20,182 +20,217 @@
|
||||
#include "piethernet.h"
|
||||
|
||||
|
||||
PIEthernet::PIEthernet(PIString ip, int port, void * data_, EthernetFunc slot): PIThread() {
|
||||
PIEthernet::PIEthernet(void * data, ReadRetFunc slot): PIIODevice("", ReadWrite) {
|
||||
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];
|
||||
type_ = UDP;
|
||||
ret_data_ = data;
|
||||
ip_ = ip_s = "";
|
||||
port_ = port_s = 0;
|
||||
sock = -1;
|
||||
ret_func_ = slot;
|
||||
connected_ = false;
|
||||
server_thread_.setData(this);
|
||||
setThreadedReadBufferSize(65536);
|
||||
#ifdef WINDOWS
|
||||
WSADATA wsaData;
|
||||
WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
#endif
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
PIEthernet::PIEthernet(PIEthernet::Type type, void * data, ReadRetFunc slot): PIIODevice("", ReadWrite) {
|
||||
piMonitor.ethernets++;
|
||||
setPriority(piHigh);
|
||||
type_ = type;
|
||||
ret_data_ = data;
|
||||
ip_ = ip_s = "";
|
||||
port_ = port_s = 0;
|
||||
sock = -1;
|
||||
ret_func_ = slot;
|
||||
connected_ = false;
|
||||
server_thread_.setData(this);
|
||||
setThreadedReadBufferSize(65536);
|
||||
#ifdef WINDOWS
|
||||
WSADATA wsaData;
|
||||
WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
#endif
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
PIEthernet::PIEthernet(int sock_, PIString ip_port): PIIODevice("", ReadWrite) {
|
||||
piMonitor.ethernets++;
|
||||
setPriority(piHigh);
|
||||
type_ = TCP_Client;
|
||||
parseAddress(ip_port, &ip_s, &port_s);
|
||||
sock = sock_;
|
||||
server_thread_.setData(this);
|
||||
init_ = opened_ = connected_ = true;
|
||||
setThreadedReadBufferSize(65536);
|
||||
#ifdef WINDOWS
|
||||
WSADATA wsaData;
|
||||
WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
#endif
|
||||
initSend();
|
||||
}
|
||||
|
||||
|
||||
PIEthernet::~PIEthernet() {
|
||||
piMonitor.ethernets--;
|
||||
terminate();
|
||||
if (server_thread_.isRunning()) server_thread_.terminate();
|
||||
closeSocket(sock);
|
||||
#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() {
|
||||
//cout << "init " << type_ << endl;
|
||||
closeSocket(sock);
|
||||
int st = 0, so = 1;
|
||||
if (type_ == UDP) st = SOCK_DGRAM;
|
||||
if (type_ == TCP_Client || type_ == TCP_Server) st = SOCK_STREAM;
|
||||
sock = socket(PF_INET, st, 0);
|
||||
if (sock == -1) {
|
||||
piCout << "[PIEthernet] Cant`t create socket, " << errorString() << endl;
|
||||
return false;
|
||||
}
|
||||
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &so, sizeof(so));
|
||||
//fcntl(sock, F_SETFL, 0/*O_NONBLOCK*/);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void PIEthernet::parseAddress(const PIString & ipp, PIString * ip, int * port) {
|
||||
if (ip != 0) *ip = ipp.left(ipp.find(":"));
|
||||
if (port != 0) *port = ipp.right(ipp.length() - ipp.find(":") - 1).toInt();
|
||||
}
|
||||
|
||||
|
||||
bool PIEthernet::openDevice() {
|
||||
if (connected_) return true;
|
||||
if (sock == -1) init();
|
||||
if (sock == -1) return false;
|
||||
//cout << " bind to " << path_ << " ..." <<endl;
|
||||
parseAddress(path_, &ip_, &port_);
|
||||
addr_.sin_port = htons(port_);
|
||||
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);
|
||||
//cout << "openDevice\n";
|
||||
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;
|
||||
piCout << "[PIEthernet] Cant`t bind to " << ip_ << ":" << port_ << ", " << errorString() << endl;
|
||||
return false;
|
||||
}
|
||||
//cout << "!" << endl;
|
||||
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;
|
||||
}
|
||||
bool PIEthernet::closeDevice() {
|
||||
//cout << "close\n";
|
||||
if (sock != -1) shutdown(sock, SHUT_RDWR);
|
||||
closeSocket(sock);
|
||||
piForeach (PIEthernet * i, clients_)
|
||||
delete i;
|
||||
clients_.clear();
|
||||
if (server_thread_.isRunning()) server_thread_.terminate();
|
||||
connected_ = 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;
|
||||
bool PIEthernet::connect(PIString ip, int port) {
|
||||
if (sock == -1) return false;
|
||||
addr_.sin_port = htons(port);
|
||||
addr_.sin_addr.s_addr = inet_addr(ip.data());
|
||||
addr_.sin_family = PF_INET;
|
||||
//piCout << "[PIEthernet] connect to " << ip << ":" << port << endl;
|
||||
connected_ = (::connect(sock, (sockaddr * )&addr_, sizeof(addr_)) == 0);
|
||||
if (!connected_)
|
||||
piCout << "[PIEthernet] Cant`t connect to " << ip << ":" << port << ", " << errorString() << endl;
|
||||
opened_ = connected_;
|
||||
return connected_;
|
||||
}
|
||||
|
||||
|
||||
bool PIEthernet::listen() {
|
||||
if (sock == -1) init();
|
||||
if (sock == -1) return false;
|
||||
parseAddress(path_, &ip_, &port_);
|
||||
addr_.sin_port = htons(port_);
|
||||
addr_.sin_addr.s_addr = inet_addr(ip_.data());
|
||||
addr_.sin_family = PF_INET;
|
||||
if (bind(sock, (sockaddr * )&addr_, sizeof(addr_)) == -1) {
|
||||
piCout << "[PIEthernet] Cant`t bind to " << ip_ << ":" << port_ << ", " << errorString() << 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;
|
||||
if (::listen(sock, 64) == -1) {
|
||||
piCout << "[PIEthernet] Can`t listen on "<< ip_ << ":" << port_ << ", " << errorString() << endl;
|
||||
return false;
|
||||
}
|
||||
//cout << "[PIEthernet] Wrote " << wrote << " bytes in " << devName << endl;
|
||||
//piCout << "[PIEthernet] listen on " << ip_ << ":" << port_ << endl;
|
||||
server_thread_.start(server_func);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool PIEthernet::send(uchar * data, int size) {
|
||||
if (sock_s == -1) {
|
||||
//cout << "[PIEthernet] Can`t send to uninitialized socket" << endl;
|
||||
return false;
|
||||
int PIEthernet::read(void * read_to, int max_size) {
|
||||
//cout << "read " << sock << endl;
|
||||
if (sock == -1) init();
|
||||
if (sock == -1) return -1;
|
||||
//piCout << "[PIEthernet] read from " << ip_ << ":" << port_ << endl;
|
||||
switch (type_) {
|
||||
case UDP: case TCP_Client:
|
||||
return recv(sock, read_to, max_size, 0);
|
||||
//return ::read(sock, read_to, max_size);
|
||||
default: break;
|
||||
//return ::read(sock, (char * )read_to, max_size);
|
||||
}
|
||||
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;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int PIEthernet::write(const void * data, int max_size) {
|
||||
if (sock == -1) init();
|
||||
if (sock == -1 || !isWriteable()) {
|
||||
//piCout << "[PIEthernet] Can`t send to uninitialized socket" << endl;
|
||||
return -1;
|
||||
}
|
||||
//piCout << "[PIEthernet] sending to " << ip_s << ":" << port_s << " " << max_size << " bytes" << endl;
|
||||
switch (type_) {
|
||||
case UDP:
|
||||
saddr_.sin_port = htons(port_s);
|
||||
saddr_.sin_addr.s_addr = inet_addr(ip_s.data());
|
||||
saddr_.sin_family = PF_INET;
|
||||
return sendto(sock, data, max_size, 0, (sockaddr * )&saddr_, sizeof(saddr_));
|
||||
case TCP_Client:
|
||||
return ::write(sock, data, max_size);
|
||||
default: break;
|
||||
//return ::read(sock, read_to, max_size);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void PIEthernet::server_func(void * eth) {
|
||||
PIEthernet * ce = (PIEthernet * )eth;
|
||||
sockaddr_in client_addr;
|
||||
socklen_t slen = sizeof(client_addr);
|
||||
int s;
|
||||
s = accept(ce->sock, (sockaddr * )&client_addr, &slen);
|
||||
if (s == -1) {
|
||||
piCout << "[PIEthernet] Cant`t accept new connection, " << errorString() << endl;
|
||||
return;
|
||||
}
|
||||
PIString ip(inet_ntoa(client_addr.sin_addr));
|
||||
ip += ":" + PIString::fromNumber(htons(client_addr.sin_port));
|
||||
ce->clients_ << new PIEthernet(s, ip);
|
||||
cout << "connected " << ip << endl;
|
||||
//char d[256];
|
||||
//cout << " recv " << recv(s, d, 256, 0) << endl;
|
||||
//cout << recv(ce->clients_.back()->sock, d, 256, 0) << endl;
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user