|  | // Copyright 2019 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "quic/masque/masque_server_session.h" | 
|  |  | 
|  | namespace quic { | 
|  |  | 
|  | MasqueServerSession::MasqueServerSession( | 
|  | const QuicConfig& config, | 
|  | const ParsedQuicVersionVector& supported_versions, | 
|  | QuicConnection* connection, | 
|  | QuicSession::Visitor* visitor, | 
|  | Visitor* owner, | 
|  | QuicCryptoServerStreamBase::Helper* helper, | 
|  | const QuicCryptoServerConfig* crypto_config, | 
|  | QuicCompressedCertsCache* compressed_certs_cache, | 
|  | MasqueServerBackend* masque_server_backend) | 
|  | : QuicSimpleServerSession(config, | 
|  | supported_versions, | 
|  | connection, | 
|  | visitor, | 
|  | helper, | 
|  | crypto_config, | 
|  | compressed_certs_cache, | 
|  | masque_server_backend), | 
|  | masque_server_backend_(masque_server_backend), | 
|  | owner_(owner), | 
|  | compression_engine_(this) { | 
|  | masque_server_backend_->RegisterBackendClient(connection_id(), this); | 
|  | } | 
|  |  | 
|  | void MasqueServerSession::OnMessageReceived(absl::string_view message) { | 
|  | QUIC_DVLOG(1) << "Received DATAGRAM frame of length " << message.length(); | 
|  |  | 
|  | QuicConnectionId client_connection_id, server_connection_id; | 
|  | QuicSocketAddress server_address; | 
|  | std::vector<char> packet; | 
|  | bool version_present; | 
|  | if (!compression_engine_.DecompressDatagram( | 
|  | message, &client_connection_id, &server_connection_id, | 
|  | &server_address, &packet, &version_present)) { | 
|  | return; | 
|  | } | 
|  |  | 
|  | QUIC_DVLOG(1) << "Received packet of length " << packet.size() << " for " | 
|  | << server_address << " client " << client_connection_id; | 
|  |  | 
|  | if (version_present) { | 
|  | if (client_connection_id.length() != kQuicDefaultConnectionIdLength) { | 
|  | QUIC_DLOG(ERROR) | 
|  | << "Dropping long header with invalid client_connection_id " | 
|  | << client_connection_id; | 
|  | return; | 
|  | } | 
|  | owner_->RegisterClientConnectionId(client_connection_id, this); | 
|  | } | 
|  |  | 
|  | WriteResult write_result = connection()->writer()->WritePacket( | 
|  | packet.data(), packet.size(), connection()->self_address().host(), | 
|  | server_address, nullptr); | 
|  | QUIC_DVLOG(1) << "Got " << write_result << " for " << packet.size() | 
|  | << " bytes to " << server_address; | 
|  | } | 
|  |  | 
|  | void MasqueServerSession::OnMessageAcked(QuicMessageId message_id, | 
|  | QuicTime /*receive_timestamp*/) { | 
|  | QUIC_DVLOG(1) << "Received ack for DATAGRAM frame " << message_id; | 
|  | } | 
|  |  | 
|  | void MasqueServerSession::OnMessageLost(QuicMessageId message_id) { | 
|  | QUIC_DVLOG(1) << "We believe DATAGRAM frame " << message_id << " was lost"; | 
|  | } | 
|  |  | 
|  | void MasqueServerSession::OnConnectionClosed( | 
|  | const QuicConnectionCloseFrame& /*frame*/, | 
|  | ConnectionCloseSource /*source*/) { | 
|  | QUIC_DLOG(INFO) << "Closing connection for " << connection_id(); | 
|  | masque_server_backend_->RemoveBackendClient(connection_id()); | 
|  | } | 
|  |  | 
|  | std::unique_ptr<QuicBackendResponse> MasqueServerSession::HandleMasqueRequest( | 
|  | const std::string& masque_path, | 
|  | const spdy::Http2HeaderBlock& /*request_headers*/, | 
|  | const std::string& request_body, | 
|  | QuicSimpleServerBackend::RequestHandler* /*request_handler*/) { | 
|  | QUIC_DLOG(INFO) << "MasqueServerSession handling MASQUE request"; | 
|  |  | 
|  | if (masque_path == "init") { | 
|  | if (masque_initialized_) { | 
|  | QUIC_DLOG(ERROR) << "Got second MASQUE init request"; | 
|  | return nullptr; | 
|  | } | 
|  | masque_initialized_ = true; | 
|  | } else if (masque_path == "unregister") { | 
|  | QuicConnectionId connection_id(request_body.data(), request_body.length()); | 
|  | QUIC_DLOG(INFO) << "Received MASQUE request to unregister " | 
|  | << connection_id; | 
|  | owner_->UnregisterClientConnectionId(connection_id); | 
|  | compression_engine_.UnregisterClientConnectionId(connection_id); | 
|  | } else { | 
|  | if (!masque_initialized_) { | 
|  | QUIC_DLOG(ERROR) << "Got MASQUE request before init"; | 
|  | return nullptr; | 
|  | } | 
|  | } | 
|  |  | 
|  | // TODO(dschinazi) implement binary protocol sent in response body. | 
|  | const std::string response_body = ""; | 
|  | spdy::Http2HeaderBlock response_headers; | 
|  | response_headers[":status"] = "200"; | 
|  | auto response = std::make_unique<QuicBackendResponse>(); | 
|  | response->set_response_type(QuicBackendResponse::REGULAR_RESPONSE); | 
|  | response->set_headers(std::move(response_headers)); | 
|  | response->set_body(response_body); | 
|  |  | 
|  | return response; | 
|  | } | 
|  |  | 
|  | void MasqueServerSession::HandlePacketFromServer( | 
|  | const ReceivedPacketInfo& packet_info) { | 
|  | QUIC_DVLOG(1) << "MasqueServerSession received " << packet_info; | 
|  | compression_engine_.CompressAndSendPacket( | 
|  | packet_info.packet.AsStringPiece(), packet_info.destination_connection_id, | 
|  | packet_info.source_connection_id, packet_info.peer_address); | 
|  | } | 
|  |  | 
|  | }  // namespace quic |