/*! Sends to connected \a socket any packet writes still in buffer. This method is usually called prior to disconnection to ensure all data, including error messages have been sent. */ void cAsyncNetIO::flush( QSocketDevice* socket ) { iterator it = buffers.find( socket ); if ( it != buffers.end() ) flushWriteBuffer( it.data() ); }
//**************************************************************************************************** void writebuffer_t::issueWrites(){ //We issue writes from the WB only if the MSHR does NOT contain any LD entries - MSHR LDs // have priority over us (note that the MSHR does NOT count Ifetch entries!) if(m_use_write_buffer){ ASSERT(m_id < system_t::inst->m_numSMTProcs); int mshr_entry_count = system_t::inst->m_seq[m_id]->getRubyCache()->getMSHRcount(); if(mshr_entry_count == 0){ flushWriteBuffer(); } } }
//*************************************************************************************************** void writebuffer_t::Wakeup( void ) { #ifdef DEBUG_WRITE_BUFFER DEBUG_OUT("\n****writebuffer_t: Wakeup CALLED cycle[%d]!\n",m_event_queue->getCycle()); print(); #endif //reset is scheduled flag m_is_scheduled = false; // DEBUG_OUT("***Wakeup called cycle[%d]\n",m_event_queue->getCycle()); flushWriteBuffer(); return; }
/*! \internal The thread's execution loop for AsyncNetIO */ void cAsyncNetIO::run() throw() { while ( !canceled() ) { mapsMutex.lock(); // do not disturb me here. for ( const_iterator it( buffers.begin() ); it != buffers.end(); ++it ) { // Read all avaliable data. char buf[4096]; cAsyncNetIOPrivate* d = it.data(); // Check if the socket is valid if ( !d->socket->isValid() ) continue; // Let it in the queue until it's taken out by the closed-collector // Try to get the UO Header somehow if ( !d->skippedUOHeader ) { int nread = d->socket->readBlock( buf, 4 - d->rsize ); if ( nread > 0 ) { QByteArray* a = new QByteArray( nread ); memcpy( a->data(), buf, nread ); d->rba.append( a ); d->rsize += nread; if ( d->rsize == 4 ) { char temp[4]; d->consumeReadBuf( 4, temp ); d->skippedUOHeader = true; d->seed = ( ( temp[0] & 0xFF ) << 24 ) | ( ( temp[1] & 0xFF ) << 16 ) | ( ( temp[2] & 0xFF ) << 8 ) | ( ( temp[3] & 0xFF ) ); // Only 0xFFFFFFFF seed allowed for !d->login if ( !d->login && d->seed != 0xFFFFFFFF ) { d->writeBlock( "\x82\x04", 2 ); flushWriteBuffer( d ); d->socket->close(); continue; } } } else if ( nread == 0 ) { d->socket->close(); } } else { int nread = d->socket->readBlock( buf, sizeof( buf ) ); if ( nread > 0 ) { // If we have an encryption object already // then decrypt the buffer before storing it if ( d->encryption ) d->encryption->clientDecrypt( &buf[0], nread ); QByteArray* a = new QByteArray( nread ); memcpy( a->data(), buf, nread ); d->rba.append( a ); d->rsize += nread; // We need to use the read buffer as a temporary buffer // for encrypted data if we didn't receive all we need if ( !d->encryption ) { // Gameserver Encryption if ( !d->login && d->rsize >= 65 ) { // The 0x91 packet is 65 byte nread = d->rsize; d->consumeReadBuf( d->rsize, &buf[0] ); // This should be no encryption if ( buf[0] == '\x91' && buf[1] == '\xFF' && buf[2] == '\xFF' && buf[3] == '\xFF' && buf[4] == '\xFF' ) { // Is no Encryption allowed? if ( !Config::instance()->allowUnencryptedClients() ) { // Send a communication problem message to this socket d->writeBlock( "\x82\x04", 2 ); flushWriteBuffer( d ); d->socket->close(); continue; } d->encryption = new cNoEncryption; } else { cGameEncryption* crypt = new cGameEncryption; crypt->init( 0xFFFFFFFF ); // Seed is fixed anyway d->encryption = crypt; } } // LoginServer Encryption else if ( d->login && d->rsize >= 62 ) { // The 0x80 packet is 62 byte, but we want to have everything nread = d->rsize; d->consumeReadBuf( d->rsize, &buf[0] ); // Check if it could be *not* encrypted if ( buf[0] == '\x80' && buf[30] == '\x00' && buf[60] == '\x00' ) { // Is no Encryption allowed? if ( !Config::instance()->allowUnencryptedClients() ) { // Send a communication problem message to this socket d->writeBlock( "\x82\x04", 2 ); flushWriteBuffer( d ); d->socket->close(); continue; } d->encryption = new cNoEncryption; } else { cLoginEncryption* crypt = new cLoginEncryption; if ( !crypt->init( d->seed, &buf[0], nread ) ) { delete crypt; // Send a communication problem message to this socket d->writeBlock( "\x82\x04", 2 ); flushWriteBuffer( d ); d->socket->close(); continue; } d->encryption = crypt; } // It gets a bit tricky now, try to decode it with all // possible keys } // If we found an encryption let's decrypt what we got in our buffer if ( d->encryption ) { d->encryption->clientDecrypt( &buf[0], nread ); QByteArray* a = new QByteArray( nread ); memcpy( a->data(), buf, nread ); d->rba.append( a ); d->rsize += nread; } } } else if ( nread == 0 ) { d->socket->close(); } buildUOPackets( d ); } // Write data to socket flushWriteBuffer( d ); } mapsMutex.unlock(); //if( buffers.empty() ) // Disconnecting doesnt work for now waitCondition.wait( 40 ); // let's rest for a while } }