Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:33

0001 //===-- llvm/Support/raw_socket_stream.h - Socket streams --*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file contains raw_ostream implementations for streams to communicate
0010 // via UNIX sockets
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_SUPPORT_RAW_SOCKET_STREAM_H
0015 #define LLVM_SUPPORT_RAW_SOCKET_STREAM_H
0016 
0017 #include "llvm/Support/Threading.h"
0018 #include "llvm/Support/raw_ostream.h"
0019 
0020 #include <atomic>
0021 #include <chrono>
0022 
0023 namespace llvm {
0024 
0025 class raw_socket_stream;
0026 
0027 #ifdef _WIN32
0028 /// Ensures proper initialization and cleanup of winsock resources
0029 ///
0030 /// Make sure that calls to WSAStartup and WSACleanup are balanced.
0031 class WSABalancer {
0032 public:
0033   WSABalancer();
0034   ~WSABalancer();
0035 };
0036 #endif // _WIN32
0037 
0038 /// Manages a passive (i.e., listening) UNIX domain socket
0039 ///
0040 /// The ListeningSocket class encapsulates a UNIX domain socket that can listen
0041 /// and accept incoming connections. ListeningSocket is portable and supports
0042 /// Windows builds begining with Insider Build 17063. ListeningSocket is
0043 /// designed for server-side operations, working alongside \p raw_socket_streams
0044 /// that function as client connections.
0045 ///
0046 /// Usage example:
0047 /// \code{.cpp}
0048 /// std::string Path = "/path/to/socket"
0049 /// Expected<ListeningSocket> S = ListeningSocket::createUnix(Path);
0050 ///
0051 /// if (S) {
0052 ///   Expected<std::unique_ptr<raw_socket_stream>> connection = S->accept();
0053 ///   if (connection) {
0054 ///     // Use the accepted raw_socket_stream for communication.
0055 ///   }
0056 /// }
0057 /// \endcode
0058 ///
0059 class ListeningSocket {
0060 
0061   std::atomic<int> FD;
0062   std::string SocketPath; // Not modified after construction
0063 
0064   /// If a separate thread calls ListeningSocket::shutdown, the ListeningSocket
0065   /// file descriptor (FD) could be closed while ::poll is waiting for it to be
0066   /// ready to perform a I/O operations. ::poll will continue to block even
0067   /// after FD is closed so use a self-pipe mechanism to get ::poll to return
0068   int PipeFD[2]; // Not modified after construction other then move constructor
0069 
0070   ListeningSocket(int SocketFD, StringRef SocketPath, int PipeFD[2]);
0071 
0072 #ifdef _WIN32
0073   WSABalancer _;
0074 #endif // _WIN32
0075 
0076 public:
0077   ~ListeningSocket();
0078   ListeningSocket(ListeningSocket &&LS);
0079   ListeningSocket(const ListeningSocket &LS) = delete;
0080   ListeningSocket &operator=(const ListeningSocket &) = delete;
0081 
0082   /// Closes the FD, unlinks the socket file, and writes to PipeFD.
0083   ///
0084   /// After the construction of the ListeningSocket, shutdown is signal safe if
0085   /// it is called during the lifetime of the object. shutdown can be called
0086   /// concurrently with ListeningSocket::accept as writing to PipeFD will cause
0087   /// a blocking call to ::poll to return.
0088   ///
0089   /// Once shutdown is called there is no way to reinitialize ListeningSocket.
0090   void shutdown();
0091 
0092   /// Accepts an incoming connection on the listening socket. This method can
0093   /// optionally either block until a connection is available or timeout after a
0094   /// specified amount of time has passed. By default the method will block
0095   /// until the socket has recieved a connection. If the accept timesout this
0096   /// method will return std::errc:timed_out
0097   ///
0098   /// \param Timeout An optional timeout duration in milliseconds. Setting
0099   /// Timeout to a negative number causes ::accept to block indefinitely
0100   ///
0101   Expected<std::unique_ptr<raw_socket_stream>> accept(
0102       const std::chrono::milliseconds &Timeout = std::chrono::milliseconds(-1));
0103 
0104   /// Creates a listening socket bound to the specified file system path.
0105   /// Handles the socket creation, binding, and immediately starts listening for
0106   /// incoming connections.
0107   ///
0108   /// \param SocketPath The file system path where the socket will be created
0109   /// \param MaxBacklog The max number of connections in a socket's backlog
0110   ///
0111   static Expected<ListeningSocket> createUnix(
0112       StringRef SocketPath,
0113       int MaxBacklog = llvm::hardware_concurrency().compute_thread_count());
0114 };
0115 
0116 //===----------------------------------------------------------------------===//
0117 //  raw_socket_stream
0118 //===----------------------------------------------------------------------===//
0119 
0120 class raw_socket_stream : public raw_fd_stream {
0121   uint64_t current_pos() const override { return 0; }
0122 #ifdef _WIN32
0123   WSABalancer _;
0124 #endif // _WIN32
0125 
0126 public:
0127   raw_socket_stream(int SocketFD);
0128   ~raw_socket_stream();
0129 
0130   /// Create a \p raw_socket_stream connected to the UNIX domain socket at \p
0131   /// SocketPath.
0132   static Expected<std::unique_ptr<raw_socket_stream>>
0133   createConnectedUnix(StringRef SocketPath);
0134 
0135   /// Attempt to read from the raw_socket_stream's file descriptor.
0136   ///
0137   /// This method can optionally either block until data is read or an error has
0138   /// occurred or timeout after a specified amount of time has passed. By
0139   /// default the method will block until the socket has read data or
0140   /// encountered an error. If the read times out this method will return
0141   /// std::errc:timed_out
0142   ///
0143   /// \param Ptr The start of the buffer that will hold any read data
0144   /// \param Size The number of bytes to be read
0145   /// \param Timeout An optional timeout duration in milliseconds
0146   ///
0147   ssize_t read(
0148       char *Ptr, size_t Size,
0149       const std::chrono::milliseconds &Timeout = std::chrono::milliseconds(-1));
0150 };
0151 
0152 } // end namespace llvm
0153 
0154 #endif