blob: 1cc64a418211eae0f1fcea21924ed91789880ccd [file] [log] [blame]
Junxiao Shi9b0d3e92014-02-15 12:27:12 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (C) 2014 Named Data Networking Project
4 * See COPYING for copyright and distribution information.
5 */
6
7#include "ndnlp-slicer.hpp"
8
9#include <ndn-cpp-dev/encoding/encoding-buffer.hpp>
10
11namespace nfd {
12namespace ndnlp {
13
14Slicer::Slicer(size_t mtu)
15 : m_mtu(mtu)
16{
17 this->estimateOverhead();
18}
19
20Slicer::~Slicer()
21{
22}
23
24template<bool T>
25static inline size_t
26Slicer_encodeFragment(ndn::EncodingImpl<T>& blk,
27 uint64_t seq, uint16_t fragIndex, uint16_t fragCount,
28 const uint8_t* payload, size_t payloadSize)
29{
30 size_t totalLength = 0;
Junxiao Shidf3b4382014-02-23 11:28:21 -070031
Junxiao Shi9b0d3e92014-02-15 12:27:12 -070032 // NdnlpPayload
33 size_t payloadLength = blk.prependByteArray(payload, payloadSize);
34 totalLength += payloadLength;
35 totalLength += blk.prependVarNumber(payloadLength);
36 totalLength += blk.prependVarNumber(tlv::NdnlpPayload);
Junxiao Shidf3b4382014-02-23 11:28:21 -070037
Junxiao Shi9b0d3e92014-02-15 12:27:12 -070038 bool needFragIndexAndCount = fragCount > 1;
39 if (needFragIndexAndCount) {
40 // NdnlpFragCount
Junxiao Shidf3b4382014-02-23 11:28:21 -070041 size_t fragCountLength = blk.prependNonNegativeInteger(fragCount);
Junxiao Shi9b0d3e92014-02-15 12:27:12 -070042 totalLength += fragCountLength;
43 totalLength += blk.prependVarNumber(fragCountLength);
44 totalLength += blk.prependVarNumber(tlv::NdnlpFragCount);
Junxiao Shidf3b4382014-02-23 11:28:21 -070045
Junxiao Shi9b0d3e92014-02-15 12:27:12 -070046 // NdnlpFragIndex
Junxiao Shidf3b4382014-02-23 11:28:21 -070047 size_t fragIndexLength = blk.prependNonNegativeInteger(fragIndex);
Junxiao Shi9b0d3e92014-02-15 12:27:12 -070048 totalLength += fragIndexLength;
49 totalLength += blk.prependVarNumber(fragIndexLength);
50 totalLength += blk.prependVarNumber(tlv::NdnlpFragIndex);
51 }
Junxiao Shidf3b4382014-02-23 11:28:21 -070052
Junxiao Shi9b0d3e92014-02-15 12:27:12 -070053 // NdnlpSequence
54 uint64_t sequenceBE = htobe64(seq);
55 size_t sequenceLength = blk.prependByteArray(
56 reinterpret_cast<uint8_t*>(&sequenceBE), sizeof(sequenceBE));
57 totalLength += sequenceLength;
58 totalLength += blk.prependVarNumber(sequenceLength);
59 totalLength += blk.prependVarNumber(tlv::NdnlpSequence);
Junxiao Shidf3b4382014-02-23 11:28:21 -070060
61 // NdnlpData
Junxiao Shi9b0d3e92014-02-15 12:27:12 -070062 totalLength += blk.prependVarNumber(totalLength);
63 totalLength += blk.prependVarNumber(tlv::NdnlpData);
Junxiao Shidf3b4382014-02-23 11:28:21 -070064
Junxiao Shi9b0d3e92014-02-15 12:27:12 -070065 return totalLength;
66}
67
68void
69Slicer::estimateOverhead()
70{
71 ndn::EncodingEstimator estimator;
72 size_t estimatedSize = Slicer_encodeFragment(estimator,
73 0, 0, 2, 0, m_mtu);
Junxiao Shidf3b4382014-02-23 11:28:21 -070074
Junxiao Shi9b0d3e92014-02-15 12:27:12 -070075 size_t overhead = estimatedSize - m_mtu;
76 m_maxPayload = m_mtu - overhead;
77}
78
79PacketArray
80Slicer::slice(const Block& block)
81{
82 BOOST_ASSERT(block.hasWire());
83 const uint8_t* networkPacket = block.wire();
84 size_t networkPacketSize = block.size();
Junxiao Shidf3b4382014-02-23 11:28:21 -070085
Junxiao Shi9b0d3e92014-02-15 12:27:12 -070086 uint16_t fragCount = static_cast<uint16_t>(
87 (networkPacketSize / m_maxPayload) +
88 (networkPacketSize % m_maxPayload == 0 ? 0 : 1)
89 );
90 PacketArray pa = make_shared<std::vector<Block> >();
91 pa->reserve(fragCount);
92 SequenceBlock seqBlock = m_seqgen.nextBlock(fragCount);
Junxiao Shidf3b4382014-02-23 11:28:21 -070093
Junxiao Shi9b0d3e92014-02-15 12:27:12 -070094 for (uint16_t fragIndex = 0; fragIndex < fragCount; ++fragIndex) {
95 size_t payloadOffset = fragIndex * m_maxPayload;
96 const uint8_t* payload = networkPacket + payloadOffset;
97 size_t payloadSize = std::min(m_maxPayload, networkPacketSize - payloadOffset);
Junxiao Shidf3b4382014-02-23 11:28:21 -070098
Junxiao Shi9b0d3e92014-02-15 12:27:12 -070099 ndn::EncodingBuffer buffer(m_mtu, 0);
100 size_t pktSize = Slicer_encodeFragment(buffer,
101 seqBlock[fragIndex], fragIndex, fragCount, payload, payloadSize);
Junxiao Shidf3b4382014-02-23 11:28:21 -0700102
Junxiao Shi9b0d3e92014-02-15 12:27:12 -0700103 BOOST_ASSERT(pktSize <= m_mtu);
Junxiao Shidf3b4382014-02-23 11:28:21 -0700104
Junxiao Shi9b0d3e92014-02-15 12:27:12 -0700105 pa->push_back(buffer.block());
106 }
Junxiao Shidf3b4382014-02-23 11:28:21 -0700107
Junxiao Shi9b0d3e92014-02-15 12:27:12 -0700108 return pa;
109}
110
111} // namespace ndnlp
112} // namespace nfd