Logo Search packages:      
Sourcecode: kmess version File versions

bool P2PApplicationBase::writeP2PDataToFile ( const P2PMessage message,
QIODevice *  file 
) [protected, inherited]

Utility function to write P2P data to a file, also deals with message offsets.

When an error occurs, the required error message will be sent back to the other client.

While Windows Live Messenger does not allow messages to be out of order, this method explicitly allows it because WLM itself seams to send messages out of order in some cases when it's switching to the direct connection (likely error prone at slow systems).

Parameters:
message The P2P message with a file part.
file The file to output the data to.
Returns:
True if the data could be written to the file, false on error.

Definition at line 2336 of file p2papplicationbase.cpp.

References Application::CANCEL_FAILED, Application::getContactHandle(), P2PMessage::getData(), P2PMessage::getDataOffset(), P2PMessage::getDataSize(), Application::sendCancelMessage(), and P2PApplicationBase::sendP2PAckImpl().

Referenced by MsnObjectTransferP2P::gotData(), InkTransferP2P::gotData(), and FileTransferP2P::gotData().

{
  unsigned long offset = message.getDataOffset();

  // See if the offset should be changed,
  // and if so, update it.
  if( offset != (ulong)file->pos() && ! file->seek( offset ) )
  {
#ifdef KMESSDEBUG_APPLICATION
    kDebug() << "data is received out of order, updating file offset.";
#endif

    // File position was different and could not be changed..
    unsigned long fileSize = (quint32)file->size();

    // See if the offset is too far ahead.. (e.g. don't make us allocate 1GB)
    if( offset > ( fileSize + 100000 ) ) // ~100 kB
    {
      // TODO: allow contacts to resume at the correct byte position.
      kWarning() << "data offset is too far ahead of current end of file "
                    "(filepos=" << file->pos() <<
                    " eofpos="  << file->size() <<
                    " offset="  << offset <<
                    " contact=" << getContactHandle() <<
                    " session=" << getSessionID() <<
                    " class="   << metaObject()->className() <<
                    " action=send0x01)";
      sendP2PAckImpl( P2PMessage::MSN_FLAG_NEGATIVE_ACK );
      sendCancelMessage( CANCEL_FAILED );   // sends slp bye
      return false;
    }
    else if( offset <= fileSize )
    {
      // seek( offset ) should only fail if the offset is beyond the end of the file.
      // If this is not the case, moving within the file failed so abort.
      kWarning() << "file pointer could not be set to message offset "
                    "(filepos=" << file->pos() <<
                    " eofpos="  << file->size() <<
                    " offset="  << offset <<
                    " contact=" << getContactHandle() <<
                    " session=" << getSessionID() <<
                    " class="   << metaObject()->className() <<
                    " action=sendcancel)";
      sendCancelMessage( CANCEL_FAILED );
      return false;
    }

    // Create padding to write at the end
    unsigned long remainingSize = offset - fileSize;
    QByteArray padding( 4096, 0x00 );

    // Add padding at the end of the file.
    file->seek( fileSize );
    while( remainingSize > 0 )
    {
      if( file->write( padding, qMin( (unsigned long) 4096, remainingSize ) ) <= 0 )
      {
        break;
      }
      remainingSize -= 4096;
    }

    // Make sure the file position is correct now.
    if( offset != (ulong)file->pos() )
    {
      sendCancelMessage( CANCEL_FAILED );
      return false;
    }
  }


  // Offsets are correct.
  // Write the data to the file,
  qint64 status = file->write( message.getData(), message.getDataSize() );
  if( status == -1 )
  {
    kWarning() << "Failed to write the data to the file "
                  "(contact=" << getContactHandle() <<
                  " session=" << getSessionID() <<
                  " class="   << metaObject()->className() <<
                  " action=sendcancel)";

    sendCancelMessage(CANCEL_FAILED);
    return false;
  }

  // Indicate success!
  return true;
}


Generated by  Doxygen 1.6.0   Back to index