17 Stream::Stream(const string &stream_id, size_t backlog_size, Encoding encoding)
18 : stream_id(stream_id),
20 data_fd(make_tempfile("")),
21 backlog_size(backlog_size),
36 } while (ret == -1 && errno == EINTR);
43 Stream::Stream(const StreamProto &serialized)
44 : stream_id(serialized.stream_id()),
45 http_header(serialized.http_header()),
46 stream_header(serialized.stream_header()),
47 encoding(Stream::STREAM_ENCODING_RAW), // Will be changed later.
48 data_fd(make_tempfile(serialized.data())),
49 backlog_size(serialized.backlog_size()),
50 bytes_received(serialized.bytes_received()),
57 // Split old-style headers into HTTP and video headers.
58 if (!serialized.header().empty()) {
59 string header = serialized.header();
60 size_t split = header.find("\r\n\r\n");
61 if (split == string::npos) {
65 http_header = header.substr(0, split + 2); // Split off the second \r\n.
66 stream_header = header.substr(split, string::npos);
71 StreamProto Stream::serialize()
73 StreamProto serialized;
74 serialized.set_http_header(http_header);
75 serialized.set_stream_header(stream_header);
76 if (!read_tempfile(data_fd, serialized.mutable_data())) { // Closes data_fd.
79 serialized.set_backlog_size(backlog_size);
80 serialized.set_bytes_received(bytes_received);
81 serialized.set_stream_id(stream_id);
86 void Stream::set_backlog_size(size_t new_size)
88 if (backlog_size == new_size) {
93 if (!read_tempfile(data_fd, &existing_data)) { // Closes data_fd.
97 // Unwrap the data so it's no longer circular.
98 if (bytes_received <= backlog_size) {
99 existing_data.resize(bytes_received);
101 size_t pos = bytes_received % backlog_size;
102 existing_data = existing_data.substr(pos, string::npos) +
103 existing_data.substr(0, pos);
106 // See if we need to discard data.
107 if (new_size < existing_data.size()) {
108 size_t to_discard = existing_data.size() - new_size;
109 existing_data = existing_data.substr(to_discard, string::npos);
112 // Create a new, empty data file.
113 data_fd = make_tempfile("");
114 backlog_size = new_size;
116 // Now cheat a bit by rewinding, and adding all the old data back.
117 bytes_received -= existing_data.size();
118 add_data(existing_data.data(), existing_data.size());
121 void Stream::put_client_to_sleep(Client *client)
123 sleeping_clients.push_back(client);
126 void Stream::add_data(const char *data, ssize_t bytes)
128 if (encoding == Stream::STREAM_ENCODING_RAW) {
129 add_data_raw(data, bytes);
130 } else if (encoding == STREAM_ENCODING_METACUBE) {
131 metacube_block_header hdr;
132 memcpy(hdr.sync, METACUBE_SYNC, sizeof(hdr.sync));
133 hdr.size = htonl(bytes);
134 hdr.flags = htonl(0);
136 char *block = new char[bytes + sizeof(hdr)];
137 memcpy(block, &hdr, sizeof(hdr));
138 memcpy(block + sizeof(hdr), data, bytes);
139 add_data_raw(block, bytes + sizeof(hdr));
146 void Stream::add_data_raw(const char *data, ssize_t bytes)
148 size_t pos = bytes_received % backlog_size;
149 bytes_received += bytes;
151 if (pos + bytes > backlog_size) {
152 ssize_t to_copy = backlog_size - pos;
153 while (to_copy > 0) {
154 int ret = pwrite(data_fd, data, to_copy, pos);
155 if (ret == -1 && errno == EINTR) {
159 log_perror("pwrite");
160 // Dazed and confused, but trying to continue...
172 int ret = pwrite(data_fd, data, bytes, pos);
173 if (ret == -1 && errno == EINTR) {
177 log_perror("pwrite");
178 // Dazed and confused, but trying to continue...
187 void Stream::wake_up_all_clients()
189 if (to_process.empty()) {
190 swap(sleeping_clients, to_process);
192 to_process.insert(to_process.end(), sleeping_clients.begin(), sleeping_clients.end());
193 sleeping_clients.clear();