int TcpServer::processSend() { char *buffer; size_t size, sent; if (this->stopping) return 0; //TODO: I find it dramatic to iterate over all the connections. Maybe // I could create one eventFd for each connection to notify that // Data is ready to be sent. for (auto it = clientList.begin(); it != clientList.end(); it++) { TcpClient* client = it->second; while ((size = client->getTxData(&buffer)) > 0) { sent = client->getSocket()->send(buffer, size); if (sent == -1) { if (errno != EAGAIN) { LOG("write error. returned " << errno); abort(); } //if EAGAIN, we stop sending and we will get notified by EPOLL when we are ready again } else if (sent == 0) { client->onDisconnected(); clientList.erase(it); delete it->second; break; } else { // this will move us to the next buffer or further in current if partially sent. client->onDataSent(sent); } } // after we are finished sending the tx queue, check if the client is failed and close the connection if (client->mFailed) { client->getSocket()->close(); client->onDisconnected(); delete client; clientList.erase(it); } } }
int TcpServer::processReceive(int socket) { auto it = clientList.find(socket); if (it == clientList.end()) return 0; TcpClient* client = it->second; char tmpBuffer[1024]; //TODO: should get a buffer from a buffer pool size_t n = 1; while (n > 0) { if (this->stopping) { n = 0; break; } n = client->getSocket()->read((char*)&tmpBuffer[0], 1024); if (n == 0) { client->onDisconnected(); clientList.erase(it); delete client; } else if (n == -1) { n = 0; if (errno == ECONNRESET) { client->onDisconnected(); clientList.erase(it); delete client; } else { if (errno != EAGAIN) { LOG("Read error. Returned " << errno); abort(); } } break; } else { client->onReceive((char*)&tmpBuffer[0], n); } } return n; }