Junxiao Shi | d6dcd2c | 2014-02-16 14:49:54 -0700 | [diff] [blame] | 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ |
| 2 | /** |
Junxiao Shi | a37405d | 2015-01-26 10:50:58 -0700 | [diff] [blame] | 3 | * 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 Afanasyev | 9bcbc7c | 2014-04-06 19:37:37 -0700 | [diff] [blame] | 10 | * |
| 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 Shi | a37405d | 2015-01-26 10:50:58 -0700 | [diff] [blame] | 24 | */ |
Junxiao Shi | d6dcd2c | 2014-02-16 14:49:54 -0700 | [diff] [blame] | 25 | |
| 26 | #include "ndnlp-partial-message-store.hpp" |
Junxiao Shi | 083f778 | 2015-02-21 12:06:26 -0700 | [diff] [blame] | 27 | #include "core/logger.hpp" |
Junxiao Shi | d6dcd2c | 2014-02-16 14:49:54 -0700 | [diff] [blame] | 28 | |
| 29 | namespace nfd { |
| 30 | namespace ndnlp { |
| 31 | |
Junxiao Shi | 083f778 | 2015-02-21 12:06:26 -0700 | [diff] [blame] | 32 | NFD_LOG_INIT("NdnlpPartialMessageStore"); |
| 33 | |
Junxiao Shi | d6dcd2c | 2014-02-16 14:49:54 -0700 | [diff] [blame] | 34 | PartialMessage::PartialMessage() |
| 35 | : m_fragCount(0) |
| 36 | , m_received(0) |
| 37 | , m_totalLength(0) |
| 38 | { |
| 39 | } |
| 40 | |
| 41 | bool |
| 42 | PartialMessage::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 Shi | df3b438 | 2014-02-23 11:28:21 -0700 | [diff] [blame] | 48 | |
Junxiao Shi | d6dcd2c | 2014-02-16 14:49:54 -0700 | [diff] [blame] | 49 | if (m_fragCount != fragCount || fragIndex >= m_fragCount) { |
| 50 | return false; |
| 51 | } |
Junxiao Shi | df3b438 | 2014-02-23 11:28:21 -0700 | [diff] [blame] | 52 | |
Junxiao Shi | d6dcd2c | 2014-02-16 14:49:54 -0700 | [diff] [blame] | 53 | if (!m_payloads[fragIndex].empty()) { // duplicate |
| 54 | return false; |
| 55 | } |
Junxiao Shi | df3b438 | 2014-02-23 11:28:21 -0700 | [diff] [blame] | 56 | |
Junxiao Shi | d6dcd2c | 2014-02-16 14:49:54 -0700 | [diff] [blame] | 57 | m_payloads[fragIndex] = payload; |
| 58 | ++m_received; |
| 59 | m_totalLength += payload.value_size(); |
Junxiao Shi | c0d0591 | 2014-02-17 19:06:21 -0700 | [diff] [blame] | 60 | return true; |
Junxiao Shi | d6dcd2c | 2014-02-16 14:49:54 -0700 | [diff] [blame] | 61 | } |
| 62 | |
| 63 | bool |
| 64 | PartialMessage::isComplete() const |
| 65 | { |
| 66 | return m_received == m_fragCount; |
| 67 | } |
| 68 | |
Junxiao Shi | 083f778 | 2015-02-21 12:06:26 -0700 | [diff] [blame] | 69 | std::tuple<bool, Block> |
Junxiao Shi | d6dcd2c | 2014-02-16 14:49:54 -0700 | [diff] [blame] | 70 | PartialMessage::reassemble() |
| 71 | { |
| 72 | BOOST_ASSERT(this->isComplete()); |
Junxiao Shi | df3b438 | 2014-02-23 11:28:21 -0700 | [diff] [blame] | 73 | |
Junxiao Shi | d6dcd2c | 2014-02-16 14:49:54 -0700 | [diff] [blame] | 74 | ndn::BufferPtr buffer = make_shared<ndn::Buffer>(m_totalLength); |
Junxiao Shi | 083f778 | 2015-02-21 12:06:26 -0700 | [diff] [blame] | 75 | 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 Shi | d6dcd2c | 2014-02-16 14:49:54 -0700 | [diff] [blame] | 78 | } |
Junxiao Shi | 083f778 | 2015-02-21 12:06:26 -0700 | [diff] [blame] | 79 | BOOST_ASSERT(buf == buffer->end()); |
Junxiao Shi | df3b438 | 2014-02-23 11:28:21 -0700 | [diff] [blame] | 80 | |
Junxiao Shi | e4eec13 | 2015-03-12 10:33:25 -0700 | [diff] [blame] | 81 | return Block::fromBuffer(buffer, 0); |
Junxiao Shi | 083f778 | 2015-02-21 12:06:26 -0700 | [diff] [blame] | 82 | } |
| 83 | |
| 84 | std::tuple<bool, Block> |
| 85 | PartialMessage::reassembleSingle(const NdnlpData& fragment) |
| 86 | { |
| 87 | BOOST_ASSERT(fragment.fragCount == 1); |
| 88 | |
Junxiao Shi | e4eec13 | 2015-03-12 10:33:25 -0700 | [diff] [blame] | 89 | try { |
| 90 | return std::make_tuple(true, fragment.payload.blockFromValue()); |
| 91 | } |
| 92 | catch (tlv::Error&) { |
| 93 | return std::make_tuple(false, Block()); |
| 94 | } |
Junxiao Shi | d6dcd2c | 2014-02-16 14:49:54 -0700 | [diff] [blame] | 95 | } |
| 96 | |
Junxiao Shi | 98e29f4 | 2014-03-31 10:27:26 -0700 | [diff] [blame] | 97 | PartialMessageStore::PartialMessageStore(const time::nanoseconds& idleDuration) |
| 98 | : m_idleDuration(idleDuration) |
Junxiao Shi | d6dcd2c | 2014-02-16 14:49:54 -0700 | [diff] [blame] | 99 | { |
| 100 | } |
| 101 | |
Junxiao Shi | d6dcd2c | 2014-02-16 14:49:54 -0700 | [diff] [blame] | 102 | void |
Junxiao Shi | 083f778 | 2015-02-21 12:06:26 -0700 | [diff] [blame] | 103 | PartialMessageStore::receive(const NdnlpData& pkt) |
Junxiao Shi | d6dcd2c | 2014-02-16 14:49:54 -0700 | [diff] [blame] | 104 | { |
Junxiao Shi | 083f778 | 2015-02-21 12:06:26 -0700 | [diff] [blame] | 105 | bool isReassembled = false; |
| 106 | Block reassembled; |
Junxiao Shi | e4eec13 | 2015-03-12 10:33:25 -0700 | [diff] [blame] | 107 | |
Junxiao Shi | 083f778 | 2015-02-21 12:06:26 -0700 | [diff] [blame] | 108 | if (pkt.fragCount == 1) { // single fragment |
| 109 | std::tie(isReassembled, reassembled) = PartialMessage::reassembleSingle(pkt); |
Junxiao Shi | e4eec13 | 2015-03-12 10:33:25 -0700 | [diff] [blame] | 110 | } |
| 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 Shi | 083f778 | 2015-02-21 12:06:26 -0700 | [diff] [blame] | 123 | return; |
| 124 | } |
Junxiao Shi | e4eec13 | 2015-03-12 10:33:25 -0700 | [diff] [blame] | 125 | } |
Junxiao Shi | 083f778 | 2015-02-21 12:06:26 -0700 | [diff] [blame] | 126 | |
Junxiao Shi | e4eec13 | 2015-03-12 10:33:25 -0700 | [diff] [blame] | 127 | if (!isReassembled) { |
| 128 | NFD_LOG_TRACE(pkt.seq << " reassemble error"); |
Junxiao Shi | d6dcd2c | 2014-02-16 14:49:54 -0700 | [diff] [blame] | 129 | return; |
| 130 | } |
Junxiao Shi | df3b438 | 2014-02-23 11:28:21 -0700 | [diff] [blame] | 131 | |
Junxiao Shi | e4eec13 | 2015-03-12 10:33:25 -0700 | [diff] [blame] | 132 | NFD_LOG_TRACE(pkt.seq << " deliver"); |
| 133 | this->onReceive(reassembled); |
Junxiao Shi | d6dcd2c | 2014-02-16 14:49:54 -0700 | [diff] [blame] | 134 | } |
| 135 | |
| 136 | void |
| 137 | PartialMessageStore::scheduleCleanup(uint64_t messageIdentifier, |
Junxiao Shi | a37405d | 2015-01-26 10:50:58 -0700 | [diff] [blame] | 138 | PartialMessage& partialMessage) |
Junxiao Shi | d6dcd2c | 2014-02-16 14:49:54 -0700 | [diff] [blame] | 139 | { |
Junxiao Shi | a37405d | 2015-01-26 10:50:58 -0700 | [diff] [blame] | 140 | partialMessage.expiry = scheduler::schedule(m_idleDuration, |
Junxiao Shi | d6dcd2c | 2014-02-16 14:49:54 -0700 | [diff] [blame] | 141 | bind(&PartialMessageStore::cleanup, this, messageIdentifier)); |
| 142 | } |
| 143 | |
| 144 | void |
| 145 | PartialMessageStore::cleanup(uint64_t messageIdentifier) |
| 146 | { |
Junxiao Shi | 083f778 | 2015-02-21 12:06:26 -0700 | [diff] [blame] | 147 | NFD_LOG_TRACE(messageIdentifier << " cleanup"); |
Junxiao Shi | a37405d | 2015-01-26 10:50:58 -0700 | [diff] [blame] | 148 | m_partialMessages.erase(messageIdentifier); |
Junxiao Shi | d6dcd2c | 2014-02-16 14:49:54 -0700 | [diff] [blame] | 149 | } |
| 150 | |
| 151 | } // namespace ndnlp |
| 152 | } // namespace nfd |