]> git.sesse.net Git - greproxy/blob - pacer.cpp
Merge branch 'master' of /srv/git.sesse.net/www/greproxy
[greproxy] / pacer.cpp
1 #include "pacer.h"
2 #include "timeutil.h"
3
4 #include <algorithm>
5
6 using namespace std;
7
8 Pacer::Pacer(Sender *sender, int max_rate_kbit_per_sec, int burst_num_packets)
9         : sender(sender), burst_num_packets(burst_num_packets), next_send_packet{0, 0}
10 {
11         const int max_rate_byte_per_sec = 1000 * max_rate_kbit_per_sec / 8;
12         seconds_per_byte = 1.0 / max_rate_byte_per_sec;
13 }
14
15 void Pacer::send_packet(uint16_t proto, const string &data, uint32_t incoming_seq)
16 {
17         waiting_packets.push_back(GREPacket{incoming_seq, proto, data, {0, 0}});
18         possibly_flush_packets();
19 }
20
21 void Pacer::possibly_adjust_tv(timeval *tv)
22 {
23         if (waiting_packets.empty()) {
24                 return;
25         }
26
27         timeval now;
28         gettimeofday(&now, NULL);
29
30         timeval tdiff = subtract_timeval_saturate(next_send_packet, now);
31         if (less_than(tdiff, *tv)) {
32                 *tv = tdiff;
33         }
34 }
35
36 void Pacer::possibly_flush_packets()
37 {
38         if (waiting_packets.empty()) {
39                 return;
40         }
41
42         timeval now;
43         gettimeofday(&now, NULL);
44         if (less_than(now, next_send_packet)) {
45                 return;
46         }
47
48         int bytes_sent = 0;
49         for (int i = 0; i < burst_num_packets && !waiting_packets.empty(); ++i) {
50                 const GREPacket &packet = waiting_packets.front();
51                 sender->send_packet(packet.proto, packet.data, packet.seq);
52                 bytes_sent += packet.data.size();
53                 waiting_packets.pop_front();
54         }
55
56         next_send_packet = offset_timeval_seconds(now, seconds_per_byte * bytes_sent);
57 }
58