Пример #1
0
  void Retransmit::send (Message_ptr m)
  {
    if (m->find (Data::id) != 0)
    {
      SN const* sn = static_cast<SN const*> (m->find (SN::id));

      Lock l (mutex_);
      queue_.bind (sn->num (), Descr (m->clone ()));
    }

    out_->send (m);
  }
Пример #2
0
  void Acknowledge::send (Message_ptr m)
  {
    if (Data const* data = static_cast<Data const*> (m->find (Data::id)))
    {
      size_t max_payload_size (
        params_.max_packet_size () - max_service_size);

      if (max_payload_size > data->size ())
      {
        u32 max_size (max_payload_size - data->size ());
        u32 max_elem (NRTM::max_count (max_size));

        if (max_elem > 0)
        {
          Lock l (mutex_);

          Profile_ptr nrtm (create_nrtm (max_elem));

          if (nrtm.get ())
            m->add (nrtm);
        }
      }

      nrtm_timer_ = params_.nrtm_timeout (); // Reset timer.
    }

    out_->send (m);
  }
Пример #3
0
  ssize_t Socket_Impl::
    size_ (ACE_Time_Value const* timeout)
    {
      ACE_Time_Value abs_time;

      if (timeout)
        abs_time = ACE_OS::gettimeofday () + *timeout;

      Lock l (mutex_);

      while (queue_.is_empty ())
        {
          if (timeout)
            {
              if (cond_.wait (&abs_time) != -1)
                break;
            }
          else
            {
              if (cond_.wait () != -1)
                break;
            }

          return -1; // errno is already set
        }

      // I can't get the head of the queue without actually dequeuing
      // the element.
      //
      Message_ptr m;

      if (queue_.dequeue_head (m) == -1)
        ACE_OS::abort ();

      if (queue_.enqueue_head (m) == -1)
        ACE_OS::abort ();

      if (m->find (NoData::id) != 0)
        {
          errno = ENOENT;
          return -1;
        }

      Data const* d = static_cast<Data const*>(m->find (Data::id));

      return static_cast<ssize_t> (d->size ());
    }
Пример #4
0
  void Retransmit::recv (Message_ptr m)
  {
    if (NAK const* nak = static_cast<NAK const*> (m->find (NAK::id)))
    {
      Address to (static_cast<To const*> (m->find (To::id))->address ());

      if (nak->address () == to)
      {
        Lock l (mutex_);

        for (NAK::iterator j (const_cast<NAK*> (nak)->begin ());
             !j.done ();
             j.advance ())
        {
          u64* psn;
          j.next (psn);

          Message_ptr m;

          Queue::ENTRY* pair;

          if (queue_.find (*psn, pair) == 0)
          {
            //cerr << 5 << "PRTM " << to << " " << pair->ext_id_ << endl;

            m = pair->int_id_.message ();

            pair->int_id_.reset ();
          }
          else
          {
            //cerr << 4 << "message " << *psn << " not available" << endl;

            m = Message_ptr (new Message);
            m->add (Profile_ptr (new SN (*psn)));
            m->add (Profile_ptr (new NoData));
          }

          out_->send (m);
        }
      }
    }

    in_->recv (m);
  }
Пример #5
0
  void Socket_Impl::recv (Message_ptr m)
    {
      if (m->find (Data::id) != 0 || m->find (NoData::id) != 0)
        {
          if (!loop_)
            {
              Address to (static_cast<To const*> (m->find (To::id))->address ());

              Address from (
                            static_cast<From const*> (m->find (From::id))->address ());

              if (to == from)
                return;
            }

          Lock l (mutex_);

          //if (queue_.size () != 0)
          //  cerr << "recv socket queue size: " << queue_.size () << endl;

          //FUZZ: disable check_for_lack_ACE_OS
          bool signal (queue_.is_empty ());
          //FUZZ: enable check_for_lack_ACE_OS

          queue_.enqueue_tail (m);

          if (signal)
            {
              // Also write to the pipe.
              if (signal_pipe_.write_handle () != ACE_INVALID_HANDLE)
                {
                  char c;

                  if (signal_pipe_.send (&c, 1) != 1)
                    {
                      // perror ("write: ");
                      ACE_OS::abort ();
                    }
                }

              cond_.signal ();
            }
        }
    }
