void TcpConnection::run() { try { //Poco::Net::SocketAddress address = _socket.peerAddress(); //std::string peer(_socket.peerAddress().toString().data()); //char hostname[48] = {0}; //memcpy(hostname, _socket.peerAddress().toString().c_str(), strlen(_socket.peerAddress().toString().c_str())); debug_log("connection established."); sendMessage(10001, (const byte*)"hello", 5); for (;;) { bool readable = _socket.poll(Poco::Timespan(30, 0), Poco::Net::Socket::SelectMode::SELECT_READ); if (readable == true && onReadable() == false) { return; } } } catch (Poco::Exception& e) { onShutdown(ShutdownReason::SR_EXCEPTION); } catch (...) { error_log("unknown exception."); } }
// async Unix send (has a Message struct in the start if transferOwnership) void WebSocket::write(char *data, size_t length, bool transferOwnership, void(*callback)(WebSocket webSocket, void *data, bool cancelled), void *callbackData) { uv_os_fd_t fd; uv_fileno((uv_handle_t *) p, &fd); ssize_t sent = 0; SocketData *socketData = (SocketData *) p->data; if (!socketData->messageQueue.empty()) { goto queueIt; } if (socketData->ssl) { sent = SSL_write(socketData->ssl, data, length); } else { sent = ::send(fd, data, length, MSG_NOSIGNAL); } if (sent == (int) length) { // everything was sent in one go! if (transferOwnership) { delete [] (data - sizeof(SocketData::Queue::Message)); } if (callback) { callback(p, callbackData, false); } } else { // not everything was sent if (sent == -1) { // check to see if any error occurred if (socketData->ssl) { int error = SSL_get_error(socketData->ssl, sent); if (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE) { goto queueIt; } } else { #ifdef _WIN32 if (WSAGetLastError() == WSAENOBUFS || WSAGetLastError() == WSAEWOULDBLOCK) { #else if (errno == EAGAIN || errno == EWOULDBLOCK) { #endif goto queueIt; } } // error sending! if (transferOwnership) { delete [] (data - sizeof(SocketData::Queue::Message)); } return; } else { queueIt: sent = std::max<ssize_t>(sent, 0); // queue the rest of the message! SocketData::Queue::Message *messagePtr; if (transferOwnership) { messagePtr = (SocketData::Queue::Message *) (data - sizeof(SocketData::Queue::Message)); messagePtr->data = data + sent; messagePtr->length = length - sent; messagePtr->nextMessage = nullptr; } else { // we need to copy the buffer messagePtr = (SocketData::Queue::Message *) new char[sizeof(SocketData::Queue::Message) + length - sent]; messagePtr->length = length - sent; messagePtr->data = ((char *) messagePtr) + sizeof(SocketData::Queue::Message); messagePtr->nextMessage = nullptr; memcpy(messagePtr->data, data + sent, messagePtr->length); } messagePtr->callback = callback; messagePtr->callbackData = callbackData; ((SocketData *) p->data)->messageQueue.push(messagePtr); // only start this if we just broke the 0 queue size! uv_poll_start(p, UV_WRITABLE | UV_READABLE, [](uv_poll_t *handle, int status, int events) { // handle all poll errors with forced disconnection if (status < 0) { WebSocket(handle).close(true, 1006); return; } // handle reads if available if (events & UV_READABLE) { onReadable(handle, status, events); if (!(events & UV_WRITABLE)) { return; } } SocketData *socketData = (SocketData *) handle->data; if (socketData->state == CLOSING) { if (uv_is_closing((uv_handle_t *) handle)) { return; } else { uv_poll_start(handle, UV_READABLE, onReadable); } } uv_os_fd_t fd; uv_fileno((uv_handle_t *) handle, &fd); do { SocketData::Queue::Message *messagePtr = socketData->messageQueue.front(); ssize_t sent; if (socketData->ssl) { sent = SSL_write(socketData->ssl, messagePtr->data, messagePtr->length); } else { sent = ::send(fd, messagePtr->data, messagePtr->length, MSG_NOSIGNAL); } if (sent == (int) messagePtr->length) { if (messagePtr->callback) { messagePtr->callback(handle, messagePtr->callbackData, false); } socketData->messageQueue.pop(); } else { if (sent == -1) { // check to see if any error occurred if (socketData->ssl) { int error = SSL_get_error(socketData->ssl, sent); if (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE) { return; } } else { #ifdef _WIN32 if (WSAGetLastError() == WSAENOBUFS || WSAGetLastError() == WSAEWOULDBLOCK) { #else if (errno == EAGAIN || errno == EWOULDBLOCK) { #endif return; } } // error sending! uv_poll_start(handle, UV_READABLE, onReadable); return; } else { // update the Message messagePtr->data += sent; messagePtr->length -= sent; return; } } } while (!socketData->messageQueue.empty()); // only receive when we have fully sent everything uv_poll_start(handle, UV_READABLE, onReadable); }); } }