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
15#include "lldb/lldb-private.h"
16
17#include "lldb/Host/SocketAddress.h"
18#include "lldb/Utility/IOObject.h"
19#include "lldb/Utility/Status.h"
20
21#ifdef _WIN32
22#include "lldb/Host/windows/windows.h"
23#include <winsock2.h>
24#include <ws2tcpip.h>
25#endif
26
27namespace llvm {
28class StringRef;
29}
30
31namespace lldb_private {
32
33#if defined(_WIN32)
34typedef SOCKET NativeSocket;
35#else
36typedef int NativeSocket;
37#endif
38class TCPSocket;
39class UDPSocket;
40
41class Socket : public IOObject {
42public:
43  enum SocketProtocol {
44    ProtocolTcp,
45    ProtocolUdp,
46    ProtocolUnixDomain,
47    ProtocolUnixAbstract
48  };
49
50  struct HostAndPort {
51    std::string hostname;
52    uint16_t port;
53
54    bool operator==(const HostAndPort &R) const {
55      return port == R.port && hostname == R.hostname;
56    }
57  };
58
59  static const NativeSocket kInvalidSocketValue;
60
61  ~Socket() override;
62
63  static llvm::Error Initialize();
64  static void Terminate();
65
66  static std::unique_ptr<Socket> Create(const SocketProtocol protocol,
67                                        bool child_processes_inherit,
68                                        Status &error);
69
70  virtual Status Connect(llvm::StringRef name) = 0;
71  virtual Status Listen(llvm::StringRef name, int backlog) = 0;
72  virtual Status Accept(Socket *&socket) = 0;
73
74  // Initialize a Tcp Socket object in listening mode.  listen and accept are
75  // implemented separately because the caller may wish to manipulate or query
76  // the socket after it is initialized, but before entering a blocking accept.
77  static llvm::Expected<std::unique_ptr<TCPSocket>>
78  TcpListen(llvm::StringRef host_and_port, bool child_processes_inherit,
79            int backlog = 5);
80
81  static llvm::Expected<std::unique_ptr<Socket>>
82  TcpConnect(llvm::StringRef host_and_port, bool child_processes_inherit);
83
84  static llvm::Expected<std::unique_ptr<UDPSocket>>
85  UdpConnect(llvm::StringRef host_and_port, bool child_processes_inherit);
86
87  int GetOption(int level, int option_name, int &option_value);
88  int SetOption(int level, int option_name, int option_value);
89
90  NativeSocket GetNativeSocket() const { return m_socket; }
91  SocketProtocol GetSocketProtocol() const { return m_protocol; }
92
93  Status Read(void *buf, size_t &num_bytes) override;
94  Status Write(const void *buf, size_t &num_bytes) override;
95
96  Status Close() override;
97
98  bool IsValid() const override { return m_socket != kInvalidSocketValue; }
99  WaitableHandle GetWaitableHandle() override;
100
101  static llvm::Expected<HostAndPort>
102  DecodeHostAndPort(llvm::StringRef host_and_port);
103
104  // If this Socket is connected then return the URI used to connect.
105  virtual std::string GetRemoteConnectionURI() const { return ""; };
106
107protected:
108  Socket(SocketProtocol protocol, bool should_close,
109         bool m_child_process_inherit);
110
111  virtual size_t Send(const void *buf, const size_t num_bytes);
112
113  static void SetLastError(Status &error);
114  static NativeSocket CreateSocket(const int domain, const int type,
115                                   const int protocol,
116                                   bool child_processes_inherit, Status &error);
117  static NativeSocket AcceptSocket(NativeSocket sockfd, struct sockaddr *addr,
118                                   socklen_t *addrlen,
119                                   bool child_processes_inherit, Status &error);
120
121  SocketProtocol m_protocol;
122  NativeSocket m_socket;
123  bool m_child_processes_inherit;
124  bool m_should_close_fd;
125};
126
127llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
128                              const Socket::HostAndPort &HP);
129
130} // namespace lldb_private
131
132#endif // LLDB_HOST_SOCKET_H
133