X-Git-Url: https://git.sesse.net/?p=cubemap;a=blobdiff_plain;f=server.cpp;h=0e056fb51f49b80a6af43baf28428aa965d3b2a5;hp=ceb7f3d80b7c96db81fe4dda0d3bf0d16d15ce48;hb=fa431bfab848624c2490a1134e084e6c1dd0dbfa;hpb=81253bd40254831a82a3d87c3ed7f2a3524f2f57 diff --git a/server.cpp b/server.cpp index ceb7f3d..0e056fb 100644 --- a/server.cpp +++ b/server.cpp @@ -19,6 +19,7 @@ #include #include +#include "ktls.h" #include "tlse.h" #include "acceptor.h" @@ -890,7 +891,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; @@ -910,8 +911,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; @@ -1066,11 +1066,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) { @@ -1090,7 +1090,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)); @@ -1124,11 +1124,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; @@ -1195,12 +1195,49 @@ void Server::construct_204(Client *client) change_epoll_events(client, EPOLLOUT | EPOLLET | EPOLLRDHUP); } +namespace { + template void delete_from(vector *v, T elem) { typename vector::iterator new_end = remove(v->begin(), v->end(), elem); v->erase(new_end, v->end()); } + +void send_ktls_close(int sock) +{ + uint8_t record_type = 21; // Alert. + uint8_t body[] = { + 1, // Warning level (but still fatal!). + 0, // close_notify. + }; + + int cmsg_len = sizeof(record_type); + char buf[CMSG_SPACE(cmsg_len)]; + + msghdr msg = {0}; + msg.msg_control = buf; + msg.msg_controllen = sizeof(buf); + cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level = SOL_TLS; + cmsg->cmsg_type = TLS_SET_RECORD_TYPE; + cmsg->cmsg_len = CMSG_LEN(cmsg_len); + *CMSG_DATA(cmsg) = record_type; + msg.msg_controllen = cmsg->cmsg_len; + + iovec msg_iov; + msg_iov.iov_base = body; + msg_iov.iov_len = sizeof(body); + msg.msg_iov = &msg_iov; + msg.msg_iovlen = 1; + + int err; + do { + err = sendmsg(sock, &msg, 0); + } while (err == -1 && errno == EINTR); // Ignore all other errors. +} + +} // namespace void Server::close_client(Client *client) { @@ -1216,6 +1253,10 @@ void Server::close_client(Client *client) } if (client->tls_context) { + if (client->in_ktls_mode) { + // Keep GnuTLS happy. + send_ktls_close(client->sock); + } tls_destroy_context(client->tls_context); }