blob: 074a4f713f9db35b44539a63c28e0ca2c9a30e62 [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;
31
32 // NdnlpPayload
33 size_t payloadLength = blk.prependByteArray(payload, payloadSize);
34 totalLength += payloadLength;
35 totalLength += blk.prependVarNumber(payloadLength);
36 totalLength += blk.prependVarNumber(tlv::NdnlpPayload);
37
38 bool needFragIndexAndCount = fragCount > 1;
39 if (needFragIndexAndCount) {
40 // NdnlpFragCount
41 uint16_t fragCountBE = htobe16(fragCount);
42 size_t fragCountLength = blk.prependByteArray(
43 reinterpret_cast<uint8_t*>(&fragCountBE), sizeof(fragCountBE));
44 totalLength += fragCountLength;
45 totalLength += blk.prependVarNumber(fragCountLength);
46 totalLength += blk.prependVarNumber(tlv::NdnlpFragCount);
47
48 // NdnlpFragIndex
49 uint16_t fragIndexBE = htobe16(fragIndex);
50 size_t fragIndexLength = blk.prependByteArray(
51 reinterpret_cast<uint8_t*>(&fragIndexBE), sizeof(fragIndexBE));
52 totalLength += fragIndexLength;
53 totalLength += blk.prependVarNumber(fragIndexLength);
54 totalLength += blk.prependVarNumber(tlv::NdnlpFragIndex);
55 }
56
57 // NdnlpSequence
58 uint64_t sequenceBE = htobe64(seq);
59 size_t sequenceLength = blk.prependByteArray(
60 reinterpret_cast<uint8_t*>(&sequenceBE), sizeof(sequenceBE));
61 totalLength += sequenceLength;
62 totalLength += blk.prependVarNumber(sequenceLength);
63 totalLength += blk.prependVarNumber(tlv::NdnlpSequence);
64
65 totalLength += blk.prependVarNumber(totalLength);
66 totalLength += blk.prependVarNumber(tlv::NdnlpData);
67
68 return totalLength;
69}
70
71void
72Slicer::estimateOverhead()
73{
74 ndn::EncodingEstimator estimator;
75 size_t estimatedSize = Slicer_encodeFragment(estimator,
76 0, 0, 2, 0, m_mtu);
77
78 size_t overhead = estimatedSize - m_mtu;
79 m_maxPayload = m_mtu - overhead;
80}
81
82PacketArray
83Slicer::slice(const Block& block)
84{
85 BOOST_ASSERT(block.hasWire());
86 const uint8_t* networkPacket = block.wire();
87 size_t networkPacketSize = block.size();
88
89 uint16_t fragCount = static_cast<uint16_t>(
90 (networkPacketSize / m_maxPayload) +
91 (networkPacketSize % m_maxPayload == 0 ? 0 : 1)
92 );
93 PacketArray pa = make_shared<std::vector<Block> >();
94 pa->reserve(fragCount);
95 SequenceBlock seqBlock = m_seqgen.nextBlock(fragCount);
96
97 for (uint16_t fragIndex = 0; fragIndex < fragCount; ++fragIndex) {
98 size_t payloadOffset = fragIndex * m_maxPayload;
99 const uint8_t* payload = networkPacket + payloadOffset;
100 size_t payloadSize = std::min(m_maxPayload, networkPacketSize - payloadOffset);
101
102 ndn::EncodingBuffer buffer(m_mtu, 0);
103 size_t pktSize = Slicer_encodeFragment(buffer,
104 seqBlock[fragIndex], fragIndex, fragCount, payload, payloadSize);
105
106 BOOST_ASSERT(pktSize <= m_mtu);
107
108 pa->push_back(buffer.block());
109 }
110
111 return pa;
112}
113
114} // namespace ndnlp
115} // namespace nfd