blob: 082f678ba5375050b24e5bdae0e79bf7723d81d5 [file] [log] [blame]
Junxiao Shid6dcd2c2014-02-16 14:49:54 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Junxiao Shia37405d2015-01-26 10:50:58 -07003 * Copyright (c) 2014-2015, Regents of the University of California,
4 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
9 * The University of Memphis.
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -070010 *
11 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
Junxiao Shia37405d2015-01-26 10:50:58 -070024 */
Junxiao Shid6dcd2c2014-02-16 14:49:54 -070025
26#include "ndnlp-partial-message-store.hpp"
Junxiao Shi083f7782015-02-21 12:06:26 -070027#include "core/logger.hpp"
Junxiao Shid6dcd2c2014-02-16 14:49:54 -070028
29namespace nfd {
30namespace ndnlp {
31
Junxiao Shi083f7782015-02-21 12:06:26 -070032NFD_LOG_INIT("NdnlpPartialMessageStore");
33
Junxiao Shid6dcd2c2014-02-16 14:49:54 -070034PartialMessage::PartialMessage()
35 : m_fragCount(0)
36 , m_received(0)
37 , m_totalLength(0)
38{
39}
40
41bool
42PartialMessage::add(uint16_t fragIndex, uint16_t fragCount, const Block& payload)
43{
44 if (m_received == 0) { // first packet
45 m_fragCount = fragCount;
46 m_payloads.resize(fragCount);
47 }
Junxiao Shidf3b4382014-02-23 11:28:21 -070048
Junxiao Shid6dcd2c2014-02-16 14:49:54 -070049 if (m_fragCount != fragCount || fragIndex >= m_fragCount) {
50 return false;
51 }
Junxiao Shidf3b4382014-02-23 11:28:21 -070052
Junxiao Shid6dcd2c2014-02-16 14:49:54 -070053 if (!m_payloads[fragIndex].empty()) { // duplicate
54 return false;
55 }
Junxiao Shidf3b4382014-02-23 11:28:21 -070056
Junxiao Shid6dcd2c2014-02-16 14:49:54 -070057 m_payloads[fragIndex] = payload;
58 ++m_received;
59 m_totalLength += payload.value_size();
Junxiao Shic0d05912014-02-17 19:06:21 -070060 return true;
Junxiao Shid6dcd2c2014-02-16 14:49:54 -070061}
62
63bool
64PartialMessage::isComplete() const
65{
66 return m_received == m_fragCount;
67}
68
Junxiao Shi083f7782015-02-21 12:06:26 -070069std::tuple<bool, Block>
Junxiao Shid6dcd2c2014-02-16 14:49:54 -070070PartialMessage::reassemble()
71{
72 BOOST_ASSERT(this->isComplete());
Junxiao Shidf3b4382014-02-23 11:28:21 -070073
Junxiao Shid6dcd2c2014-02-16 14:49:54 -070074 ndn::BufferPtr buffer = make_shared<ndn::Buffer>(m_totalLength);
Junxiao Shi083f7782015-02-21 12:06:26 -070075 ndn::Buffer::iterator buf = buffer->begin();
76 for (const Block& payload : m_payloads) {
77 buf = std::copy(payload.value_begin(), payload.value_end(), buf);
Junxiao Shid6dcd2c2014-02-16 14:49:54 -070078 }
Junxiao Shi083f7782015-02-21 12:06:26 -070079 BOOST_ASSERT(buf == buffer->end());
Junxiao Shidf3b4382014-02-23 11:28:21 -070080
Junxiao Shi083f7782015-02-21 12:06:26 -070081 Block reassembled;
82 bool isBlockOk = Block::fromBuffer(buffer, 0, reassembled);
83 return std::make_tuple(isBlockOk, reassembled);
84}
85
86std::tuple<bool, Block>
87PartialMessage::reassembleSingle(const NdnlpData& fragment)
88{
89 BOOST_ASSERT(fragment.fragCount == 1);
90
91 Block reassembled;
92 bool isBlockOk = Block::fromBuffer(fragment.payload.value(), fragment.payload.value_size(),
93 reassembled);
94 return std::make_tuple(isBlockOk, reassembled);
Junxiao Shid6dcd2c2014-02-16 14:49:54 -070095}
96
Junxiao Shi98e29f42014-03-31 10:27:26 -070097PartialMessageStore::PartialMessageStore(const time::nanoseconds& idleDuration)
98 : m_idleDuration(idleDuration)
Junxiao Shid6dcd2c2014-02-16 14:49:54 -070099{
100}
101
Junxiao Shid6dcd2c2014-02-16 14:49:54 -0700102void
Junxiao Shi083f7782015-02-21 12:06:26 -0700103PartialMessageStore::receive(const NdnlpData& pkt)
Junxiao Shid6dcd2c2014-02-16 14:49:54 -0700104{
Junxiao Shi083f7782015-02-21 12:06:26 -0700105 bool isReassembled = false;
106 Block reassembled;
107 if (pkt.fragCount == 1) { // single fragment
108 std::tie(isReassembled, reassembled) = PartialMessage::reassembleSingle(pkt);
109 if (!isReassembled) {
110 NFD_LOG_TRACE(pkt.seq << " reassemble error");
111 return;
112 }
113
114 NFD_LOG_TRACE(pkt.seq << " deliver");
115 this->onReceive(reassembled);
Junxiao Shid6dcd2c2014-02-16 14:49:54 -0700116 return;
117 }
Junxiao Shidf3b4382014-02-23 11:28:21 -0700118
Junxiao Shi083f7782015-02-21 12:06:26 -0700119 uint64_t messageIdentifier = pkt.seq - pkt.fragIndex;
Junxiao Shia37405d2015-01-26 10:50:58 -0700120 PartialMessage& pm = m_partialMessages[messageIdentifier];
Junxiao Shid6dcd2c2014-02-16 14:49:54 -0700121 this->scheduleCleanup(messageIdentifier, pm);
Junxiao Shidf3b4382014-02-23 11:28:21 -0700122
Junxiao Shi083f7782015-02-21 12:06:26 -0700123 pm.add(pkt.fragIndex, pkt.fragCount, pkt.payload);
Junxiao Shia37405d2015-01-26 10:50:58 -0700124 if (pm.isComplete()) {
Junxiao Shi083f7782015-02-21 12:06:26 -0700125 std::tie(isReassembled, reassembled) = pm.reassemble();
126 if (!isReassembled) {
127 NFD_LOG_TRACE(messageIdentifier << " reassemble error");
128 return;
129 }
130
131 NFD_LOG_TRACE(messageIdentifier << " deliver");
132 this->onReceive(reassembled);
133 m_partialMessages.erase(messageIdentifier);
Junxiao Shid6dcd2c2014-02-16 14:49:54 -0700134 }
135}
136
137void
138PartialMessageStore::scheduleCleanup(uint64_t messageIdentifier,
Junxiao Shia37405d2015-01-26 10:50:58 -0700139 PartialMessage& partialMessage)
Junxiao Shid6dcd2c2014-02-16 14:49:54 -0700140{
Junxiao Shia37405d2015-01-26 10:50:58 -0700141 partialMessage.expiry = scheduler::schedule(m_idleDuration,
Junxiao Shid6dcd2c2014-02-16 14:49:54 -0700142 bind(&PartialMessageStore::cleanup, this, messageIdentifier));
143}
144
145void
146PartialMessageStore::cleanup(uint64_t messageIdentifier)
147{
Junxiao Shi083f7782015-02-21 12:06:26 -0700148 NFD_LOG_TRACE(messageIdentifier << " cleanup");
Junxiao Shia37405d2015-01-26 10:50:58 -0700149 m_partialMessages.erase(messageIdentifier);
Junxiao Shid6dcd2c2014-02-16 14:49:54 -0700150}
151
152} // namespace ndnlp
153} // namespace nfd