]> git.sesse.net Git - cubemap/blob - client.cpp
Bump version number to 0.2; it's about time.
[cubemap] / client.cpp
1 #include <arpa/inet.h>
2 #include <netinet/in.h>
3 #include <stdint.h>
4 #include <sys/socket.h>
5
6 #include "client.h"
7 #include "log.h"
8 #include "markpool.h"
9 #include "state.pb.h"
10 #include "stream.h"
11
12 using namespace std;
13
14 Client::Client(int sock)
15         : sock(sock),
16           fwmark(0),
17           connect_time(time(NULL)),
18           state(Client::READING_REQUEST),
19           stream(NULL),
20           header_or_error_bytes_sent(0),
21           stream_pos(0),
22           bytes_sent(0),
23           bytes_lost(0),
24           num_loss_events(0)
25 {
26         request.reserve(1024);
27
28         // Find the remote address, and convert it to ASCII.
29         sockaddr_in6 addr;
30         socklen_t addr_len = sizeof(addr);
31
32         if (getpeername(sock, reinterpret_cast<sockaddr *>(&addr), &addr_len) == -1) {
33                 log_perror("getpeername");
34                 remote_addr = "";
35                 return;
36         }
37
38         char buf[INET6_ADDRSTRLEN];
39         if (IN6_IS_ADDR_V4MAPPED(&addr.sin6_addr)) {
40                 // IPv4 address, really.
41                 if (inet_ntop(AF_INET, &addr.sin6_addr.s6_addr32[3], buf, sizeof(buf)) == NULL) {
42                         log_perror("inet_ntop");
43                         remote_addr = "";
44                 } else {
45                         remote_addr = buf;
46                 }
47         } else {
48                 if (inet_ntop(addr.sin6_family, &addr.sin6_addr, buf, sizeof(buf)) == NULL) {
49                         log_perror("inet_ntop");
50                         remote_addr = "";
51                 } else {
52                         remote_addr = buf;
53                 }
54         }
55 }
56         
57 Client::Client(const ClientProto &serialized, Stream *stream)
58         : sock(serialized.sock()),
59           remote_addr(serialized.remote_addr()),
60           connect_time(serialized.connect_time()),
61           state(State(serialized.state())),
62           request(serialized.request()),
63           url(serialized.url()),
64           stream(stream),
65           header_or_error(serialized.header_or_error()),
66           header_or_error_bytes_sent(serialized.header_or_error_bytes_sent()),
67           stream_pos(serialized.stream_pos()),
68           bytes_sent(serialized.bytes_sent()),
69           bytes_lost(serialized.bytes_lost()),
70           num_loss_events(serialized.num_loss_events())
71 {
72         if (stream != NULL && stream->mark_pool != NULL) {
73                 fwmark = stream->mark_pool->get_mark();
74         } else {
75                 fwmark = 0;  // No mark.
76         }
77         if (setsockopt(sock, SOL_SOCKET, SO_MARK, &fwmark, sizeof(fwmark)) == -1) {
78                 if (fwmark != 0) {
79                         log_perror("setsockopt(SO_MARK)");
80                 }
81                 fwmark = 0;
82         }
83 }
84
85 ClientProto Client::serialize() const
86 {
87         ClientProto serialized;
88         serialized.set_sock(sock);
89         serialized.set_remote_addr(remote_addr);
90         serialized.set_connect_time(connect_time);
91         serialized.set_state(state);
92         serialized.set_request(request);
93         serialized.set_url(url);
94         serialized.set_header_or_error(header_or_error);
95         serialized.set_header_or_error_bytes_sent(serialized.header_or_error_bytes_sent());
96         serialized.set_stream_pos(stream_pos);
97         serialized.set_bytes_sent(bytes_sent);
98         serialized.set_bytes_lost(bytes_lost);
99         serialized.set_num_loss_events(num_loss_events);
100         return serialized;
101 }
102         
103 ClientStats Client::get_stats() const
104 {
105         ClientStats stats;
106         if (url.empty()) {
107                 stats.url = "-";
108         } else {
109                 stats.url = url;
110         }
111         stats.sock = sock;
112         stats.fwmark = fwmark;
113         stats.remote_addr = remote_addr;
114         stats.connect_time = connect_time;
115         stats.bytes_sent = bytes_sent;
116         stats.bytes_lost = bytes_lost;
117         stats.num_loss_events = num_loss_events;
118         return stats;
119 }