1 // Copyright 2022 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef QUICHE_QUIC_CORE_IO_EVENT_LOOP_CONNECTING_CLIENT_SOCKET_H_
6 #define QUICHE_QUIC_CORE_IO_EVENT_LOOP_CONNECTING_CLIENT_SOCKET_H_
7 
8 #include <optional>
9 #include <string>
10 
11 #include "absl/status/status.h"
12 #include "absl/strings/string_view.h"
13 #include "absl/types/variant.h"
14 #include "quiche/quic/core/connecting_client_socket.h"
15 #include "quiche/quic/core/io/quic_event_loop.h"
16 #include "quiche/quic/core/io/socket.h"
17 #include "quiche/quic/core/quic_types.h"
18 #include "quiche/quic/platform/api/quic_socket_address.h"
19 #include "quiche/common/platform/api/quiche_export.h"
20 #include "quiche/common/quiche_buffer_allocator.h"
21 
22 namespace quic {
23 
24 // A connection-based client socket implemented using an underlying
25 // QuicEventLoop.
26 class EventLoopConnectingClientSocket : public ConnectingClientSocket,
27                                         public QuicSocketEventListener {
28  public:
29   // Will use platform default buffer size if `receive_buffer_size` or
30   // `send_buffer_size` is zero. `async_visitor` may be null if no async
31   // operations will be  requested. `event_loop`, `buffer_allocator`, and
32   // `async_visitor` (if non-null) must outlive the created socket.
33   EventLoopConnectingClientSocket(
34       socket_api::SocketProtocol protocol,
35       const quic::QuicSocketAddress& peer_address,
36       QuicByteCount receive_buffer_size, QuicByteCount send_buffer_size,
37       QuicEventLoop* event_loop,
38       quiche::QuicheBufferAllocator* buffer_allocator,
39       AsyncVisitor* async_visitor);
40 
41   ~EventLoopConnectingClientSocket() override;
42 
43   // ConnectingClientSocket:
44   absl::Status ConnectBlocking() override;
45   void ConnectAsync() override;
46   void Disconnect() override;
47   absl::StatusOr<QuicSocketAddress> GetLocalAddress() override;
48   absl::StatusOr<quiche::QuicheMemSlice> ReceiveBlocking(
49       QuicByteCount max_size) override;
50   void ReceiveAsync(QuicByteCount max_size) override;
51   absl::Status SendBlocking(std::string data) override;
52   absl::Status SendBlocking(quiche::QuicheMemSlice data) override;
53   void SendAsync(std::string data) override;
54   void SendAsync(quiche::QuicheMemSlice data) override;
55 
56   // QuicSocketEventListener:
57   void OnSocketEvent(QuicEventLoop* event_loop, SocketFd fd,
58                      QuicSocketEventMask events) override;
59 
60  private:
61   enum class ConnectStatus {
62     kNotConnected,
63     kConnecting,
64     kConnected,
65   };
66 
67   absl::Status Open();
68   void Close();
69   absl::Status DoInitialConnect();
70   absl::Status GetConnectResult();
71   void FinishOrRearmAsyncConnect(absl::Status status);
72   absl::StatusOr<quiche::QuicheMemSlice> ReceiveInternal();
73   void FinishOrRearmAsyncReceive(absl::StatusOr<quiche::QuicheMemSlice> buffer);
74   // Returns `true` if a byte received, or `false` if successfully received
75   // empty data.
76   absl::StatusOr<bool> OneBytePeek();
77   absl::Status SendBlockingInternal();
78   absl::Status SendInternal();
79   void FinishOrRearmAsyncSend(absl::Status status);
80 
81   const socket_api::SocketProtocol protocol_;
82   const QuicSocketAddress peer_address_;
83   const QuicByteCount receive_buffer_size_;
84   const QuicByteCount send_buffer_size_;
85   QuicEventLoop* const event_loop_;                  // unowned
86   quiche::QuicheBufferAllocator* buffer_allocator_;  // unowned
87   AsyncVisitor* const async_visitor_;  // unowned, potentially null
88 
89   SocketFd descriptor_ = kInvalidSocketFd;
90   ConnectStatus connect_status_ = ConnectStatus::kNotConnected;
91 
92   // Only set while receive in progress or pending, otherwise nullopt.
93   std::optional<QuicByteCount> receive_max_size_;
94 
95   // Only contains data while send in progress or pending, otherwise monostate.
96   absl::variant<absl::monostate, std::string, quiche::QuicheMemSlice>
97       send_data_;
98   // Points to the unsent portion of `send_data_` while send in progress or
99   // pending, otherwise empty.
100   absl::string_view send_remaining_;
101 };
102 
103 }  // namespace quic
104 
105 #endif  // QUICHE_QUIC_CORE_IO_EVENT_LOOP_CONNECTING_CLIENT_SOCKET_H_
106