summaryrefslogtreecommitdiffstats
path: root/net/curvecp/sent_block_list.cc
blob: 2eb55dcbff03a70cd78a660cd1b3dc78788bbb4a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/curvecp/sent_block_list.h"

#include "base/logging.h"
#include "net/base/io_buffer.h"

namespace net {

static const size_t kMaxBlocks = 128;

SentBlockList::SentBlockList()
    : current_message_id_(1),
      send_sequence_number_(0) {
}

SentBlockList::~SentBlockList() {
}

int64 SentBlockList::CreateBlock(IOBufferWithSize* buffer) {
  DCHECK_LT(0, buffer->size());

  if (is_full())
    return -1;

  Block new_block;
  new_block.position = send_sequence_number_;
  new_block.length = buffer->size();
  new_block.transmissions = 0;
  new_block.last_message_id = 0;
  new_block.data= buffer;

  send_sequence_number_ += buffer->size();
  list_.push_back(new_block);
  return new_block.position;
}

bool SentBlockList::MarkBlockSent(int64 position, int64 message_id) {
  int index = FindBlock(position);
  if (index < 0) {
    NOTREACHED();
    return false;
  }
  list_[index].last_message_id = message_id;
  list_[index].transmissions++;
  list_[index].last_sent_time = base::TimeTicks::Now();
  return true;
}

void SentBlockList::AcknowledgeBlocks(int64 begin_range, int64 end_range) {
  if (begin_range == end_range)
    return;

  // TODO(mbelshe): use a better data structure.
  LOG(ERROR) << "ACK of: " << begin_range << " to " << end_range;

  BlockList::iterator it = list_.begin();
  while (it != list_.end()) {
    int64 position = it->position;
    int64 length = it->length;
    if (position >= begin_range && (position + length) <= end_range) {
      list_.erase(it);
      it = list_.begin();  // iterator was invalidated, so go to start of list.
      continue;
    }

    // Verify we didn't have a partial block acknowledgement.
    CHECK(position < begin_range || position >= end_range);
    CHECK((position + length) < begin_range || (position + length) > end_range);
    it++;
  }
}

int64 SentBlockList::GetNewMessageId() {
  return current_message_id_++;
}

IOBufferWithSize* SentBlockList::FindBlockByPosition(int64 position) const {
  int index = FindBlock(position);
  if (index < 0)
    return NULL;
  return list_[index].data;
}

base::TimeTicks SentBlockList::FindLastSendTime(int64 last_message_id) const {
  for (size_t index = 0; index < list_.size(); ++index)
    if (list_[index].last_message_id == last_message_id)
      return list_[index].last_sent_time;
  return base::TimeTicks();
}

int SentBlockList::FindBlock(int64 position) const {
  for (size_t index = 0; index < list_.size(); ++index)
    if (list_[index].position == position)
      return index;
  return -1;
}

int64 SentBlockList::FindPositionOfOldestSentBlock() const {
  base::TimeTicks oldest_time;
  int64 position = -1;

  LogBlockList();

  // Walks the entire list.
  for (size_t index = 0; index < list_.size(); ++index) {
    base::TimeTicks last_sent_time = list_[index].last_sent_time;
    if (!last_sent_time.is_null()) {
      if (last_sent_time < oldest_time || oldest_time.is_null()) {
        oldest_time = last_sent_time;
        position = list_[index].position;
      }
    }
  }
  return position;
}
bool SentBlockList::is_full() const {
  return list_.size() == kMaxBlocks;
}

void SentBlockList::LogBlockList() const {
  LOG(INFO) << "Sent Blocks: " << list_.size();
  std::string msg;
  std::ostringstream stream(msg);
  for (size_t index = 0; index < list_.size(); ++index)
     stream << "(" << list_[index].position
            << "," << list_[index].length << ")";
  LOG(INFO) << stream.str();
}

}  // namespace net