📄 largedatagramout.cpp
字号:
/*************************************************************************** * Copyright (C) 2007 by Anistratov Oleg * * ower@users.sourceforge.net * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License version 2 * * as published by the Free Software Foundation; * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * ***************************************************************************/#include "largedatagramout.h"#include <QThread>#include "chatcore.h"LargeDatagramOut::LargeDatagramOut(QObject *parent) : QObject(parent), m_confirmed (false), m_inited (false), m_header (NULL), m_data (NULL), m_fragments (NULL), m_selfDestroyInterval(10 * 1000){ m_selfDestroyTimer = new QTimer(this); connect(m_selfDestroyTimer, SIGNAL(timeout()), this, SLOT(selfDestroy()));}//\*****************************************************************************LargeDatagramOut::~LargeDatagramOut(){ qDebug("[~LargeDatagramOut]: ID = %lu", (unsigned long)m_id); free(m_header); // we need free only m_header beckause m_data points to m_header + m_headerSize free(m_fragments);}//\*****************************************************************************void LargeDatagramOut::init(char* header, quint16 header_size, char* data , quint32 data_size , quint64 dest_uid, quint32 id){ m_id = id; m_header = header; m_data = data ; m_headerSize = header_size; m_dataSize = data_size; m_sizePerFragment = (MAX_PACKET_LEN - m_headerSize); m_rest = m_dataSize % m_sizePerFragment; m_totalFragments = m_dataSize / m_sizePerFragment + m_rest; m_fragmentsRemain = m_totalFragments; m_fragments = (char*)calloc(m_totalFragments + 1, 1);// + 1, beckause we need to send initialization packet m_inited = true; m_confirmed = true; m_destUid = dest_uid;}//\*****************************************************************************void LargeDatagramOut::init(char* header, quint16 header_size, const QString & filename, quint64 dest_uid, quint32 id){ m_id = id; m_header = header; m_data = NULL; m_headerSize = header_size; m_dataSize = 0; m_filename = filename; m_destUid = dest_uid; m_file.setFileName(filename); if(!m_file.open(QIODevice::ReadOnly)) { qWarning("[LargeDatagramOut::init]: Failed. couldn't open file %s for reading!\n", m_filename.toLocal8Bit().data()); emit wantDie(this); emit sendingCancelled(id); return; } if(m_file.handle() < 0) { qWarning("[LargeDatagramOut::init]: m_file.handle() < 0\n");// emit wantDie(this);// return; } m_fileSize = m_file.size(); m_sizePerFragment = (MAX_PACKET_LEN - m_headerSize); m_rest = m_fileSize % m_sizePerFragment; m_totalFragments = m_fileSize / m_sizePerFragment + m_rest; m_fragmentsRemain = m_totalFragments; m_fragments = (char*)calloc(m_totalFragments + 1, 1);// + 1, t.k. nado otoslat' esche i initsializir. paket! m_inited = true;}//\*****************************************************************************void LargeDatagramOut::prepareInitHeader(){ if(!m_inited) return; AbstractChatCore::setPacketId (m_header, m_id); AbstractChatCore::setFragmentSize(m_header, m_sizePerFragment); AbstractChatCore::setPacketNum (m_header, 0); AbstractChatCore::setMessageLen (m_header, m_totalFragments); // +61 MsgLen / TotalFragments / DataLen // FIXME !!!file size may be greater then quint32!!! if(!m_filename.isEmpty()) AbstractChatCore::setParametrsLen(m_header, m_fileSize); else AbstractChatCore::setParametrsLen(m_header, m_dataSize); // +65 ParametersLen / TotalSize / == 0}//\*****************************************************************************void LargeDatagramOut::sendNextFragment(QAbstractSocket* socket, quint16 port, char* buf){ quint32 num; quint32 i; quint32 size; int res = -1; QTcpSocket* tcp = qobject_cast<QTcpSocket*>(socket); QUdpSocket* udp = qobject_cast<QUdpSocket*>(socket); if(!m_fragmentsRemain) { if(m_selfDestroyTimer && (m_selfDestroyTimer->timerId() < 0)) { m_selfDestroyTimer->setSingleShot(true); m_selfDestroyTimer->start(m_selfDestroyInterval); } return; } // TODO optimizirovat' for(i = 0; i <= m_totalFragments; i++) if(m_fragments[i] == 0) break; num = i; if(num != 0 && !m_confirmed) return; if(num > m_totalFragments)// znachit net neotoslannyh fragmentov. i soobschenii o peresylke ne prihodilo return; size = writeFragment(buf, num); if(tcp) { AbstractChatCore::setPacketSize(buf, size); res = tcp->write(buf, size); tcp->flush(); } else if(udp) res = udp->writeDatagram(buf, size, QHostAddress(m_destUid), port); if(res < 0) qWarning("\n[LargeDatagramOut::sendNextFragment]: datagram send error !\n"); else { m_fragments[num] = 1; if(num) m_fragmentsRemain--; // esli vse otoslali - zhdem nekotoroe vremya zaprosov pereslat' zanovo fragmenty, // i esli zaprosa ne prihodit unichtozhaemsya if(!m_fragmentsRemain) { m_selfDestroyTimer->setSingleShot(true); m_selfDestroyTimer->start(m_selfDestroyInterval); } }}//\*****************************************************************************quint32 LargeDatagramOut::writeFragment(char* buf, quint32 num){ if(!m_inited || !buf || num > m_totalFragments) return 0; uint fragmentSize = m_sizePerFragment; if(num == m_totalFragments && m_rest) if(!m_filename.isEmpty()) fragmentSize = m_fileSize % m_sizePerFragment; else fragmentSize = m_dataSize % m_sizePerFragment; if(!num) { prepareInitHeader(); memcpy(buf, m_header, m_headerSize); if(!m_filename.isEmpty()) { QByteArray ba = m_filename.right(m_filename.size() - 1 - m_filename.lastIndexOf("/")).toUtf8(); catUS2str(buf + m_headerSize, ba.size()); memcpy(buf + m_headerSize + 2, ba.data(), ba.size()); return m_headerSize + 2 + ba.size(); } return m_headerSize; } AbstractChatCore::setParametrsLen(m_header, 0); // +65 ParametersLen / TotalSize / == 0 AbstractChatCore::setPacketNum (m_header, num); //PacketNUM AbstractChatCore::setMessageLen (m_header, m_sizePerFragment); // +61 MsgLen / TotalFragments / DataLen memcpy(buf, m_header, m_headerSize); if(!m_filename.isEmpty()) { m_file.seek((num - 1) * m_sizePerFragment); m_file.read(buf + m_headerSize, fragmentSize); return m_headerSize + fragmentSize; } memcpy(buf + m_headerSize, m_data + (m_sizePerFragment * (num - 1)), fragmentSize); return m_headerSize + fragmentSize;}//\*****************************************************************************void LargeDatagramOut::selfDestroy(){ qDebug("[LargeDatagramOut[%d]::selfDestroy]", m_id); emit wantDie(this);}//\*****************************************************************************void LargeDatagramOut::slot_confirmed(unsigned short ID){ if(m_id == ID) m_confirmed = true;}//\*****************************************************************************void LargeDatagramOut::fragmentsRequest(const char* dtgrm, quint16 len){// qDebug("[LargeDatagramOut::fragmentsRequest]"); quint32 i; quint32 shift; quint32 pars_len = AbstractChatCore::parametrsLen(dtgrm); shift = AbstractChatCore::compNameLen(dtgrm) + AbstractChatCore::protocolLen() + AbstractChatCore::userNameLen(dtgrm) + AbstractChatCore::messageLen(dtgrm) + AbstractChatCore::optionsLen(dtgrm); if(len - shift < pars_len) return; QByteArray pars(dtgrm + shift, pars_len); QByteArray buf; quint16 frags_len; const char* frags; if(!m_inited) return; buf = ChatCore::getParametr("FragmentsLen", pars); frags_len = str2US(buf.data()); qDebug("[LargeDatagramOut::fragmentsRequest]: fragments_len = %d", frags_len); buf = ChatCore::getParametr("FragmentsRequest", pars); frags = buf.constData(); qDebug("[LargeDatagramOut::fragmentsRequest]: fragmentsRemain before = %d", m_fragmentsRemain); for(i = 0; i < frags_len && i < m_totalFragments; i++) if(!frags[i]) { m_fragmentsRemain += m_fragments[i + 1]; m_fragments[i + 1] = 0; } qDebug("[LargeDatagramOut::fragmentsRequest]: fragmentsRemain after = %d", m_fragmentsRemain); if(m_fragmentsRemain) m_selfDestroyTimer->stop();}//\*****************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -