X-Git-Url: https://git.sesse.net/?p=cubemap;a=blobdiff_plain;f=server.cpp;h=ccac946726bf9710946ebb3a5612386ab0690e62;hp=2f55589ac75773af7494417e099b0b58112814db;hb=fe40a37edd195457e6771a36ac9807bf3ca4ceda;hpb=c687f8878c86e5895d0c4fd955695be0df2576a3 diff --git a/server.cpp b/server.cpp index 2f55589..ccac946 100644 --- a/server.cpp +++ b/server.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -748,6 +749,22 @@ sending_data_again: } } +namespace { + +void flush_pending_data(int sock) +{ + // Flush pending data, which would otherwise wait for the 200ms TCP_CORK timer + // to elapsed; does not cancel out TCP_CORK (since that still takes priority), + // but does a one-off flush. + int one = 1; + if (setsockopt(sock, SOL_TCP, TCP_NODELAY, &one, sizeof(one)) == -1) { + log_perror("setsockopt(TCP_NODELAY)"); + // Can still continue. + } +} + +} // namespace + bool Server::send_pending_tls_data(Client *client) { // See if there's data from the TLS library to write. @@ -780,9 +797,15 @@ send_data_again: return true; } if (ret > 0 && size_t(ret) == client->tls_data_left_to_send) { - // All data has been sent, so we don't need to go to sleep. + // All data has been sent, so we don't need to go to sleep + // (although we are likely to do so immediately afterwards, + // due to lack of client data). tls_buffer_clear(client->tls_context); client->tls_data_to_send = nullptr; + + // Flush the data we just wrote, since the client probably + // is waiting for it. + flush_pending_data(client->sock); return false; } @@ -891,7 +914,7 @@ void Server::skip_lost_data(Client *client) if (!client->close_after_response) { assert(client->stream_pos_end != Client::STREAM_POS_NO_END); - // We've already sent a Content-length, so we can't just skip data. + // We've already sent a Content-Length, so we can't just skip data. // Close the connection immediately and hope the other side // is able to figure out that there was an error and it needs to skip. client->close_after_response = true; @@ -911,8 +934,7 @@ int Server::parse_request(Client *client) } // Parse the headers, for logging purposes. - // TODO: Case-insensitivity. - unordered_multimap headers = extract_headers(lines, client->remote_addr); + HTTPHeaderMultimap headers = extract_headers(lines, client->remote_addr); const auto referer_it = headers.find("Referer"); if (referer_it != headers.end()) { client->referer = referer_it->second; @@ -1067,11 +1089,11 @@ void Server::construct_stream_header(Client *client) string response = stream->http_header; if (client->stream_pos == Client::STREAM_POS_HEADER_ONLY) { char buf[64]; - snprintf(buf, sizeof(buf), "Content-length: %zu\r\n", stream->stream_header.size()); + snprintf(buf, sizeof(buf), "Content-Length: %zu\r\n", stream->stream_header.size()); response.append(buf); } else if (client->stream_pos_end != Client::STREAM_POS_NO_END) { char buf[64]; - snprintf(buf, sizeof(buf), "Content-length: %" PRIu64 "\r\n", client->stream_pos_end - client->stream_pos); + snprintf(buf, sizeof(buf), "Content-Length: %" PRIu64 "\r\n", client->stream_pos_end - client->stream_pos); response.append(buf); } if (client->http_11) { @@ -1091,7 +1113,7 @@ void Server::construct_stream_header(Client *client) if (stream->encoding == Stream::STREAM_ENCODING_RAW) { response.append("\r\n"); } else if (stream->encoding == Stream::STREAM_ENCODING_METACUBE) { - response.append("Content-encoding: metacube\r\n\r\n"); + response.append("Content-Encoding: metacube\r\n\r\n"); if (!stream->stream_header.empty()) { metacube2_block_header hdr; memcpy(hdr.sync, METACUBE2_SYNC, sizeof(hdr.sync)); @@ -1125,11 +1147,11 @@ void Server::construct_error(Client *client, int error_code) char error[256]; if (client->http_11 && client->close_after_response) { snprintf(error, sizeof(error), - "HTTP/1.1 %d Error\r\nContent-type: text/plain\r\nConnection: close\r\n\r\nSomething went wrong. Sorry.\r\n", + "HTTP/1.1 %d Error\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\nSomething went wrong. Sorry.\r\n", error_code); } else { snprintf(error, sizeof(error), - "HTTP/1.%d %d Error\r\nContent-type: text/plain\r\nContent-length: 30\r\n\r\nSomething went wrong. Sorry.\r\n", + "HTTP/1.%d %d Error\r\nContent-Type: text/plain\r\nContent-Length: 30\r\n\r\nSomething went wrong. Sorry.\r\n", client->http_11, error_code); } client->header_or_short_response_holder = error; @@ -1291,13 +1313,7 @@ bool Server::more_requests(Client *client) // Log to access_log. access_log->write(client->get_stats()); - // Flush pending data; does not cancel out TCP_CORK (since that still takes priority), - // but does a one-off flush. - int one = 1; - if (setsockopt(client->sock, SOL_TCP, TCP_NODELAY, &one, sizeof(one)) == -1) { - log_perror("setsockopt(TCP_NODELAY)"); - // Can still continue. - } + flush_pending_data(client->sock); // Switch states and reset the parsers. We don't reset statistics. client->state = Client::READING_REQUEST;