xref: /llvm-project/lldb/include/lldb/Host/Socket.h (revision 384562495bae44be053c1bbd40c359ef4b82d803)
1 //===-- Socket.h ------------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLDB_HOST_SOCKET_H
10 #define LLDB_HOST_SOCKET_H
11 
12 #include <memory>
13 #include <string>
14 #include <vector>
15 
16 #include "lldb/Host/MainLoopBase.h"
17 #include "lldb/Utility/Timeout.h"
18 #include "lldb/lldb-private.h"
19 
20 #include "lldb/Host/SocketAddress.h"
21 #include "lldb/Utility/IOObject.h"
22 #include "lldb/Utility/Status.h"
23 
24 #ifdef _WIN32
25 #include "lldb/Host/Pipe.h"
26 #include "lldb/Host/windows/windows.h"
27 #include <winsock2.h>
28 #include <ws2tcpip.h>
29 #endif
30 
31 namespace llvm {
32 class StringRef;
33 }
34 
35 namespace lldb_private {
36 
37 #if defined(_WIN32)
38 typedef SOCKET NativeSocket;
39 typedef lldb::pipe_t shared_fd_t;
40 #else
41 typedef int NativeSocket;
42 typedef NativeSocket shared_fd_t;
43 #endif
44 class Socket;
45 class TCPSocket;
46 class UDPSocket;
47 
48 class SharedSocket {
49 public:
50   static const shared_fd_t kInvalidFD;
51 
52   SharedSocket(const Socket *socket, Status &error);
53 
54   shared_fd_t GetSendableFD() { return m_fd; }
55 
56   Status CompleteSending(lldb::pid_t child_pid);
57 
58   static Status GetNativeSocket(shared_fd_t fd, NativeSocket &socket);
59 
60 private:
61 #ifdef _WIN32
62   Pipe m_socket_pipe;
63   NativeSocket m_socket;
64 #endif
65   shared_fd_t m_fd;
66 };
67 
68 class Socket : public IOObject {
69 public:
70   enum SocketProtocol {
71     ProtocolTcp,
72     ProtocolUdp,
73     ProtocolUnixDomain,
74     ProtocolUnixAbstract
75   };
76 
77   struct HostAndPort {
78     std::string hostname;
79     uint16_t port;
80 
81     bool operator==(const HostAndPort &R) const {
82       return port == R.port && hostname == R.hostname;
83     }
84   };
85 
86   static const NativeSocket kInvalidSocketValue;
87 
88   ~Socket() override;
89 
90   static const char *FindSchemeByProtocol(const SocketProtocol protocol);
91   static bool FindProtocolByScheme(const char *scheme,
92                                    SocketProtocol &protocol);
93 
94   static llvm::Error Initialize();
95   static void Terminate();
96 
97   static std::unique_ptr<Socket> Create(const SocketProtocol protocol,
98                                         Status &error);
99 
100   virtual Status Connect(llvm::StringRef name) = 0;
101   virtual Status Listen(llvm::StringRef name, int backlog) = 0;
102 
103   // Use the provided main loop instance to accept new connections. The callback
104   // will be called (from MainLoop::Run) for each new connection. This function
105   // does not block.
106   virtual llvm::Expected<std::vector<MainLoopBase::ReadHandleUP>>
107   Accept(MainLoopBase &loop,
108          std::function<void(std::unique_ptr<Socket> socket)> sock_cb) = 0;
109 
110   // Accept a single connection and "return" it in the pointer argument. This
111   // function blocks until the connection arrives.
112   virtual Status Accept(const Timeout<std::micro> &timeout, Socket *&socket);
113 
114   // Initialize a Tcp Socket object in listening mode.  listen and accept are
115   // implemented separately because the caller may wish to manipulate or query
116   // the socket after it is initialized, but before entering a blocking accept.
117   static llvm::Expected<std::unique_ptr<TCPSocket>>
118   TcpListen(llvm::StringRef host_and_port, int backlog = 5);
119 
120   static llvm::Expected<std::unique_ptr<Socket>>
121   TcpConnect(llvm::StringRef host_and_port);
122 
123   static llvm::Expected<std::unique_ptr<UDPSocket>>
124   UdpConnect(llvm::StringRef host_and_port);
125 
126   static int GetOption(NativeSocket sockfd, int level, int option_name,
127                        int &option_value);
128   int GetOption(int level, int option_name, int &option_value) {
129     return GetOption(m_socket, level, option_name, option_value);
130   };
131 
132   static int SetOption(NativeSocket sockfd, int level, int option_name,
133                        int option_value);
134   int SetOption(int level, int option_name, int option_value) {
135     return SetOption(m_socket, level, option_name, option_value);
136   };
137 
138   NativeSocket GetNativeSocket() const { return m_socket; }
139   SocketProtocol GetSocketProtocol() const { return m_protocol; }
140 
141   Status Read(void *buf, size_t &num_bytes) override;
142   Status Write(const void *buf, size_t &num_bytes) override;
143 
144   Status Close() override;
145 
146   bool IsValid() const override { return m_socket != kInvalidSocketValue; }
147   WaitableHandle GetWaitableHandle() override;
148 
149   static llvm::Expected<HostAndPort>
150   DecodeHostAndPort(llvm::StringRef host_and_port);
151 
152   // If this Socket is connected then return the URI used to connect.
153   virtual std::string GetRemoteConnectionURI() const { return ""; };
154 
155   // If the Socket is listening then return the URI for clients to connect.
156   virtual std::vector<std::string> GetListeningConnectionURI() const {
157     return {};
158   }
159 
160 protected:
161   Socket(SocketProtocol protocol, bool should_close);
162 
163   virtual size_t Send(const void *buf, const size_t num_bytes);
164 
165   static int CloseSocket(NativeSocket sockfd);
166   static Status GetLastError();
167   static void SetLastError(Status &error);
168   static NativeSocket CreateSocket(const int domain, const int type,
169                                    const int protocol, Status &error);
170   static NativeSocket AcceptSocket(NativeSocket sockfd, struct sockaddr *addr,
171                                    socklen_t *addrlen, Status &error);
172 
173   SocketProtocol m_protocol;
174   NativeSocket m_socket;
175   bool m_should_close_fd;
176 };
177 
178 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
179                               const Socket::HostAndPort &HP);
180 
181 } // namespace lldb_private
182 
183 #endif // LLDB_HOST_SOCKET_H
184