diff --git a/libs/main/io_devices/piethernet.cpp b/libs/main/io_devices/piethernet.cpp index 8106921e..551529df 100644 --- a/libs/main/io_devices/piethernet.cpp +++ b/libs/main/io_devices/piethernet.cpp @@ -418,7 +418,10 @@ bool PIEthernet::closeDevice() { closeSocket(sock_s); while (!clients_.isEmpty()) delete clients_.back(); - if (ned) disconnected(false); + if (ned) { + piCoutObj << "Disconnect on close"; + disconnected(false); + } return true; } @@ -579,13 +582,14 @@ bool PIEthernet::connect(bool threaded) { #ifdef QNX PRIVATE->addr_.sin_len = sizeof(PRIVATE->addr_); #endif + connecting_ = true; connected_ = connectTCP(); + connecting_ = false; if (!connected_) { piCoutObj << "Can`t connect to" << addr_r << "," << ethErrorString(); } opened_ = connected_; if (connected_) { - connecting_ = false; connected(); } return connected_; @@ -728,7 +732,7 @@ ssize_t PIEthernet::readDevice(void * read_to, ssize_t max_size) { errorClear(); #ifdef WINDOWS { - long wr = waitForEvent(FD_READ | FD_CLOSE); + long wr = waitForEvent(PRIVATE->event, FD_READ | FD_CLOSE); switch (wr) { case FD_READ: //piCout << "fd_read ..."; @@ -760,7 +764,7 @@ ssize_t PIEthernet::readDevice(void * read_to, ssize_t max_size) { return -1; } if (connected_) { - //piCoutObj << "Disconnect on read," << ethErrorString(); + piCoutObj << "Disconnect on read," << ethErrorString(); opened_ = connected_ = false; closeSocket(sock); init(); @@ -777,7 +781,7 @@ ssize_t PIEthernet::readDevice(void * read_to, ssize_t max_size) { memset(&PRIVATE->raddr_, 0, sizeof(PRIVATE->raddr_)); //piCoutObj << "read from" << path() << "..."; #ifdef WINDOWS - long wr = waitForEvent(FD_READ | FD_CLOSE); + long wr = waitForEvent(PRIVATE->event, FD_READ | FD_CLOSE); switch (wr) { case FD_READ: //piCout << "fd_read ..."; @@ -829,7 +833,7 @@ ssize_t PIEthernet::writeDevice(const void * data, ssize_t max_size) { #endif , (sockaddr * )&PRIVATE->saddr_, sizeof(PRIVATE->saddr_)); //piCout << "[PIEth] write to" << ip_s << ":" << port_s << "ok"; - case TCP_Client: + case TCP_Client: { if (connecting_) { memset(&PRIVATE->addr_, 0, sizeof(PRIVATE->addr_)); addr_r.set(path()); @@ -850,15 +854,44 @@ ssize_t PIEthernet::writeDevice(const void * data, ssize_t max_size) { } } if (!connected_) return -1; - ret = ::send(sock, (const char *)data, max_size, 0); - if (ret < 0) { + auto disconnectFunc = [this](){ piCoutObj << "Disconnect on write," << ethErrorString(); opened_ = connected_ = false; closeSocket(sock); init(); 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; } return -1; @@ -897,7 +930,7 @@ void PIEthernet::server_func(void * eth) { sockaddr_in client_addr; socklen_t slen = sizeof(client_addr); #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) { piMSleep(10); return; @@ -954,7 +987,7 @@ bool PIEthernet::connectTCP() { ::connect(sock, (sockaddr * )&(PRIVATE->addr_), sizeof(PRIVATE->addr_)); //piCout << errorString(); #ifdef WINDOWS - long wr = waitForEvent(FD_CONNECT | FD_CLOSE); + long wr = waitForEvent(PRIVATE->event, FD_CONNECT | FD_CLOSE); switch (wr) { case FD_CONNECT: //piCout << "fd_connect ..."; @@ -975,16 +1008,16 @@ bool PIEthernet::connectTCP() { #ifdef WINDOWS -long PIEthernet::waitForEvent(long mask) { - if (!PRIVATE->event.isCreate() || sock < 0) return 0; - WSAEventSelect(sock, PRIVATE->event.getEvent(), mask); - if (PRIVATE->event.wait()) { +long PIEthernet::waitForEvent(PIWaitEvent & event, long mask) { + if (!event.isCreate() || sock < 0) return 0; + WSAEventSelect(sock, event.getEvent(), mask); + if (event.wait()) { //DWORD wr = WSAWaitForMultipleEvents(1, &(PRIVATE->read_event), FALSE, WSA_INFINITE, TRUE); //piCout << "wait result" << wr; //if (wr == WSA_WAIT_EVENT_0) { WSANETWORKEVENTS events; memset(&events, 0, sizeof(events)); - WSAEnumNetworkEvents(sock, PRIVATE->event.getEvent(), &events); + WSAEnumNetworkEvents(sock, event.getEvent(), &events); //piCout << "wait result" << events.lNetworkEvents; return events.lNetworkEvents; } diff --git a/libs/main/io_devices/piethernet.h b/libs/main/io_devices/piethernet.h index e4648874..06b2dbb9 100644 --- a/libs/main/io_devices/piethernet.h +++ b/libs/main/io_devices/piethernet.h @@ -503,7 +503,7 @@ private: void setType(Type t, bool reopen = true); bool connectTCP(); #ifdef WINDOWS - long waitForEvent(long mask); + long waitForEvent(PIWaitEvent & event, long mask); #endif static int ethErrorCore(); diff --git a/libs/main/io_devices/piserial.cpp b/libs/main/io_devices/piserial.cpp index 79829a87..80bcd7b2 100644 --- a/libs/main/io_devices/piserial.cpp +++ b/libs/main/io_devices/piserial.cpp @@ -840,7 +840,7 @@ ssize_t PISerial::readDevice(void * read_to, ssize_t max_size) { if (ret < 0) { int err = errno; if (err == EBADF || err == EFAULT || err == EINVAL || err == EIO) { - softStopThreadedRead(); + stopThreadedRead(); close(); return 0; }