File: client.h

package info (click to toggle)
cubemap 1.4.2-1
  • links: PTS
  • area: main
  • in suites: buster
  • size: 844 kB
  • sloc: ansic: 8,155; cpp: 5,539; sh: 114; perl: 112; makefile: 63
file content (146 lines) | stat: -rw-r--r-- 5,113 bytes parent folder | download | duplicates (3)
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
134
135
136
137
138
139
140
141
142
143
144
145
146
#ifndef _CLIENT_H
#define _CLIENT_H 1

// A Client represents a single connection from a client (watching a single stream).

#include <stddef.h>
#include <time.h>

#include <memory>
#include <string>
#include <unordered_map>
#include <vector>

#include "tlse.h"

class ClientProto;
struct Stream;

// Digested statistics for writing to logs etc.
// Note that "referer" and "user_agent" here are already escaped for scary characters.
struct ClientStats {
	std::string url;
	int sock;
	std::string remote_addr;
	std::string referer;
	std::string user_agent;
	timespec connect_time;
	size_t bytes_sent;
	size_t bytes_lost;
	size_t num_loss_events;
	std::string hls_zombie_key;
};

struct Client {
	Client(int sock);

	// Serialization/deserialization.
	Client(const ClientProto &serialized, const std::vector<std::shared_ptr<const std::string>> &short_responses, Stream *stream);
	ClientProto serialize(std::unordered_map<const std::string *, size_t> *short_response_pool) const;

	ClientStats get_stats() const;

	std::string get_hls_zombie_key() const {
		if (x_playback_session_id.empty()) {
			return remote_addr;
		} else {
			return x_playback_session_id;
		}
	}

	// The file descriptor associated with this socket.
	int sock;

	// When the client connected (or went into keepalive), in terms of CLOCK_MONOTONIC_COARSE.
	timespec connect_time;

	// Some information only used for logging.
	std::string remote_addr;
	std::string referer;
	std::string user_agent;
	std::string x_playback_session_id;

	enum State { READING_REQUEST, SENDING_HEADER, SENDING_DATA, SENDING_SHORT_RESPONSE, WAITING_FOR_KEYFRAME, PREBUFFERING };
	State state = READING_REQUEST;

	// The HTTP request, as sent by the client. If we are in READING_REQUEST,
	// this might not be finished.
	std::string request;

	// What stream we're connecting to; parsed from <request>.
	// Not relevant for READING_REQUEST.
	std::string url;
	Stream *stream = nullptr;

	// If true, we don't actually serve the stream, but its HLS playlist.
	// TODO: Maybe this shouldn't be part of Client, since it's only
	// really used in communicating once from parse_request() to
	// process_client(); it's not permanent state (and is not serialized).
	bool serving_hls_playlist = false;

	// Whether we should close the connection after sending the response.
	// Not relevant for READING_REQUEST. Must be true if http_11 is false.
	bool close_after_response;

	// Whether the request came in over HTTP/1.1 or higher.
	bool http_11;

	// The header we want to send, or the response with headers if we know
	// it in its entirety after reading the request (typically an error).
	// This is nominally a copy of Stream::header, but since that might
	// change on reconnects etc., we keep a local copy here. Only relevant
	// for SENDING_HEADER or SENDING_SHORT_RESPONSE; blank otherwise.
	//
	// Must start with the string "HTTP/1.0 ", which will be changed to 1.1
	// if relevant.
	const std::string *header_or_short_response = nullptr;

	// <header_or_short_response> can come from two distinct places; it can be
	// local to the Client object, or it can be shared between many Clients
	// (typically HLS playlists, that can be so large that they are expensive
	// to hold in many copies). <header_or_short_response> will point to exactly
	// one of these, which should be cleared out/dereferenced when it is
	// no longer needed.
	//
	// The use of shared_ptr is somewhat overkill since we don't need
	// to access the HLS playlists from multiple threads, but it's not a
	// big deal for us.
	std::string header_or_short_response_holder;
	std::shared_ptr<const std::string> header_or_short_response_ref;

	// Number of bytes we've sent of the header. Only relevant for SENDING_HEADER
	// or SENDING_SHORT_RESPONSE.
	size_t header_or_short_response_bytes_sent = 0;

	// Number of bytes we are into the stream (ie., the end of last send).
	// -1 means we want to send from the end of the backlog (the normal case),
	// although only at a keyframe.
	// -2 means we want to send from the _beginning_ of the backlog.
	// -3 means we sent the header only.
	static const uint64_t STREAM_POS_AT_END = -1;
	static const uint64_t STREAM_POS_AT_START = -2;
	static const uint64_t STREAM_POS_HEADER_ONLY = -3;

	// Once we go into WAITING_FOR_KEYFRAME, PREBUFFERING or SENDING_DATA,
	// these negative values will be translated to real numbers.
	uint64_t stream_pos = 0;

	// Position at which to end the stream (one-past-the-end, used for fragments).
	// -1 means never to end; this is the common case.
	static const uint64_t STREAM_POS_NO_END = -1;
	uint64_t stream_pos_end = 0;

	// Number of bytes we've sent of data. Only relevant for SENDING_DATA.
	uint64_t bytes_sent = 0;

	// Number of times we've skipped forward due to the backlog being too big,
	// and how many bytes we've skipped over in all. Only relevant for SENDING_DATA.
	uint64_t bytes_lost = 0, num_loss_events = 0;

	TLSContext *tls_context = nullptr;
	const unsigned char *tls_data_to_send = nullptr;
	unsigned tls_data_left_to_send = 0;
	bool in_ktls_mode = false;
};

#endif  // !defined(_CLIENT_H)