Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:03:46

0001 ///////////////////////////////////////////////////////////////////////////////
0002 // Copyright (c) Lewis Baker
0003 // Licenced under MIT license. See LICENSE.txt for details.
0004 ///////////////////////////////////////////////////////////////////////////////
0005 #ifndef CPPCORO_NET_SOCKET_HPP_INCLUDED
0006 #define CPPCORO_NET_SOCKET_HPP_INCLUDED
0007 
0008 #include <cppcoro/config.hpp>
0009 
0010 #include <cppcoro/net/ip_endpoint.hpp>
0011 #include <cppcoro/net/socket_accept_operation.hpp>
0012 #include <cppcoro/net/socket_connect_operation.hpp>
0013 #include <cppcoro/net/socket_disconnect_operation.hpp>
0014 #include <cppcoro/net/socket_recv_operation.hpp>
0015 #include <cppcoro/net/socket_recv_from_operation.hpp>
0016 #include <cppcoro/net/socket_send_operation.hpp>
0017 #include <cppcoro/net/socket_send_to_operation.hpp>
0018 
0019 #include <cppcoro/cancellation_token.hpp>
0020 
0021 #if CPPCORO_OS_WINNT
0022 # include <cppcoro/detail/win32.hpp>
0023 #endif
0024 
0025 namespace cppcoro
0026 {
0027     class io_service;
0028 
0029     namespace net
0030     {
0031         class socket
0032         {
0033         public:
0034 
0035             /// Create a socket that can be used to communicate using TCP/IPv4 protocol.
0036             ///
0037             /// \param ioSvc
0038             /// The I/O service the socket will use for dispatching I/O completion events.
0039             ///
0040             /// \return
0041             /// The newly created socket.
0042             ///
0043             /// \throws std::system_error
0044             /// If the socket could not be created for some reason.
0045             static socket create_tcpv4(io_service& ioSvc);
0046 
0047             /// Create a socket that can be used to communicate using TCP/IPv6 protocol.
0048             ///
0049             /// \param ioSvc
0050             /// The I/O service the socket will use for dispatching I/O completion events.
0051             ///
0052             /// \return
0053             /// The newly created socket.
0054             ///
0055             /// \throws std::system_error
0056             /// If the socket could not be created for some reason.
0057             static socket create_tcpv6(io_service& ioSvc);
0058 
0059             /// Create a socket that can be used to communicate using UDP/IPv4 protocol.
0060             ///
0061             /// \param ioSvc
0062             /// The I/O service the socket will use for dispatching I/O completion events.
0063             ///
0064             /// \return
0065             /// The newly created socket.
0066             ///
0067             /// \throws std::system_error
0068             /// If the socket could not be created for some reason.
0069             static socket create_udpv4(io_service& ioSvc);
0070 
0071             /// Create a socket that can be used to communicate using UDP/IPv6 protocol.
0072             ///
0073             /// \param ioSvc
0074             /// The I/O service the socket will use for dispatching I/O completion events.
0075             ///
0076             /// \return
0077             /// The newly created socket.
0078             ///
0079             /// \throws std::system_error
0080             /// If the socket could not be created for some reason.
0081             static socket create_udpv6(io_service& ioSvc);
0082 
0083             socket(socket&& other) noexcept;
0084 
0085             /// Closes the socket, releasing any associated resources.
0086             ///
0087             /// If the socket still has an open connection then the connection will be
0088             /// reset. The destructor will not block waiting for queueud data to be sent.
0089             /// If you need to ensure that queued data is delivered then you must call
0090             /// disconnect() and wait until the disconnect operation completes.
0091             ~socket();
0092 
0093             socket& operator=(socket&& other) noexcept;
0094 
0095 #if CPPCORO_OS_WINNT
0096             /// Get the Win32 socket handle assocaited with this socket.
0097             cppcoro::detail::win32::socket_t native_handle() noexcept { return m_handle; }
0098 
0099             /// Query whether I/O operations that complete synchronously will skip posting
0100             /// an I/O completion event to the I/O completion port.
0101             ///
0102             /// The operation class implementations can use this to determine whether or not
0103             /// it should immediately resume the coroutine on the current thread upon an
0104             /// operation completing synchronously or whether it should suspend the coroutine
0105             /// and wait until the I/O completion event is dispatched to an I/O thread.
0106             bool skip_completion_on_success() noexcept { return m_skipCompletionOnSuccess; }
0107 #endif
0108 
0109             /// Get the address and port of the local end-point.
0110             ///
0111             /// If the socket is not bound then this will be the unspecified end-point
0112             /// of the socket's associated address-family.
0113             const ip_endpoint& local_endpoint() const noexcept { return m_localEndPoint; }
0114 
0115             /// Get the address and port of the remote end-point.
0116             ///
0117             /// If the socket is not in the connected state then this will be the unspecified
0118             /// end-point of the socket's associated address-family.
0119             const ip_endpoint& remote_endpoint() const noexcept { return m_remoteEndPoint; }
0120 
0121             /// Bind the local end of this socket to the specified local end-point.
0122             ///
0123             /// \param localEndPoint
0124             /// The end-point to bind to.
0125             /// This can be either an unspecified address (in which case it binds to all available
0126             /// interfaces) and/or an unspecified port (in which case a random port is allocated).
0127             ///
0128             /// \throws std::system_error
0129             /// If the socket could not be bound for some reason.
0130             void bind(const ip_endpoint& localEndPoint);
0131 
0132             /// Put the socket into a passive listening state that will start acknowledging
0133             /// and queueing up new connections ready to be accepted by a call to 'accept()'.
0134             ///
0135             /// The backlog of connections ready to be accepted will be set to some default
0136             /// suitable large value, depending on the network provider. If you need more
0137             /// control over the size of the queue then use the overload of listen()
0138             /// that accepts a 'backlog' parameter.
0139             ///
0140             /// \throws std::system_error
0141             /// If the socket could not be placed into a listening mode.
0142             void listen();
0143 
0144             /// Put the socket into a passive listening state that will start acknowledging
0145             /// and queueing up new connections ready to be accepted by a call to 'accept()'.
0146             ///
0147             /// \param backlog
0148             /// The maximum number of pending connections to allow in the queue of ready-to-accept
0149             /// connections.
0150             ///
0151             /// \throws std::system_error
0152             /// If the socket could not be placed into a listening mode.
0153             void listen(std::uint32_t backlog);
0154 
0155             /// Connect the socket to the specified remote end-point.
0156             ///
0157             /// The socket must be in a bound but unconnected state prior to this call.
0158             ///
0159             /// \param remoteEndPoint
0160             /// The IP address and port-number to connect to.
0161             ///
0162             /// \return
0163             /// An awaitable object that must be co_await'ed to perform the async connect
0164             /// operation. The result of the co_await expression is type void.
0165             [[nodiscard]]
0166             socket_connect_operation connect(const ip_endpoint& remoteEndPoint) noexcept;
0167 
0168             /// Connect to the specified remote end-point.
0169             ///
0170             /// \param remoteEndPoint
0171             /// The IP address and port of the remote end-point to connect to.
0172             ///
0173             /// \param ct
0174             /// A cancellation token that can be used to communicate a request to
0175             /// later cancel the operation. If the operation is successfully
0176             /// cancelled then it will complete by throwing a cppcoro::operation_cancelled
0177             /// exception.
0178             ///
0179             /// \return
0180             /// An awaitable object that will start the connect operation when co_await'ed
0181             /// and will suspend the coroutine, resuming it when the operation completes.
0182             /// The result of the co_await expression has type 'void'.
0183             [[nodiscard]]
0184             socket_connect_operation_cancellable connect(
0185                 const ip_endpoint& remoteEndPoint,
0186                 cancellation_token ct) noexcept;
0187 
0188             [[nodiscard]]
0189             socket_accept_operation accept(socket& acceptingSocket) noexcept;
0190             [[nodiscard]]
0191             socket_accept_operation_cancellable accept(
0192                 socket& acceptingSocket,
0193                 cancellation_token ct) noexcept;
0194 
0195             [[nodiscard]]
0196             socket_disconnect_operation disconnect() noexcept;
0197             [[nodiscard]]
0198             socket_disconnect_operation_cancellable disconnect(cancellation_token ct) noexcept;
0199 
0200             [[nodiscard]]
0201             socket_send_operation send(
0202                 const void* buffer,
0203                 std::size_t size) noexcept;
0204             [[nodiscard]]
0205             socket_send_operation_cancellable send(
0206                 const void* buffer,
0207                 std::size_t size,
0208                 cancellation_token ct) noexcept;
0209 
0210             [[nodiscard]]
0211             socket_recv_operation recv(
0212                 void* buffer,
0213                 std::size_t size) noexcept;
0214             [[nodiscard]]
0215             socket_recv_operation_cancellable recv(
0216                 void* buffer,
0217                 std::size_t size,
0218                 cancellation_token ct) noexcept;
0219 
0220             [[nodiscard]]
0221             socket_recv_from_operation recv_from(
0222                 void* buffer,
0223                 std::size_t size) noexcept;
0224             [[nodiscard]]
0225             socket_recv_from_operation_cancellable recv_from(
0226                 void* buffer,
0227                 std::size_t size,
0228                 cancellation_token ct) noexcept;
0229 
0230             [[nodiscard]]
0231             socket_send_to_operation send_to(
0232                 const ip_endpoint& destination,
0233                 const void* buffer,
0234                 std::size_t size) noexcept;
0235             [[nodiscard]]
0236             socket_send_to_operation_cancellable send_to(
0237                 const ip_endpoint& destination,
0238                 const void* buffer,
0239                 std::size_t size,
0240                 cancellation_token ct) noexcept;
0241 
0242             void close_send();
0243             void close_recv();
0244 
0245         private:
0246 
0247             friend class socket_accept_operation_impl;
0248             friend class socket_connect_operation_impl;
0249 
0250 #if CPPCORO_OS_WINNT
0251             explicit socket(
0252                 cppcoro::detail::win32::socket_t handle,
0253                 bool skipCompletionOnSuccess) noexcept;
0254 #endif
0255 
0256 #if CPPCORO_OS_WINNT
0257             cppcoro::detail::win32::socket_t m_handle;
0258             bool m_skipCompletionOnSuccess;
0259 #endif
0260 
0261             ip_endpoint m_localEndPoint;
0262             ip_endpoint m_remoteEndPoint;
0263 
0264         };
0265     }
0266 }
0267 
0268 #endif