Пример #6
0
  void Fragment::send (Message_ptr m)
  {
    if (Data const* data = static_cast<Data const*> (m->find (Data::id)))
    {
      size_t max_payload_size (
        params_.max_packet_size () - max_service_size);

      if (data->size () <= max_payload_size)
      {
        u64 sn;
        {
          Lock l (mutex_);
          sn = sn_++;
        }

        m->add (Profile_ptr (new SN (sn)));

        out_->send (m);
        return;
      }

      char const* p = data->buf ();
      size_t size (data->size ());

      // Need fragmentation.
      //
      u32 packets (size / max_payload_size + (size % max_payload_size ? 1 : 0));

      // cerr << "size : " << size << endl
      //      << "packs: " << packets << endl;

      for (u32 i (1); i <= packets; ++i)
      {
        Message_ptr part (new Message);

        size_t s (i == packets ? size % max_payload_size : max_payload_size);

        // cerr << "pack: " << s << endl;

        u64 sn;
        {
          Lock l (mutex_);
          sn = sn_++;
        }

        part->add (Profile_ptr (new SN (sn)));
        part->add (Profile_ptr (new Part (i, packets, size)));
        part->add (Profile_ptr (new Data (p, s)));

        out_->send (part);

        p += s;
      }
    }
  }
Пример #7
0
void
ProtocolDataWidget::onRecv(Message_ptr m)
{
        Address from;
        if (From const* f = static_cast<From const*>(m->find(From::id)))
        {
                from = f->address();
        }

        if (PFileSend const* pfs = static_cast<PFileSend const*>(m->find(IMProto::FileSend)))
        {
                QString const& sn = QString::fromUtf8(pfs->property_data(IMProto::EventSn));
                QString const& kName = QString::fromUtf8(pfs->property_data(IMProto::FileKey));
                QString const& fName = QString::fromUtf8(pfs->property_data(IMProto::FileName));
                quint64 siz = QString::fromUtf8(pfs->property_data(IMProto::FileSize)).toULongLong();
                //u16 port = QString::fromUtf8(pfs->property_data(IMProto::ListenPort)).toUShort();

                QTreeWidgetItem* root = new QTreeWidgetItem;
                this->addTopLevelItem(root);
                m_RecvItemMap.insert(sn, root);
                QString const& sizstr = GetFormatedFileSize(siz);

                root->setText(COL_NAME, fName);
                root->setText(COL_SIZE, sizstr);
                root->setText(COL_TYPE, tr("File"));
                root->setText(COL_STATE, tr("waiting to receive"));
                root->setText(COL_PERCENT, "0%");
                root->setData(COL_NAME, FileKeyRole, kName);
                root->setData(COL_NAME, FileSizeRole, siz);
                root->setData(COL_NAME, DirFileRole, "FILE");
                root->setData(COL_NAME, SendRecvRole, "R");
                root->setData(COL_NAME, TransStateRole, "WAIT");
                root->setData(COL_NAME, TransItemSNRole, sn);
                root->setIcon(COL_NAME, QIcon(DataAccess::SkinPath() + "/download-file.png"));
                root->setIcon(COL_STATE, QIcon(DataAccess::SkinPath() + "/clock.png"));
                emit sigTips(tr("The other request to send %1:%2. Please switch to file transferring window to process.")
                        .arg(tr("File"))
                        .arg(fName));
        }
        else if (PDirFileRecv const* pfr = static_cast<PDirFileRecv const*>(m->find(IMProto::DirFileRecv)))
        {
                QString const& sn = QString::fromUtf8(pfr->property_data(IMProto::EventSn));
                QString const& kName = QString::fromUtf8(pfr->property_data(IMProto::FileKey));
                u16 port = QString::fromUtf8(pfr->property_data(IMProto::ListenPort)).toUShort();

                QTreeWidgetItem* item = m_SendItemMap.value(sn, 0);
                if (!item)
                {
                        //QMessageBox::critical(this, tr("Error"), tr("Unable to find item in file SendItemMap. key: %1.").arg(keys[2]));
                        return;
                }
                QString const& pfName = m_userItem->SendingFilesCollection()->value(kName);
                if (pfName.isEmpty())
                {
                        //QMessageBox::critical(this, tr("Error"), tr("Unable to find in SendingFilesCollection key: %1.").arg(keys[2]));
                        return;
                }
                QFileInfo finfo(pfName);

                ProtocolDataTransfer* pdthr = 0;
                if (finfo.isFile())
                {
                        pdthr = new ProtocolDataTransfer(item, pfName, 0,
                                port, m_userItem->IpAddress(),
                                ProtocolDataTransfer::DoSendFile);
                        connect(&m_timer, SIGNAL(timeout()), pdthr, SLOT(slotUpdate()));
                }
                else  if (finfo.isDir())
                {
                        pdthr = new ProtocolDataTransfer(item, pfName,
                                port, m_userItem->IpAddress(),
                                ProtocolDataTransfer::DoSendDir);
                        connect(&m_timer, SIGNAL(timeout()), pdthr, SLOT(slotUpdate()));
                }
                if (!pdthr)
                {
                        return;
                }
                item->setData(COL_NAME, TransThreadRole, (quint64)pdthr);
                if (!m_timer.isActive())
                {
                        m_timer.start(1000);
                }
                pdthr->start();
        } 
        else if (ProfileWithProperties const* pds = static_cast<ProfileWithProperties const*>(m->find(IMProto::DirSend)))
        {
                QString const& sn = QString::fromUtf8(pds->property_data(IMProto::EventSn));
                QString const& kName = QString::fromUtf8(pds->property_data(IMProto::FileKey));
                QString const& dName = QString::fromUtf8(pds->property_data(IMProto::FileName));
                quint64 siz = QString::fromUtf8(pds->property_data(IMProto::FileSize)).toULongLong();
                //u16 port = QString::fromUtf8(pfs->property_data(IMProto::ListenPort)).toUShort();

                QTreeWidgetItem* root = new QTreeWidgetItem;
                this->addTopLevelItem(root);
                m_RecvItemMap.insert(sn, root);
                QString const& sizstr = tr("unknown");

                root->setText(COL_NAME, dName);
                root->setText(COL_SIZE, sizstr);
                root->setText(COL_TYPE, tr("Dir"));
                root->setText(COL_STATE, tr("waiting to receive"));
                root->setText(COL_PERCENT, "0%");
                root->setData(COL_NAME, FileKeyRole, kName);
                root->setData(COL_NAME, FileSizeRole, siz);
                root->setData(COL_NAME, DirFileRole, "DIR");
                root->setData(COL_NAME, SendRecvRole, "R");
                root->setData(COL_NAME, TransStateRole, "WAIT");
                root->setData(COL_NAME, TransItemSNRole, sn);
                root->setIcon(COL_NAME, QIcon(DataAccess::SkinPath() + "/download-folder.png"));
                root->setIcon(COL_STATE, QIcon(DataAccess::SkinPath() + "/clock.png"));
                emit sigTips(tr("The other request to send %1:%2. Please switch to file transferring window to process.")
                        .arg(tr("Dir"))
                        .arg(dName));
        } 
        else if (PDirFileSendCancel const* pfsc = static_cast<PDirFileSendCancel const*>(m->find(IMProto::DirFileSendCancel)))
        {
                QString const& sn = QString::fromUtf8(pfsc->property_data(IMProto::EventSn));
                QTreeWidgetItem* item = m_RecvItemMap.value(sn);
                if (!item)
                {
                        //QMessageBox::critical(this, tr("Error"), tr("Unable to find item in file RecvItemMap. key: %1.").arg(keys[2]));
                        return;
                }
                QString tips = tr("The other canceled sending %1: %2.").arg(item->text(COL_TYPE)).arg(item->text(COL_NAME));
                emit sigTips(tips);
                m_RecvItemMap.remove(sn);

                QString const& tsr = item->data(COL_NAME, TransStateRole).toString();
                if (tsr == "START")
                {
                        ProtocolDataTransfer* t = (ProtocolDataTransfer*)item->data(COL_NAME, TransThreadRole).toULongLong();
                        disconnect(&m_timer, SIGNAL(timeout()), t, SLOT(slotUpdate()));
                        t->slotCancel();
                }

                if (!delItemWhenFinished)
                {
                        item->setData(COL_NAME, TransStateRole, "CANCEL");
                        item->setIcon(COL_STATE, QIcon(DataAccess::SkinPath() + "/warning.png"));
                        item->setText(COL_STATE, tr("Canceled"));
                }
                else
                {
                        this->takeTopLevelItem(this->indexOfTopLevelItem(item));
                }
        } 
        else if (ProfileWithProperties const* pfrc = static_cast<ProfileWithProperties const*>(m->find(IMProto::DirFileRecvCancel)))
        {
                QString const& sn = QString::fromUtf8(pfrc->property_data(IMProto::EventSn));
                QTreeWidgetItem* item = m_SendItemMap.value(sn, 0);
                if (!item)
                {
                        //QMessageBox::critical(this, tr("Error"), tr("Unable to find item in file SendItemMap. key: %1.").arg(keys[2]));
                        return;
                }
                QString tips = tr("The other canceled receiving %1: %2.").arg(item->text(COL_TYPE)).arg(item->text(COL_NAME));
                emit sigTips(tips);
                m_SendItemMap.remove(sn);

                QString const& tsr = item->data(COL_NAME, TransStateRole).toString();
                if (tsr == "START")
                {
                        ProtocolDataTransfer* t = (ProtocolDataTransfer*)item->data(COL_NAME, TransThreadRole).toLongLong();
                        disconnect(&m_timer, SIGNAL(timeout()), t, SLOT(slotUpdate()));
                        t->slotCancel();
                }
                if (!delItemWhenFinished)
                {
                        item->setData(COL_NAME, TransStateRole, "CANCEL");
                        item->setIcon(COL_STATE, QIcon(DataAccess::SkinPath() + "/warning.png"));
                        item->setText(COL_STATE, tr("Canceled"));
                }
                else
                {
                        this->takeTopLevelItem(this->indexOfTopLevelItem(item));
                }
        }
}
Пример #8
0
  void Acknowledge::recv (Message_ptr m)
  {
    // Handle NRTM. There could be some nasty interaction with code
    // that handles data below (like missing message and NAK). This
    // is why I hold the lock at the beginning (which may be not very
    // efficient).
    //
    Lock l (mutex_);

    if (NRTM const* nrtm = static_cast<NRTM const*> (m->find (NRTM::id)))
    {
      for (Map::iterator i (hold_.begin ()), e (hold_.end ()); i != e; ++i)
      {
        u64 sn (nrtm->find ((*i).ext_id_));

        if (sn != 0)
        {
          Queue& q = (*i).int_id_;

          u64 old (q.max_sn ());

          if (old < sn)
          {
            // Mark as lost.
            //
            q.bind (sn, Descr (1));
          }
        }
      }
    }

    if (m->find (Data::id) || m->find (NoData::id))
    {
      Address from (
        static_cast<From const*> (m->find (From::id))->address ());

      u64 sn (static_cast<SN const*> (m->find (SN::id))->num ());

      Map::ENTRY* e = 0;

      if (hold_.find (from, e) == -1)
      {
        // First message from this source.
        //
        hold_.bind (from, Queue (sn));
        in_->recv (m);
      }
      else
      {
        Queue& q = e->int_id_;

        if (sn <= q.sn ())
        {
          // Duplicate.
          //
          //cerr << 6 << "DUP " << from << " " << q.sn () << " >= " << sn
          //     << endl;
        }
        else if (sn == q.sn () + 1)
        {
          // Next message.
          //

          q.rebind (sn, Descr (m));
          collapse (q);
        }
        else
        {
          // Some messages are missing. Insert this one into the queue.
          //
          q.rebind (sn, Descr (m));
        }
      }
    }
    else
    {
      l.release ();

      // Just forward it up.
      //
      in_->recv (m);
    }
  }
