X-Git-Url: https://git.sesse.net/?p=cubemap;a=blobdiff_plain;f=server.cpp;h=093899939b4d832be6dd28a8a3e8966d46efa650;hp=879063339c9b2a6efca5a0c45fb0ce2e1633019b;hb=c2080e598ec887ac7b087dbc287c42a14881d667;hpb=ee1346294bd78efbba2b4f9108585467eee43f5a diff --git a/server.cpp b/server.cpp index 8790633..0938999 100644 --- a/server.cpp +++ b/server.cpp @@ -28,6 +28,10 @@ #include "stream.h" #include "util.h" +#ifndef SO_MAX_PACING_RATE +#define SO_MAX_PACING_RATE 47 +#endif + using namespace std; extern AccessLogThread *access_log; @@ -35,7 +39,7 @@ extern AccessLogThread *access_log; Server::Server() { pthread_mutex_init(&mutex, NULL); - pthread_mutex_init(&queued_data_mutex, NULL); + pthread_mutex_init(&queued_clients_mutex, NULL); epoll_fd = epoll_create(1024); // Size argument is ignored. if (epoll_fd == -1) { @@ -140,7 +144,7 @@ CubemapStateProto Server::serialize() void Server::add_client_deferred(int sock) { - MutexLock lock(&queued_data_mutex); + MutexLock lock(&queued_clients_mutex); queued_add_clients.push_back(sock); } @@ -248,19 +252,6 @@ void Server::set_header(int stream_index, const string &http_header, const strin assert(stream_index >= 0 && stream_index < ssize_t(streams.size())); streams[stream_index]->http_header = http_header; streams[stream_index]->stream_header = stream_header; - - // If there are clients we haven't sent anything to yet, we should give - // them the header, so push back into the SENDING_HEADER state. - for (map::iterator client_it = clients.begin(); - client_it != clients.end(); - ++client_it) { - Client *client = &client_it->second; - if (client->state == Client::WAITING_FOR_KEYFRAME || - (client->state == Client::SENDING_DATA && - client->stream_pos == 0)) { - construct_header(client); - } - } } void Server::set_mark_pool(int stream_index, MarkPool *mark_pool) @@ -271,9 +262,16 @@ void Server::set_mark_pool(int stream_index, MarkPool *mark_pool) streams[stream_index]->mark_pool = mark_pool; } +void Server::set_pacing_rate(int stream_index, uint32_t pacing_rate) +{ + MutexLock lock(&mutex); + assert(clients.empty()); + assert(stream_index >= 0 && stream_index < ssize_t(streams.size())); + streams[stream_index]->pacing_rate = pacing_rate; +} + void Server::add_data_deferred(int stream_index, const char *data, size_t bytes, StreamStartSuitability suitable_for_stream_start) { - MutexLock lock(&queued_data_mutex); assert(stream_index >= 0 && stream_index < ssize_t(streams.size())); streams[stream_index]->add_data_deferred(data, bytes, suitable_for_stream_start); } @@ -433,7 +431,7 @@ sending_data_again: ssize_t ret; do { - loff_t offset = client->stream_pos % stream->backlog_size; + off_t offset = client->stream_pos % stream->backlog_size; ret = sendfile(client->sock, stream->data_fd, &offset, bytes_to_send); } while (ret == -1 && errno == EINTR); @@ -471,6 +469,9 @@ sending_data_again: void Server::skip_lost_data(Client *client) { Stream *stream = client->stream; + if (stream == NULL) { + return; + } size_t bytes_to_send = stream->bytes_received - client->stream_pos; if (bytes_to_send > stream->backlog_size) { size_t bytes_lost = bytes_to_send - stream->backlog_size; @@ -514,8 +515,13 @@ int Server::parse_request(Client *client) return 404; // Not found. } + Stream *stream = streams[url_map_it->second]; + if (stream->http_header.empty()) { + return 503; // Service unavailable. + } + client->url = request_tokens[1]; - client->stream = streams[url_map_it->second]; + client->stream = stream; if (client->stream->mark_pool != NULL) { client->fwmark = client->stream->mark_pool->get_mark(); } else { @@ -526,6 +532,11 @@ int Server::parse_request(Client *client) log_perror("setsockopt(SO_MARK)"); } } + if (setsockopt(client->sock, SOL_SOCKET, SO_MAX_PACING_RATE, &client->stream->pacing_rate, sizeof(client->stream->pacing_rate)) == -1) { + if (client->stream->pacing_rate != ~0U) { + log_perror("setsockopt(SO_MAX_PACING_RATE)"); + } + } client->request.clear(); return 200; // OK! @@ -624,12 +635,14 @@ void Server::close_client(Client *client) void Server::process_queued_data() { - MutexLock lock(&queued_data_mutex); + { + MutexLock lock(&queued_clients_mutex); - for (size_t i = 0; i < queued_add_clients.size(); ++i) { - add_client(queued_add_clients[i]); + for (size_t i = 0; i < queued_add_clients.size(); ++i) { + add_client(queued_add_clients[i]); + } + queued_add_clients.clear(); } - queued_add_clients.clear(); for (size_t i = 0; i < streams.size(); ++i) { streams[i]->process_queued_data();