void Connection::write(uint8* buffer, uint16 size) { if(!m_connected) return; // send old buffer if we can't add more data if(m_sendBufferSize + size >= SEND_BUFFER_SIZE && m_sendEvent) m_sendEvent->execute(); // we can't send the data right away, otherwise we could create tcp congestion memcpy(m_sendBuffer + m_sendBufferSize, buffer, size); m_sendBufferSize += size; if(!m_sendEvent || m_sendEvent->isExecuted() || m_sendEvent->isCanceled()) { auto weakSelf = ConnectionWeakPtr(shared_from_this()); // wait 1 ms to do the real send m_sendEvent = g_dispatcher.scheduleEvent([=] { if(!weakSelf.lock()) return; //m_writeTimer.cancel(); asio::async_write(m_socket, asio::buffer(m_sendBuffer, m_sendBufferSize), std::bind(&Connection::onWrite, shared_from_this(), std::placeholders::_1, std::placeholders::_2)); m_writeTimer.expires_from_now(boost::posix_time::seconds(WRITE_TIMEOUT)); m_writeTimer.async_wait(std::bind(&Connection::onTimeout, shared_from_this(), std::placeholders::_1)); m_sendBufferSize = 0; }, SEND_INTERVAL); } }
void Connection::connect(const std::string& host, uint16 port, const std::function<void()>& connectCallback) { m_connected = false; m_connecting = true; m_error.clear(); m_connectCallback = connectCallback; asio::ip::tcp::resolver::query query(host, stdext::unsafe_cast<std::string>(port)); auto weakSelf = ConnectionWeakPtr(shared_from_this()); m_resolver.async_resolve(query, [=](const boost::system::error_code& error, asio::ip::tcp::resolver::iterator endpointIterator) { if(!weakSelf.lock()) return; m_readTimer.cancel(); if(!error) { m_socket.async_connect(*endpointIterator, std::bind(&Connection::onConnect, shared_from_this(), std::placeholders::_1)); m_readTimer.expires_from_now(boost::posix_time::seconds(READ_TIMEOUT)); m_readTimer.async_wait(std::bind(&Connection::onTimeout, shared_from_this(), std::placeholders::_1)); } else handleError(error); }); m_readTimer.expires_from_now(boost::posix_time::seconds(READ_TIMEOUT)); m_readTimer.async_wait(std::bind(&Connection::onTimeout, shared_from_this(), std::placeholders::_1)); }
UserConnection::UserConnection(Urho3D::Context* context, ConnectionPtr connection_) : Tundra::UserConnection(context), webSocketConnection(ConnectionWeakPtr(connection_)) { }