blob: 252e77d4b09a11130b5fc11be0a3dea1e8586a45 [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 Shie4eec132015-03-12 10:33:25 -070081 return Block::fromBuffer(buffer, 0);
Junxiao Shi083f7782015-02-21 12:06:26 -070082}
83
84std::tuple<bool, Block>
85PartialMessage::reassembleSingle(const NdnlpData& fragment)
86{
87 BOOST_ASSERT(fragment.fragCount == 1);
88
Junxiao Shie4eec132015-03-12 10:33:25 -070089 try {
90 return std::make_tuple(true, fragment.payload.blockFromValue());
91 }
92 catch (tlv::Error&) {
93 return std::make_tuple(false, Block());
94 }
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;
Junxiao Shie4eec132015-03-12 10:33:25 -0700107
Junxiao Shi083f7782015-02-21 12:06:26 -0700108 if (pkt.fragCount == 1) { // single fragment
109 std::tie(isReassembled, reassembled) = PartialMessage::reassembleSingle(pkt);
Junxiao Shie4eec132015-03-12 10:33:25 -0700110 }
111 else {
112 uint64_t messageIdentifier = pkt.seq - pkt.fragIndex;
113 PartialMessage& pm = m_partialMessages[messageIdentifier];
114 this->scheduleCleanup(messageIdentifier, pm);
115
116 pm.add(pkt.fragIndex, pkt.fragCount, pkt.payload);
117
118 if (pm.isComplete()) {
119 std::tie(isReassembled, reassembled) = pm.reassemble();
120 m_partialMessages.erase(messageIdentifier);
121 }
122 else {
Junxiao Shi083f7782015-02-21 12:06:26 -0700123 return;
124 }
Junxiao Shie4eec132015-03-12 10:33:25 -0700125 }
Junxiao Shi083f7782015-02-21 12:06:26 -0700126
Junxiao Shie4eec132015-03-12 10:33:25 -0700127 if (!isReassembled) {
128 NFD_LOG_TRACE(pkt.seq << " reassemble error");
Junxiao Shid6dcd2c2014-02-16 14:49:54 -0700129 return;
130 }
Junxiao Shidf3b4382014-02-23 11:28:21 -0700131
Junxiao Shie4eec132015-03-12 10:33:25 -0700132 NFD_LOG_TRACE(pkt.seq << " deliver");
133 this->onReceive(reassembled);
Junxiao Shid6dcd2c2014-02-16 14:49:54 -0700134}
135
136void
137PartialMessageStore::scheduleCleanup(uint64_t messageIdentifier,
Junxiao Shia37405d2015-01-26 10:50:58 -0700138 PartialMessage& partialMessage)
Junxiao Shid6dcd2c2014-02-16 14:49:54 -0700139{
Junxiao Shia37405d2015-01-26 10:50:58 -0700140 partialMessage.expiry = scheduler::schedule(m_idleDuration,
Junxiao Shid6dcd2c2014-02-16 14:49:54 -0700141 bind(&PartialMessageStore::cleanup, this, messageIdentifier));
142}
143
144void
145PartialMessageStore::cleanup(uint64_t messageIdentifier)
146{
Junxiao Shi083f7782015-02-21 12:06:26 -0700147 NFD_LOG_TRACE(messageIdentifier << " cleanup");
Junxiao Shia37405d2015-01-26 10:50:58 -0700148 m_partialMessages.erase(messageIdentifier);
Junxiao Shid6dcd2c2014-02-16 14:49:54 -0700149}
150
151} // namespace ndnlp
152} // namespace nfd