Sponge
CS144's user-space TCP library
util.cc
Go to the documentation of this file.
1 #include "util.hh"
2 
3 #include <array>
4 #include <cctype>
5 #include <chrono>
6 #include <iomanip>
7 #include <iostream>
8 #include <sstream>
9 #include <sys/socket.h>
10 
11 using namespace std;
12 
15  using time_point = std::chrono::steady_clock::time_point;
16  static const time_point program_start = std::chrono::steady_clock::now();
17  const time_point now = std::chrono::steady_clock::now();
18  return std::chrono::duration_cast<std::chrono::milliseconds>(now - program_start).count();
19 }
20 
42 int SystemCall(const char *attempt, const int return_value, const int errno_mask) {
43  if (return_value >= 0 || errno == errno_mask) {
44  return return_value;
45  }
46 
47  throw unix_error(attempt);
48 }
49 
54 int SystemCall(const string &attempt, const int return_value, const int errno_mask) {
55  return SystemCall(attempt.c_str(), return_value, errno_mask);
56 }
57 
65  auto rd = random_device();
67  generate(seed_data.begin(), seed_data.end(), [&] { return rd(); });
68  seed_seq seed(seed_data.begin(), seed_data.end());
69  return mt19937(seed);
70 }
71 
87 InternetChecksum::InternetChecksum(const uint32_t initial_sum) : _sum(initial_sum) {}
88 
89 void InternetChecksum::add(std::string_view data) {
90  for (size_t i = 0; i < data.size(); i++) {
91  uint16_t val = uint8_t(data[i]);
92  if (not _parity) {
93  val <<= 8;
94  }
95  _sum += val;
96  _parity = !_parity;
97  }
98 }
99 
101  uint32_t ret = _sum;
102 
103  while (ret > 0xffff) {
104  ret = (ret >> 16) + (ret & 0xffff);
105  }
106 
107  return ~ret;
108 }
109 
113 void hexdump(const uint8_t *data, const size_t len, const size_t indent) {
114  const auto flags(cout.flags());
115  const string indent_string(indent, ' ');
116  int printed = 0;
117  stringstream pchars(" ");
118  cout << hex << setfill('0');
119  for (unsigned i = 0; i < len; ++i) {
120  if ((printed & 0xf) == 0) {
121  if (printed != 0) {
122  cout << " " << pchars.str() << "\n";
123  pchars.str(" ");
124  }
125  cout << indent_string << setw(8) << printed << ": ";
126  } else if ((printed & 1) == 0) {
127  cout << ' ';
128  }
129  cout << setw(2) << +data[i];
130  pchars << (static_cast<bool>(isprint(data[i])) ? static_cast<char>(data[i]) : '.');
131  printed += 1;
132  }
133  const int print_rem = (16 - (printed & 0xf)) % 16; // extra spacing before final chars
134  cout << string(2 * print_rem + print_rem / 2 + 4, ' ') << pchars.str();
135  cout << '\n' << endl;
136  cout.flags(flags);
137 }
138 
142 void hexdump(const char *data, const size_t len, const size_t indent) {
143  hexdump(reinterpret_cast<const uint8_t *>(data), len, indent);
144 }
util.hh
std::string
len
constexpr size_t len
Definition: tcp_benchmark.cc:12
InternetChecksum::add
void add(std::string_view data)
Definition: util.cc:89
get_random_generator
mt19937 get_random_generator()
Seed a fast random generator.
Definition: util.cc:64
std::stringstream
InternetChecksum::value
uint16_t value() const
Definition: util.cc:100
std::generate
T generate(T... args)
std::setfill
T setfill(T... args)
SystemCall
int SystemCall(const char *attempt, const int return_value, const int errno_mask)
Error-checking wrapper for most syscalls.
Definition: util.cc:42
timestamp_ms
uint64_t timestamp_ms()
Get the time in milliseconds since the program began.
Definition: util.cc:14
std::hex
T hex(T... args)
std::mt19937
std::random_device
std::cout
std::string::c_str
T c_str(T... args)
std::array
InternetChecksum::InternetChecksum
InternetChecksum(const uint32_t initial_sum=0)
Definition: util.cc:87
std::isprint
T isprint(T... args)
std::uint64_t
InternetChecksum::_parity
bool _parity
Definition: util.hh:58
std::endl
T endl(T... args)
unix_error
a tagged_error for syscalls
Definition: util.hh:33
std::seed_seq
std
std::stringstream::str
T str(T... args)
std::setw
T setw(T... args)
hexdump
void hexdump(const uint8_t *data, const size_t len, const size_t indent)
Definition: util.cc:113
InternetChecksum::_sum
uint32_t _sum
Definition: util.hh:57
std::chrono::steady_clock::now
T now(T... args)