⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 largedatagram.cpp

📁 用qt4 编写的局域网聊天工具
💻 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 "largedatagram.h"#include "globals.h"#include <assert.h>#include <QHostAddress>#include "chatcore.h"#include "userinfo.h"LargeDatagram::LargeDatagram(quint64 IP, quint32 ID, QObject* parent) :  QObject(parent),  m_remain             (101),  m_isFile             (false),  m_fileInited         (false),  m_inited             (false),  m_srcIP              (IP),  m_datagramID         (ID),  m_lastFragmentNum    (0),  m_fragments          (NULL),  m_data               (NULL),  m_requestInterval    (1000),  m_selfDestroyInterval(60 * 1000){  qDebug("[LargeDatagram::LargeDatagram]: ID = %lu", (unsigned long)ID);  m_requestTimer        = new QTimer(this);  m_selfDestroyTimer    = new QTimer(this);  connect(m_requestTimer    , SIGNAL(timeout()), this, SLOT(slot_fragmentsRequest ()));  connect(m_selfDestroyTimer, SIGNAL(timeout()), this, SLOT(slot_selfDestroy      ()));}//\*****************************************************************************LargeDatagram::~LargeDatagram(){  qDebug("[~LargeDatagram]: ID = %lu", (unsigned long)m_datagramID);  free(m_fragments);  free(m_data);}//\*****************************************************************************void LargeDatagram::initDatagram(const char* dtgrm, quint32 dtgrm_len){  quint8 cnl; // comp_name_len  quint8 unl; // user_name_len  if(m_inited || dtgrm_len < AbstractChatCore::protocolLen())    return;  m_programVersion    = ChatCore::programVersion (dtgrm);  m_protocolVersion   = ChatCore::protocolVersion(dtgrm);  m_destIP            = ChatCore::destIp         (dtgrm);  m_packetType        = ChatCore::packetType     (dtgrm);  m_fragmentSize      = ChatCore::fragmentSize   (dtgrm);  m_firstFragmentTime = ChatCore::time           (dtgrm);  m_channelType       = ChatCore::channelType    (dtgrm);  cnl                 = ChatCore::compNameLen    (dtgrm);  unl                 = ChatCore::userNameLen    (dtgrm);  if(dtgrm_len < quint32(AbstractChatCore::protocolLen() + unl + cnl + AbstractChatCore::optionsLen(dtgrm)))    return;  m_totalFragments    = ChatCore::messageLen  (dtgrm);  m_totalSize         = ChatCore::parametrsLen(dtgrm);  m_senderCompName    = ChatCore::compName    (dtgrm, dtgrm_len);  m_senderName        = ChatCore::userName    (dtgrm, dtgrm_len);  // не m_totalFragments-1, потому что 0-й фрагмент является инициализирующим  m_lastFragmentNum   = m_totalFragments;  // вычисляем есть ли остаток  if(m_totalSize < m_fragmentSize * m_totalFragments)    m_lastFragmentSize  = m_totalSize - (m_fragmentSize * (m_totalFragments - 1));  else    m_lastFragmentSize  = m_fragmentSize;  m_currentSize     = 0;  m_fragmentsRemain = m_totalFragments;  m_fragments       = (char*)calloc(m_totalFragments, 1);  assert(NULL != m_fragments);  //******************  if(AbstractChatCore::packetType(dtgrm) == AbstractChatCore::FILE)  {    QByteArray ba;    quint16    size;    if(dtgrm_len >= quint32(AbstractChatCore::protocolLen() + unl + cnl + 2 + AbstractChatCore::optionsLen(dtgrm)))    {      size = str2US(dtgrm + AbstractChatCore::protocolLen() + unl + cnl + AbstractChatCore::optionsLen(dtgrm));      if(dtgrm_len >= quint32(AbstractChatCore::protocolLen() + unl + cnl + 2 + size + AbstractChatCore::optionsLen(dtgrm)))      {        m_filename = QString().fromUtf8(dtgrm + AbstractChatCore::protocolLen() + unl + cnl + 2, size + AbstractChatCore::optionsLen(dtgrm)); // FIXME kraine koryavo        qDebug("[LargeDatagram::initDatagram]: filename = %s", m_filename.toLocal8Bit().data());      }      m_isFile = true;    }    else    {      m_selfDestroyTimer->setInterval(m_selfDestroyInterval);      m_selfDestroyTimer->start();      return;    }  }  //******************  else  {    m_data = (char*)calloc(m_totalSize, 1);    assert(NULL != m_data);  }  m_inited = true;  if((!m_isFile || m_fileInited) && m_requestTimer && m_selfDestroyTimer)  {    m_requestTimer->setInterval(m_requestInterval);    m_requestTimer->start();    m_selfDestroyTimer->setInterval(m_selfDestroyInterval);    m_selfDestroyTimer->start();  }  else if(!m_requestTimer || !m_selfDestroyTimer)  {    Globals::addError("Timer(s) is(are) NULL!");    qWarning("[LargeDatagram[%d]::initDatagram]: Timer(s) is(are) NULL! req_timer = %p, destr_timer = %p\n ", m_datagramID, m_requestTimer, m_selfDestroyTimer);  }}//\*****************************************************************************void LargeDatagram::addFragment(const char* dtgrm, quint32 dtgrm_len){//   qDebug("[LargeDatagram[%d]::addFragment]:", m_datagramID);  // TODO proveryat' sootvetstvie dtgrm_len neobhodimomu razmeru  if(!m_inited || !m_fragmentsRemain || dtgrm_len < AbstractChatCore::protocolLen())    return;  quint32 num = ChatCore::packetNum  (dtgrm);  quint8  cnl = ChatCore::compNameLen(dtgrm);  quint8  unl = ChatCore::userNameLen(dtgrm);  if((dtgrm_len < quint32(AbstractChatCore::protocolLen() + unl + cnl + AbstractChatCore::optionsLen(dtgrm))) || m_fragments[num - 1] || (ChatCore::packetType(dtgrm) == AbstractChatCore::FILE))    return;  // если фрагмент последний - его размер может быть меньше чем у остальных.. выясним это:  int fragment_size = (num != m_totalFragments) ? m_fragmentSize : m_lastFragmentSize;  if(dtgrm_len < quint32(AbstractChatCore::protocolLen() + unl + cnl + fragment_size + AbstractChatCore::optionsLen(dtgrm)))      return;  memcpy((m_data + (num - 1) * m_fragmentSize), dtgrm + AbstractChatCore::protocolLen() + cnl + unl + AbstractChatCore::optionsLen(dtgrm), fragment_size);  m_fragmentsRemain--;  m_currentSize += fragment_size;  m_fragments[num - 1] = 1;  if(!m_fragmentsRemain)  {    m_finalFragmentTime  = time(NULL);    m_requestTimer->stop();    m_selfDestroyTimer->stop();    delete m_selfDestroyTimer;    delete m_requestTimer;    m_selfDestroyTimer = NULL;    m_requestTimer = NULL;    return;  }  else if(num == m_lastFragmentNum)  {    qDebug("[LargeDatagram[%d]::addFragment]: fragmentsRemain  = %d", m_datagramID, m_fragmentsRemain);    qDebug("[LargeDatagram[%d]::addFragment]: lastFragmentNum = %d", m_datagramID, m_lastFragmentNum);    for(int i = m_lastFragmentNum; i >= 0; i--)      if(!m_fragments[i])      {        m_lastFragmentNum = i;        break;      }    qDebug("[LargeDatagram[%d]::addFragment]: newLastFragmentNum = %d", m_datagramID, m_lastFragmentNum);    emit wantFragments(m_fragments, m_totalFragments, m_datagramID, m_srcIP);  }  if(m_requestTimer)    m_requestTimer->start(m_requestInterval);  if(m_selfDestroyTimer)    m_selfDestroyTimer->start(m_selfDestroyInterval);}//\*****************************************************************************void LargeDatagram::addFileFragment(const char* dtgrm, quint32 dtgrm_len){  if(!m_inited || !m_fragmentsRemain || dtgrm_len < AbstractChatCore::protocolLen() || (m_isFile && !m_fileInited))    return;  quint32 num = ChatCore::packetNum  (dtgrm);  quint8  cnl = ChatCore::compNameLen(dtgrm);  quint8  unl = ChatCore::userNameLen(dtgrm);  if(dtgrm_len < quint32(AbstractChatCore::protocolLen() + unl + cnl + AbstractChatCore::optionsLen(dtgrm)))    return;  if(m_fragments[num - 1])    return;  // если фрагмент последний - его размер может быть меньше чем у остальных.. выясним это:  int fragment_size = (num != m_totalFragments) ? m_fragmentSize : m_lastFragmentSize;  if(dtgrm_len < quint32(AbstractChatCore::protocolLen() + unl + cnl + fragment_size + AbstractChatCore::optionsLen(dtgrm)))    return;  m_file.seek(m_fragmentSize * (num - 1));  m_file.write(dtgrm + AbstractChatCore::protocolLen() + cnl + unl + AbstractChatCore::optionsLen(dtgrm), fragment_size);  m_fragmentsRemain--;  m_currentSize += fragment_size;  m_fragments[num - 1] = 1;  if(!m_fragmentsRemain)  {    m_finalFragmentTime  = time(NULL);    printf("[LargeDatagram[%d]::addFileFragment]: 0%% left\n", m_datagramID);    emit percentsRemain(0, m_datagramID, m_srcIP);    m_file.close();    m_requestTimer->stop();    m_selfDestroyTimer->stop();    delete m_selfDestroyTimer;    delete m_requestTimer;    m_selfDestroyTimer = NULL;    m_requestTimer = NULL;    emit completed(this);    return;  }  else if(num == m_lastFragmentNum)  {    qDebug("[LargeDatagram[%d]::addFileFragment]: fragmentsRemain = %d", m_datagramID, m_fragmentsRemain);    qDebug("[LargeDatagram[%d]::addFileFragment]: lastFragmentNum = %d", m_datagramID, m_lastFragmentNum);    for(int i = m_lastFragmentNum; i >= 0; i--)      if(!m_fragments[i])      {        m_lastFragmentNum = i;        break;      }    qDebug("[LargeDatagram[%d]::addFileFragment]: newLastFragmentNum = %d", m_datagramID, m_lastFragmentNum);    emit wantFragments(m_fragments, m_totalFragments, m_datagramID, m_srcIP);  }  quint8 remain = (quint8)((double)m_fragmentsRemain / ((double)m_totalFragments / (double)100));  if(remain < m_remain)  {    m_remain = remain;    printf("[LargeDatagram[%d]::addFileFragment]: %d%% left\n", m_datagramID, remain);    emit percentsRemain(remain, m_datagramID, m_srcIP);  }  if(m_requestTimer)    m_requestTimer->start(m_requestInterval);  if(m_selfDestroyTimer)    m_selfDestroyTimer->start(m_selfDestroyInterval);}//\*****************************************************************************bool LargeDatagram::fillHeader(QC_DatagramHeader* Hdr){  qDebug("[LargeDatagram(%lu, %lu)::fillHeader], m_inited = %d", (unsigned long)m_srcIP, (unsigned long)m_datagramID, m_inited);  int shift;  shift = /*m_protocolVersion >= 4 ? 0 :*/ 8;  if(m_inited == false || m_programVersion < 5 || (m_protocolVersion != AbstractChatCore::protocolVersion()))    return 0;  Hdr->programVersion  = m_programVersion;  Hdr->protocolVersion = m_protocolVersion;  Hdr->dest_ip         = m_destIP;  Hdr->src_ip          = m_srcIP;  Hdr->type            = m_packetType;  Hdr->tm              = m_firstFragmentTime;  Hdr->receive_tm      = m_finalFragmentTime;  Hdr->name            = m_senderName;  Hdr->comp_name       = m_senderCompName;  Hdr->chnnl_id        = m_channelType;  Hdr->msg_len         = str2UL(m_data    );  Hdr->parametrs_len   = str2UL(m_data + 4);  printf("protver = %d\n", m_protocolVersion);//   if(m_protocolVersion >= 4)//   {//     Hdr->msg_len         = AbstractChatCore::messageLen(m_data);//     Hdr->parametrs_len   = AbstractChatCore::parametrsLen(m_data);//   }  if(m_totalSize < shift + Hdr->msg_len + Hdr->parametrs_len)  {    qWarning("[LargeDatagram::fillHeader]: [error] wrong length of fragmented packet (total size smaller than expected[%jd < %lu]) [3]\n Exiting from fillHeader\n", m_totalSize, shift + Hdr->msg_len + Hdr->parametrs_len );//     qWarning("[LargeDatagram::fillHeader]: %d + %d\n", Hdr->msg_len, Hdr->parametrs_len);    return 0;  }  Hdr->msg       = QString().fromUtf8( QByteArray(m_data  + shift, Hdr->msg_len), Hdr->msg_len );  Hdr->parametrs = QByteArray(m_data + shift + Hdr->msg_len, Hdr->parametrs_len);  Hdr->color = ChatCore::getColorParametr(&Hdr->parametrs);  // getting versionName  QByteArray ba = ChatCore::getParametr("Version", Hdr->parametrs);  if(!ba.isEmpty())    Hdr->versionName = QString().fromUtf8(ba);  else if(Hdr->programVersion <= Globals::VersionID)    Hdr->versionName = QString(Globals::VersionsTable[Hdr->programVersion - 1]);  else    Hdr->versionName = QString("New Version[id = %1]").arg(Hdr->programVersion);  // getting status  Hdr->status = Globals::FREE;  ba = ChatCore::getParametr("Status", Hdr->parametrs);  if(!ba.isEmpty())    Hdr->status = ba[0];  clear();  emit completed(this);  return 1;}//\*****************************************************************************void LargeDatagram::clear(){  if(m_inited)  {    free(m_data);    free(m_fragments);    m_data = NULL;    m_fragments = NULL;  }  m_inited = false;}//\*****************************************************************************void LargeDatagram::slot_fragmentsRequest(){  qDebug("[LargeDatagram[%d]::slot_fragmentsRequest]", m_datagramID);  if(m_inited && m_fragmentsRemain)    emit wantFragments(m_fragments, m_totalFragments, m_datagramID, m_srcIP);}//\*****************************************************************************void LargeDatagram::slot_selfDestroy(){  qDebug("[LargeDatagram[%d]::selfDestroy]", m_datagramID);  delete m_requestTimer;  delete m_selfDestroyTimer;  clear();  m_inited = false;  emit wantDie(this);}//\*****************************************************************************void LargeDatagram::allocateSpace(){  if(!m_fileInited)    return;  m_file.open(QIODevice::WriteOnly);  m_file.resize(m_totalSize);  m_file.seek(0);}//\*****************************************************************************void LargeDatagram::slot_initFile(const QString & filename){  m_file.setFileName(filename);  m_fileInited = true;  allocateSpace();  m_requestTimer->setInterval(m_requestInterval);  m_requestTimer->start();  emit readyReceive(m_datagramID, m_srcIP);}//\*****************************************************************************

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -