• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 #pragma once
15 
16 #include <netinet/in.h>
17 
18 #include <cstdint>
19 
20 #include "pw_result/result.h"
21 #include "pw_span/span.h"
22 #include "pw_stream/stream.h"
23 
24 namespace pw::stream {
25 
26 class SocketStream : public NonSeekableReaderWriter {
27  public:
28   constexpr SocketStream() = default;
29 
30   // SocketStream objects are moveable but not copyable.
31   SocketStream& operator=(SocketStream&& other) {
32     listen_port_ = other.listen_port_;
33     socket_fd_ = other.socket_fd_;
34     other.socket_fd_ = kInvalidFd;
35     connection_fd_ = other.connection_fd_;
36     other.connection_fd_ = kInvalidFd;
37     sockaddr_client_ = other.sockaddr_client_;
38     return *this;
39   }
SocketStream(SocketStream && other)40   SocketStream(SocketStream&& other) noexcept
41       : listen_port_(other.listen_port_),
42         socket_fd_(other.socket_fd_),
43         connection_fd_(other.connection_fd_),
44         sockaddr_client_(other.sockaddr_client_) {
45     other.socket_fd_ = kInvalidFd;
46     other.connection_fd_ = kInvalidFd;
47   }
48   SocketStream(const SocketStream&) = delete;
49   SocketStream& operator=(const SocketStream&) = delete;
50 
~SocketStream()51   ~SocketStream() override { Close(); }
52 
53   // Listen to the port and return after a client is connected
54   //
55   // DEPRECATED: Use the ServerSocket class instead.
56   // TODO(b/271323032): Remove when this method is no longer used.
57   Status Serve(uint16_t port);
58 
59   // Connect to a local or remote endpoint. Host may be either an IPv4 or IPv6
60   // address. If host is nullptr then the IPv4 localhost address is used
61   // instead.
62   Status Connect(const char* host, uint16_t port);
63 
64   // Close the socket stream and release all resources
65   void Close();
66 
67   // Exposes the file descriptor for the active connection. This is exposed to
68   // allow configuration and introspection of this socket's current
69   // configuration using setsockopt() and getsockopt().
70   //
71   // Returns -1 if there is no active connection.
connection_fd()72   int connection_fd() { return connection_fd_; }
73 
74  private:
75   friend class ServerSocket;
76 
77   static constexpr int kInvalidFd = -1;
78 
79   Status DoWrite(span<const std::byte> data) override;
80 
81   StatusWithSize DoRead(ByteSpan dest) override;
82 
83   uint16_t listen_port_ = 0;
84   int socket_fd_ = kInvalidFd;
85   int connection_fd_ = kInvalidFd;
86   struct sockaddr_in sockaddr_client_ = {};
87 };
88 
89 /// `ServerSocket` wraps a POSIX-style server socket, producing a `SocketStream`
90 /// for each accepted client connection.
91 ///
92 /// Call `Listen` to create the socket and start listening for connections.
93 /// Then call `Accept` any number of times to accept client connections.
94 class ServerSocket {
95  public:
96   ServerSocket() = default;
~ServerSocket()97   ~ServerSocket() { Close(); }
98 
99   ServerSocket(const ServerSocket& other) = delete;
100   ServerSocket& operator=(const ServerSocket& other) = delete;
101 
102   // Listen for connections on the given port.
103   // If port is 0, a random unused port is chosen and can be retrieved with
104   // port().
105   Status Listen(uint16_t port = 0);
106 
107   // Accept a connection. Blocks until after a client is connected.
108   // On success, returns a SocketStream connected to the new client.
109   Result<SocketStream> Accept();
110 
111   // Close the server socket, preventing further connections.
112   void Close();
113 
114   // Returns the port this socket is listening on.
port()115   uint16_t port() const { return port_; }
116 
117  private:
118   static constexpr int kInvalidFd = -1;
119 
120   uint16_t port_ = -1;
121   int socket_fd_ = kInvalidFd;
122 };
123 
124 }  // namespace pw::stream
125