Пример #9
0
  ssize_t Socket_Impl::
    recv_ (void* buf,
           size_t s,
           ACE_Time_Value const* timeout,
           ACE_INET_Addr* from)
    {
      ACE_Time_Value abs_time;

      if (timeout)
        abs_time = ACE_OS::gettimeofday () + *timeout;

      Lock l (mutex_);

      while (queue_.is_empty ())
        {
          if (timeout)
            {
              if (cond_.wait (&abs_time) != -1)
                break;
            }
          else
            {
              if (cond_.wait () != -1)
                break;
            }

          return -1; // errno is already set
        }


      Message_ptr m;

      if (queue_.dequeue_head (m) == -1)
        ACE_OS::abort ();


      if (queue_.is_empty ())
        {
          // Remove data from the pipe.
          //
          if (signal_pipe_.read_handle () != ACE_INVALID_HANDLE)
            {
              char c;

              if (signal_pipe_.recv (&c, 1) != 1)
                {
                  ACE_OS::perror ("read: ");
                  ACE_OS::abort ();
                }
            }
        }

      if (from)
        *from = static_cast<From const*> (m->find (From::id))->address ();

      if (m->find (NoData::id) != 0)
        {
          errno = ENOENT;
          return -1;
        }

      Data const* d = static_cast<Data const*>(m->find (Data::id));

      ssize_t r (static_cast<ssize_t> (d->size () < s ? d->size () : s));

      ACE_OS::memcpy (buf, d->buf (), r);

      return r;
    }
