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); }
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); }
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 ()); }
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); }
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 (); } } }
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; } } }
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)); } } }
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); } }
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; }
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); } }