blocking PIEthernet write works

This commit is contained in:
2022-11-08 17:34:06 +03:00
parent 21fa3baf4e
commit d3dd3fb32b
3 changed files with 51 additions and 18 deletions

View File

@@ -418,7 +418,10 @@ bool PIEthernet::closeDevice() {
closeSocket(sock_s); closeSocket(sock_s);
while (!clients_.isEmpty()) while (!clients_.isEmpty())
delete clients_.back(); delete clients_.back();
if (ned) disconnected(false); if (ned) {
piCoutObj << "Disconnect on close";
disconnected(false);
}
return true; return true;
} }
@@ -579,13 +582,14 @@ bool PIEthernet::connect(bool threaded) {
#ifdef QNX #ifdef QNX
PRIVATE->addr_.sin_len = sizeof(PRIVATE->addr_); PRIVATE->addr_.sin_len = sizeof(PRIVATE->addr_);
#endif #endif
connecting_ = true;
connected_ = connectTCP(); connected_ = connectTCP();
connecting_ = false;
if (!connected_) { if (!connected_) {
piCoutObj << "Can`t connect to" << addr_r << "," << ethErrorString(); piCoutObj << "Can`t connect to" << addr_r << "," << ethErrorString();
} }
opened_ = connected_; opened_ = connected_;
if (connected_) { if (connected_) {
connecting_ = false;
connected(); connected();
} }
return connected_; return connected_;
@@ -728,7 +732,7 @@ ssize_t PIEthernet::readDevice(void * read_to, ssize_t max_size) {
errorClear(); errorClear();
#ifdef WINDOWS #ifdef WINDOWS
{ {
long wr = waitForEvent(FD_READ | FD_CLOSE); long wr = waitForEvent(PRIVATE->event, FD_READ | FD_CLOSE);
switch (wr) { switch (wr) {
case FD_READ: case FD_READ:
//piCout << "fd_read ..."; //piCout << "fd_read ...";
@@ -760,7 +764,7 @@ ssize_t PIEthernet::readDevice(void * read_to, ssize_t max_size) {
return -1; return -1;
} }
if (connected_) { if (connected_) {
//piCoutObj << "Disconnect on read," << ethErrorString(); piCoutObj << "Disconnect on read," << ethErrorString();
opened_ = connected_ = false; opened_ = connected_ = false;
closeSocket(sock); closeSocket(sock);
init(); init();
@@ -777,7 +781,7 @@ ssize_t PIEthernet::readDevice(void * read_to, ssize_t max_size) {
memset(&PRIVATE->raddr_, 0, sizeof(PRIVATE->raddr_)); memset(&PRIVATE->raddr_, 0, sizeof(PRIVATE->raddr_));
//piCoutObj << "read from" << path() << "..."; //piCoutObj << "read from" << path() << "...";
#ifdef WINDOWS #ifdef WINDOWS
long wr = waitForEvent(FD_READ | FD_CLOSE); long wr = waitForEvent(PRIVATE->event, FD_READ | FD_CLOSE);
switch (wr) { switch (wr) {
case FD_READ: case FD_READ:
//piCout << "fd_read ..."; //piCout << "fd_read ...";
@@ -829,7 +833,7 @@ ssize_t PIEthernet::writeDevice(const void * data, ssize_t max_size) {
#endif #endif
, (sockaddr * )&PRIVATE->saddr_, sizeof(PRIVATE->saddr_)); , (sockaddr * )&PRIVATE->saddr_, sizeof(PRIVATE->saddr_));
//piCout << "[PIEth] write to" << ip_s << ":" << port_s << "ok"; //piCout << "[PIEth] write to" << ip_s << ":" << port_s << "ok";
case TCP_Client: case TCP_Client: {
if (connecting_) { if (connecting_) {
memset(&PRIVATE->addr_, 0, sizeof(PRIVATE->addr_)); memset(&PRIVATE->addr_, 0, sizeof(PRIVATE->addr_));
addr_r.set(path()); addr_r.set(path());
@@ -850,15 +854,44 @@ ssize_t PIEthernet::writeDevice(const void * data, ssize_t max_size) {
} }
} }
if (!connected_) return -1; if (!connected_) return -1;
ret = ::send(sock, (const char *)data, max_size, 0); auto disconnectFunc = [this](){
if (ret < 0) {
piCoutObj << "Disconnect on write," << ethErrorString(); piCoutObj << "Disconnect on write," << ethErrorString();
opened_ = connected_ = false; opened_ = connected_ = false;
closeSocket(sock); closeSocket(sock);
init(); init();
disconnected(true); disconnected(true);
};
if (!isOptionSet(BlockingWrite)) {
ret = ::send(sock, (const char *)data, max_size, 0);
if (ret < 0) {
disconnectFunc();
return -1;
}
} else {
ssize_t remain_size = max_size;
const char * remain_data = (const char *)data;
while (remain_size > 0) {
int sr = ::send(sock, remain_data, remain_size, 0);
if (sr < 0) {
int err = ethErrorCore();
#ifdef WINDOWS
if (err == WSAEWOULDBLOCK) {
#else
if (err == EAGAIN || err == EWOULDBLOCK) {
#endif
piMinSleep();
//piCoutObj << "wait for write";
continue;
} else {
disconnectFunc();
return -1;
}
}
remain_data += sr;
remain_size -= sr;
}
} }
return ret; return ret;}
default: break; default: break;
} }
return -1; return -1;
@@ -897,7 +930,7 @@ void PIEthernet::server_func(void * eth) {
sockaddr_in client_addr; sockaddr_in client_addr;
socklen_t slen = sizeof(client_addr); socklen_t slen = sizeof(client_addr);
#ifdef WINDOWS #ifdef WINDOWS
long wr = ce->waitForEvent(FD_ACCEPT | FD_CLOSE); long wr = ce->waitForEvent(ce->PRIVATEWB->event, FD_ACCEPT | FD_CLOSE);
if (wr != FD_ACCEPT) { if (wr != FD_ACCEPT) {
piMSleep(10); piMSleep(10);
return; return;
@@ -954,7 +987,7 @@ bool PIEthernet::connectTCP() {
::connect(sock, (sockaddr * )&(PRIVATE->addr_), sizeof(PRIVATE->addr_)); ::connect(sock, (sockaddr * )&(PRIVATE->addr_), sizeof(PRIVATE->addr_));
//piCout << errorString(); //piCout << errorString();
#ifdef WINDOWS #ifdef WINDOWS
long wr = waitForEvent(FD_CONNECT | FD_CLOSE); long wr = waitForEvent(PRIVATE->event, FD_CONNECT | FD_CLOSE);
switch (wr) { switch (wr) {
case FD_CONNECT: case FD_CONNECT:
//piCout << "fd_connect ..."; //piCout << "fd_connect ...";
@@ -975,16 +1008,16 @@ bool PIEthernet::connectTCP() {
#ifdef WINDOWS #ifdef WINDOWS
long PIEthernet::waitForEvent(long mask) { long PIEthernet::waitForEvent(PIWaitEvent & event, long mask) {
if (!PRIVATE->event.isCreate() || sock < 0) return 0; if (!event.isCreate() || sock < 0) return 0;
WSAEventSelect(sock, PRIVATE->event.getEvent(), mask); WSAEventSelect(sock, event.getEvent(), mask);
if (PRIVATE->event.wait()) { if (event.wait()) {
//DWORD wr = WSAWaitForMultipleEvents(1, &(PRIVATE->read_event), FALSE, WSA_INFINITE, TRUE); //DWORD wr = WSAWaitForMultipleEvents(1, &(PRIVATE->read_event), FALSE, WSA_INFINITE, TRUE);
//piCout << "wait result" << wr; //piCout << "wait result" << wr;
//if (wr == WSA_WAIT_EVENT_0) { //if (wr == WSA_WAIT_EVENT_0) {
WSANETWORKEVENTS events; WSANETWORKEVENTS events;
memset(&events, 0, sizeof(events)); memset(&events, 0, sizeof(events));
WSAEnumNetworkEvents(sock, PRIVATE->event.getEvent(), &events); WSAEnumNetworkEvents(sock, event.getEvent(), &events);
//piCout << "wait result" << events.lNetworkEvents; //piCout << "wait result" << events.lNetworkEvents;
return events.lNetworkEvents; return events.lNetworkEvents;
} }

View File

@@ -503,7 +503,7 @@ private:
void setType(Type t, bool reopen = true); void setType(Type t, bool reopen = true);
bool connectTCP(); bool connectTCP();
#ifdef WINDOWS #ifdef WINDOWS
long waitForEvent(long mask); long waitForEvent(PIWaitEvent & event, long mask);
#endif #endif
static int ethErrorCore(); static int ethErrorCore();

View File

@@ -840,7 +840,7 @@ ssize_t PISerial::readDevice(void * read_to, ssize_t max_size) {
if (ret < 0) { if (ret < 0) {
int err = errno; int err = errno;
if (err == EBADF || err == EFAULT || err == EINVAL || err == EIO) { if (err == EBADF || err == EFAULT || err == EINVAL || err == EIO) {
softStopThreadedRead(); stopThreadedRead();
close(); close();
return 0; return 0;
} }