Пример #10
0
  void Reassemble::recv (Message_ptr m)
  {
    Map::ENTRY* e = 0;
    Address from (
      static_cast<From const*> (m->find (From::id))->address ());

    if (Data const* data = static_cast<Data const*> (m->find (Data::id)))
    {
      if (Part const* part = static_cast<Part const*> (m->find (Part::id)))
      {
        if (map_.find (from, e) == -1)
        {
          // First part of the message.
          //

          if (part->num () != 1)
          {
            // We assume that we received NoData for one of the preceding
            // fragments. Ignore this one.
            return;
          }

          Data_ptr new_data (new Data (data->buf (),
                                       static_cast<size_t> (data->size ()),
                                       static_cast<size_t> (part->total_size ())));

          //std::cerr << "part->total_size (): " << part->total_size () << endl;

          map_.bind (from, new_data);
        }
        else
        {
          // Next part of the message.
          //

          if (part->num () == 1)
            ACE_OS::abort ();


          Data const* data = static_cast<Data const*> (m->find (Data::id));

          Data_ptr& new_data = e->int_id_;

          ACE_OS::memcpy (new_data->buf () + new_data->size (),
                          data->buf (),
                          data->size ());

          //std::cerr << "data->size (): " << data->size () << endl
          //          << "new_data->size (): " << new_data->size () << endl
          //          << "new_data->capa (): " << new_data->capacity () << endl;

          new_data->size (new_data->size () + data->size ());


          if (part->num () == part->of ())
          {
            // Reassembly is complete.
            //
            if (part->total_size () != new_data->size ())
              ACE_OS::abort ();

            Message_ptr new_msg (new Message ());

            Address to (
              static_cast<To const*> (m->find (To::id))->address ());

            new_msg->add (Profile_ptr (new To (to)));
            new_msg->add (Profile_ptr (new From (from)));
            /*
             * Heads up... we need to add the new_data to new_msg then
             * unbind the entry that maps to new_data, which will decrement
             * its reference count. If the bound/refcounted pointer acted
             * polymorphically like a regular pointer does, we'd be able to
             * just pass new_data to add(Profile_Ptr) and it would work.
             * However, Profile_Ptr and Data_Ptr are not compatible, but
             * we can use the secret knowledge that both are instances of the
             * same template and that the pointers they contain really are
             * hierarchically compatible, and do this funky cast to get
             * the result we want.
             */
            //new_msg->add (*(reinterpret_cast<Profile_ptr*> (&new_data)));

            new_msg->add (Profile_ptr (new_data));

            map_.unbind (from);

            in_->recv (new_msg);
          }
        }
      }
      else
      {
        // Non-fragmented message. Make sure we are in the consistent state
        // and forward it up.
        //
        if (map_.find (from, e) != -1)
          ACE_OS::abort ();

        in_->recv (m);
      }
    }
    else if (m->find (NoData::id) != 0)
    {
      if (map_.find (from, e) != -1)
      {
        // We already received some fragments. Clean everyhting up.
        //
        map_.unbind (from);
      }

      in_->recv (m);
    }
  }