|
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645 |
- // <experimental/socket> -*- C++ -*-
-
- // Copyright (C) 2015-2020 Free Software Foundation, Inc.
- //
- // This file is part of the GNU ISO C++ Library. This library is free
- // software; you can redistribute it and/or modify it under the
- // terms of the GNU General Public License as published by the
- // Free Software Foundation; either version 3, or (at your option)
- // any later version.
-
- // This library is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
-
- // Under Section 7 of GPL version 3, you are granted additional
- // permissions described in the GCC Runtime Library Exception, version
- // 3.1, as published by the Free Software Foundation.
-
- // You should have received a copy of the GNU General Public License and
- // a copy of the GCC Runtime Library Exception along with this program;
- // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
- // <http://www.gnu.org/licenses/>.
-
- /** @file experimental/socket
- * This is a TS C++ Library header.
- * @ingroup networking-ts
- */
-
- #ifndef _GLIBCXX_EXPERIMENTAL_SOCKET
- #define _GLIBCXX_EXPERIMENTAL_SOCKET
-
- #pragma GCC system_header
-
- #if __cplusplus >= 201402L
-
- #include <experimental/netfwd>
- #include <experimental/buffer>
- #include <experimental/io_context>
- #include <experimental/bits/net.h>
- #include <streambuf>
- #include <istream>
- #include <bits/unique_ptr.h>
- #if _GLIBCXX_HAVE_UNISTD_H
- # include <unistd.h>
- # ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
- # include <sys/socket.h> // socket etc
- # endif
- # ifdef _GLIBCXX_HAVE_SYS_IOCTL_H
- # include <sys/ioctl.h> // ioctl
- # endif
- # ifdef _GLIBCXX_HAVE_SYS_UIO_H
- # include <sys/uio.h> // iovec
- # endif
- # ifdef _GLIBCXX_HAVE_POLL_H
- # include <poll.h> // poll, pollfd, POLLIN, POLLOUT, POLLERR
- # endif
- # ifdef _GLIBCXX_HAVE_FCNTL_H
- # include <fcntl.h> // fcntl, F_GETFL, F_SETFL
- # endif
- #endif
-
- namespace std _GLIBCXX_VISIBILITY(default)
- {
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
- namespace experimental
- {
- namespace net
- {
- inline namespace v1
- {
-
- /** @addtogroup networking-ts
- * @{
- */
-
- enum class socket_errc { // TODO decide values
- already_open = 3,
- not_found = 4
- };
-
- } // namespace v1
- } // namespace net
- } // namespace experimental
-
- template<>
- struct is_error_code_enum<experimental::net::v1::socket_errc>
- : public true_type {};
-
- namespace experimental
- {
- namespace net
- {
- inline namespace v1
- {
- const error_category& socket_category() noexcept
- {
- struct __cat : error_category
- {
- const char* name() const noexcept { return "socket"; }
-
- std::string message(int __e) const
- {
- if (__e == (int)socket_errc::already_open)
- return "already open";
- else if (__e == (int)socket_errc::not_found)
- return "endpoint not found";
- return "socket error";
- }
-
- virtual void __message(int) { } // TODO dual ABI XXX
- };
- static __cat __c;
- return __c;
- }
-
- inline error_code
- make_error_code(socket_errc __e) noexcept
- { return error_code(static_cast<int>(__e), socket_category()); }
-
- inline error_condition
- make_error_condition(socket_errc __e) noexcept
- { return error_condition(static_cast<int>(__e), socket_category()); }
-
- template<typename _Tp, typename = __void_t<>>
- struct __is_endpoint_impl : false_type
- { };
-
- // Check Endpoint requirements.
- template<typename _Tp>
- auto
- __endpoint_reqs(const _Tp* __a = 0)
- -> enable_if_t<__and_<
- is_default_constructible<_Tp>,
- __is_value_constructible<_Tp>,
- is_same<decltype(__a->__protocol()), typename _Tp::protocol_type>
- >::value,
- __void_t< typename _Tp::protocol_type::endpoint >>;
-
- template<typename _Tp>
- struct __is_endpoint_impl<_Tp, decltype(__endpoint_reqs<_Tp>())>
- : true_type
- { };
-
- template<typename _Tp>
- struct __is_endpoint : __is_endpoint_impl<_Tp>
- { };
-
- // TODO Endpoint reqs for extensible implementations
- // TODO _Protocol reqs
- // TODO AcceptableProtocol reqs
- // TODO GettableSocket reqs
- // TODO SettableSocket reqs
- // TODO BooleanSocketOption reqs
- // TODO IntegerSocketOption reqs
- // TODO IoControlCommand reqs
- // TODO ConnectCondition reqs
-
- /** @brief Sockets
- * @{
- */
-
- class socket_base
- {
- public:
- #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
- struct broadcast : __sockopt_crtp<broadcast, bool>
- {
- using __sockopt_crtp::__sockopt_crtp;
-
- static const int _S_level = SOL_SOCKET;
- static const int _S_name = SO_BROADCAST;
- };
-
- struct debug : __sockopt_crtp<debug, bool>
- {
- using __sockopt_crtp::__sockopt_crtp;
-
- static const int _S_level = SOL_SOCKET;
- static const int _S_name = SO_DEBUG;
- };
-
- struct do_not_route : __sockopt_crtp<do_not_route, bool>
- {
- using __sockopt_crtp::__sockopt_crtp;
-
- static const int _S_level = SOL_SOCKET;
- static const int _S_name = SO_DONTROUTE;
- };
-
- struct keep_alive : __sockopt_crtp<keep_alive, bool>
- {
- using __sockopt_crtp::__sockopt_crtp;
-
- static const int _S_level = SOL_SOCKET;
- static const int _S_name = SO_KEEPALIVE;
- };
-
- struct linger : __sockopt_crtp<linger, ::linger>
- {
- using __sockopt_crtp::__sockopt_crtp;
-
- linger() noexcept = default;
-
- linger(bool __e, chrono::seconds __t) noexcept
- {
- enabled(__e);
- timeout(__t);
- }
-
- bool
- enabled() const noexcept
- { return _M_value.l_onoff != 0; }
-
- void
- enabled(bool __e) noexcept
- { _M_value.l_onoff = int(__e); }
-
- chrono::seconds
- timeout() const noexcept
- { return chrono::seconds(_M_value.l_linger); }
-
- void
- timeout(chrono::seconds __t) noexcept
- { _M_value.l_linger = __t.count(); }
-
- static const int _S_level = SOL_SOCKET;
- static const int _S_name = SO_LINGER;
- };
-
- struct out_of_band_inline : __sockopt_crtp<out_of_band_inline, bool>
- {
- using __sockopt_crtp::__sockopt_crtp;
-
- static const int _S_level = SOL_SOCKET;
- static const int _S_name = SO_OOBINLINE;
- };
-
- struct receive_buffer_size : __sockopt_crtp<receive_buffer_size>
- {
- using __sockopt_crtp::__sockopt_crtp;
-
- static const int _S_level = SOL_SOCKET;
- static const int _S_name = SO_RCVBUF;
- };
-
- struct receive_low_watermark : __sockopt_crtp<receive_low_watermark>
- {
- using __sockopt_crtp::__sockopt_crtp;
-
- static const int _S_level = SOL_SOCKET;
- static const int _S_name = SO_RCVLOWAT;
- };
-
- struct reuse_address : __sockopt_crtp<reuse_address, bool>
- {
- using __sockopt_crtp::__sockopt_crtp;
-
- static const int _S_level = SOL_SOCKET;
- static const int _S_name = SO_REUSEADDR;
- };
-
- struct send_buffer_size : __sockopt_crtp<send_buffer_size>
- {
- using __sockopt_crtp::__sockopt_crtp;
-
- static const int _S_level = SOL_SOCKET;
- static const int _S_name = SO_SNDBUF;
- };
-
- struct send_low_watermark : __sockopt_crtp<send_low_watermark>
- {
- using __sockopt_crtp::__sockopt_crtp;
-
- static const int _S_level = SOL_SOCKET;
- static const int _S_name = SO_SNDLOWAT;
- };
-
- enum shutdown_type : int
- {
- __shutdown_receive = SHUT_RD,
- __shutdown_send = SHUT_WR,
- __shutdown_both = SHUT_RDWR
- };
- static constexpr shutdown_type shutdown_receive = __shutdown_receive;
- static constexpr shutdown_type shutdown_send = __shutdown_send;
- static constexpr shutdown_type shutdown_both = __shutdown_both;
-
- #ifdef _GLIBCXX_HAVE_POLL_H
- enum wait_type : int
- {
- __wait_read = POLLIN,
- __wait_write = POLLOUT,
- __wait_error = POLLERR
- };
- static constexpr wait_type wait_read = __wait_read;
- static constexpr wait_type wait_write = __wait_write;
- static constexpr wait_type wait_error = __wait_error;
- #endif
-
- enum message_flags : int
- {
- __message_peek = MSG_PEEK,
- __message_oob = MSG_OOB,
- __message_dontroute = MSG_DONTROUTE
- };
- static constexpr message_flags message_peek = __message_peek;
- static constexpr message_flags message_out_of_band = __message_oob;
- static constexpr message_flags message_do_not_route = __message_dontroute;
-
- static const int max_listen_connections = SOMAXCONN;
- #endif
-
- protected:
- socket_base() = default;
- ~socket_base() = default;
-
- #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
- struct __msg_hdr : ::msghdr
- {
- #ifdef IOV_MAX
- using __iovec_array = array<::iovec, IOV_MAX>;
- #elif _GLIBCXX_HAVE_UNISTD_H
- struct __iovec_array
- {
- __iovec_array() : _M_ptr(new ::iovec[size()]) { }
-
- ::iovec& operator[](size_t __n) noexcept { return _M_ptr[__n]; }
-
- ::iovec* data() noexcept { return _M_ptr.get(); }
-
- static size_t size()
- {
- static const size_t __iov_max = ::sysconf(_SC_IOV_MAX);
- return __iov_max;
- }
-
- private:
- unique_ptr<::iovec[]> _M_ptr;
- };
- #else
- using __iovec_array = array<::iovec, 16>;
- #endif
-
- __iovec_array _M_iov;
-
- template<typename _BufferSequence>
- explicit
- __msg_hdr(const _BufferSequence& __buffers)
- : msghdr()
- {
- auto __buf = net::buffer_sequence_begin(__buffers);
- const auto __bufend = net::buffer_sequence_end(__buffers);
- size_t __len = 0;
- while (__buf != __bufend && __len != _M_iov.size())
- {
- _M_iov[__len].iov_base = (void*)__buf->data();
- _M_iov[__len].iov_len = __buf->size();
- ++__buf;
- ++__len;
- }
- this->msg_iovlen = __len;
- this->msg_iov = _M_iov.data();
- }
-
- template<typename _BufferSequence, typename _Endpoint>
- __msg_hdr(const _BufferSequence& __buffers, const _Endpoint& __ep)
- : __msg_hdr(__buffers)
- {
- this->msg_name = __ep.data();
- this->msg_namelen = __ep.size();
- }
- };
- #endif
- };
-
- constexpr socket_base::message_flags
- operator&(socket_base::message_flags __f1, socket_base::message_flags __f2)
- { return socket_base::message_flags( int(__f1) & int(__f2) ); }
-
- constexpr socket_base::message_flags
- operator|(socket_base::message_flags __f1, socket_base::message_flags __f2)
- { return socket_base::message_flags( int(__f1) | int(__f2) ); }
-
- constexpr socket_base::message_flags
- operator^(socket_base::message_flags __f1, socket_base::message_flags __f2)
- { return socket_base::message_flags( int(__f1) ^ int(__f2) ); }
-
- constexpr socket_base::message_flags
- operator~(socket_base::message_flags __f)
- { return socket_base::message_flags( ~int(__f) ); }
-
- inline socket_base::message_flags&
- operator&=(socket_base::message_flags& __f1, socket_base::message_flags __f2)
- { return __f1 = (__f1 & __f2); }
-
- inline socket_base::message_flags&
- operator|=(socket_base::message_flags& __f1, socket_base::message_flags __f2)
- { return __f1 = (__f1 | __f2); }
-
- inline socket_base::message_flags&
- operator^=(socket_base::message_flags& __f1, socket_base::message_flags __f2)
- { return __f1 = (__f1 ^ __f2); }
-
- #if _GLIBCXX_HAVE_UNISTD_H
-
- class __socket_impl
- {
- protected:
-
- using executor_type = io_context::executor_type;
- using native_handle_type = int;
-
- explicit
- __socket_impl(io_context& __ctx) : _M_ctx(std::addressof(__ctx)) { }
-
- __socket_impl(__socket_impl&& __rhs)
- : _M_ctx(__rhs._M_ctx),
- _M_sockfd(std::exchange(__rhs._M_sockfd, -1)),
- _M_bits(std::exchange(__rhs._M_bits, {}))
- { }
-
- __socket_impl&
- operator=(__socket_impl&& __rhs)
- {
- _M_ctx = __rhs._M_ctx;
- _M_sockfd = std::exchange(__rhs._M_sockfd, -1);
- _M_bits = std::exchange(__rhs._M_bits, {});
- return *this;
- }
-
- ~__socket_impl() = default;
-
- __socket_impl(const __socket_impl&) = delete;
- __socket_impl& operator=(const __socket_impl&) = delete;
-
- executor_type get_executor() noexcept { return _M_ctx->get_executor(); }
-
- native_handle_type native_handle() noexcept { return _M_sockfd; }
-
- bool is_open() const noexcept { return _M_sockfd != -1; }
-
- void
- close(error_code& __ec)
- {
- if (is_open())
- {
- cancel(__ec);
- if (!__ec)
- {
- if (::close(_M_sockfd) == -1)
- __ec.assign(errno, generic_category());
- else
- {
- get_executor().context()._M_remove_fd(_M_sockfd);
- _M_sockfd = -1;
- }
- }
- }
- }
-
- void cancel(error_code& __ec) { _M_ctx->cancel(_M_sockfd, __ec); }
-
- void
- non_blocking(bool __mode, error_code&)
- { _M_bits.non_blocking = __mode; }
-
- bool non_blocking() const { return _M_bits.non_blocking; }
-
- void
- native_non_blocking(bool __mode, error_code& __ec)
- {
- #ifdef _GLIBCXX_HAVE_FCNTL_H
- int __flags = ::fcntl(_M_sockfd, F_GETFL, 0);
- if (__flags >= 0)
- {
- if (__mode)
- __flags |= O_NONBLOCK;
- else
- __flags &= ~O_NONBLOCK;
- __flags = ::fcntl(_M_sockfd, F_SETFL, __flags);
- }
- if (__flags == -1)
- __ec.assign(errno, generic_category());
- else
- {
- __ec.clear();
- _M_bits.native_non_blocking = __mode;
- }
- #else
- __ec = std::make_error_code(std::errc::not_supported);
- #endif
- }
-
- bool
- native_non_blocking() const
- {
- #ifdef _GLIBCXX_HAVE_FCNTL_H
- if (_M_bits.native_non_blocking == -1)
- {
- const int __flags = ::fcntl(_M_sockfd, F_GETFL, 0);
- if (__flags == -1)
- return 0;
- _M_bits.native_non_blocking = __flags & O_NONBLOCK;
- }
- return _M_bits.native_non_blocking;
- #else
- return false;
- #endif
- }
-
- io_context* _M_ctx;
- int _M_sockfd{-1};
- struct {
- unsigned non_blocking : 1;
- mutable signed native_non_blocking : 2;
- unsigned enable_connection_aborted : 1;
- } _M_bits{};
- };
-
- template<typename _Protocol>
- class __basic_socket_impl : public __socket_impl
- {
- using __base = __socket_impl;
-
- protected:
- using protocol_type = _Protocol;
- using endpoint_type = typename protocol_type::endpoint;
-
- explicit
- __basic_socket_impl(io_context& __ctx) : __base(__ctx) { }
-
- __basic_socket_impl(__basic_socket_impl&&) = default;
-
- template<typename _OtherProtocol>
- __basic_socket_impl(__basic_socket_impl<_OtherProtocol>&& __rhs)
- : __base(std::move(__rhs)), _M_protocol(std::move(__rhs._M_protocol))
- { }
-
- __basic_socket_impl&
- operator=(__basic_socket_impl&& __rhs)
- {
- if (this == std::addressof(__rhs))
- return *this;
- _M_close();
- __base::operator=(std::move(__rhs));
- return *this;
- }
-
- ~__basic_socket_impl() { _M_close(); }
-
- __basic_socket_impl(const __basic_socket_impl&) = delete;
- __basic_socket_impl& operator=(const __basic_socket_impl&) = delete;
-
- void
- open(const protocol_type& __protocol, error_code& __ec)
- {
- #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
- if (is_open())
- __ec = socket_errc::already_open;
- else
- {
- _M_protocol = __protocol;
- _M_sockfd = ::socket(__protocol.family(), __protocol.type(),
- __protocol.protocol());
- if (is_open())
- {
- get_executor().context()._M_add_fd(_M_sockfd);
- __ec.clear();
- }
- else
- __ec.assign(errno, std::generic_category());
- }
- #else
- __ec = std::make_error_code(errc::operation_not_supported);
- #endif
- }
-
- void
- assign(const protocol_type& __protocol,
- const native_handle_type& __native_socket,
- error_code& __ec)
- {
- if (is_open())
- __ec = socket_errc::already_open;
- else
- {
- _M_protocol = __protocol;
- _M_bits.native_non_blocking = -1;
- _M_sockfd = __native_socket;
- if (is_open())
- {
- get_executor().context()._M_add_fd(_M_sockfd);
- __ec.clear();
- }
- else
- __ec.assign(errno, std::generic_category());
- }
- }
-
- native_handle_type release(error_code& __ec)
- {
- __glibcxx_assert(is_open());
- cancel(__ec);
- return std::exchange(_M_sockfd, -1);
- }
-
- template<typename _SettableSocketOption>
- void
- set_option(const _SettableSocketOption& __option, error_code& __ec)
- {
- int __result = ::setsockopt(_M_sockfd, __option.level(_M_protocol),
- __option.name(_M_protocol),
- __option.data(_M_protocol),
- __option.size(_M_protocol));
- if (__result == -1)
- __ec.assign(errno, generic_category());
- else
- __ec.clear();
- }
-
- template<typename _GettableSocketOption>
- void
- get_option(_GettableSocketOption& __option, error_code& __ec) const
- {
- int __result = ::getsockopt(_M_sockfd, __option.level(_M_protocol),
- __option.name(_M_protocol),
- __option.data(_M_protocol),
- __option.size(_M_protocol));
- if (__result == -1)
- __ec.assign(errno, generic_category());
- else
- __ec.clear();
- }
-
- template<typename _IoControlCommand>
- void
- io_control(_IoControlCommand& __command, error_code& __ec)
- {
- #ifdef _GLIBCXX_HAVE_SYS_IOCTL_H
- int __result = ::ioctl(_M_sockfd, __command.name(),
- __command.data());
- if (__result == -1)
- __ec.assign(errno, generic_category());
- else
- __ec.clear();
- #else
- __ec = std::make_error_code(std::errc::not_supported);
- #endif
- }
-
- endpoint_type
- local_endpoint(error_code& __ec) const
- {
- endpoint_type __endpoint;
- #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
- socklen_t __endpoint_len = __endpoint.capacity();
- if (::getsockname(_M_sockfd, (sockaddr*)__endpoint.data(),
- &__endpoint_len) == -1)
- {
- __ec.assign(errno, generic_category());
- return endpoint_type{};
- }
- __ec.clear();
- __endpoint.resize(__endpoint_len);
- #else
- __ec = std::make_error_code(errc::operation_not_supported);
- #endif
- return __endpoint;
- }
-
- void
- bind(const endpoint_type& __endpoint, error_code& __ec)
- {
- #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
- if (::bind(_M_sockfd, (sockaddr*)__endpoint.data(), __endpoint.size())
- == -1)
- __ec.assign(errno, generic_category());
- else
- __ec.clear();
- #else
- __ec = std::make_error_code(errc::operation_not_supported);
- #endif
- }
-
- _Protocol _M_protocol{ endpoint_type{}.protocol() };
-
- private:
- void
- _M_close()
- {
- if (is_open())
- {
- error_code __ec;
- cancel(__ec);
- set_option(socket_base::linger{false, chrono::seconds{}}, __ec);
- ::close(_M_sockfd);
- }
- }
- };
-
- template<typename _Protocol>
- class basic_socket
- : public socket_base, private __basic_socket_impl<_Protocol>
- {
- using __base = __basic_socket_impl<_Protocol>;
-
- public:
- // types:
-
- typedef io_context::executor_type executor_type;
- typedef int native_handle_type;
- typedef _Protocol protocol_type;
- typedef typename protocol_type::endpoint endpoint_type;
-
- // basic_socket operations:
-
- executor_type get_executor() noexcept { return __base::get_executor(); }
-
- native_handle_type
- native_handle() noexcept { return __base::native_handle(); }
-
- void
- open(const protocol_type& __protocol = protocol_type())
- { open(__protocol, __throw_on_error{"basic_socket::open"}); }
-
- void
- open(const protocol_type& __protocol, error_code& __ec)
- { __base::open(__protocol, __ec); }
-
- void
- assign(const protocol_type& __protocol,
- const native_handle_type& __native_socket)
- {
- assign(__protocol, __native_socket,
- __throw_on_error{"basic_socket::assign"});
- }
-
- void
- assign(const protocol_type& __protocol,
- const native_handle_type& __native_socket,
- error_code& __ec)
- { __base::assign(__protocol, __native_socket, __ec); }
-
- native_handle_type release()
- { return release(__throw_on_error{"basic_socket::release"}); }
-
- native_handle_type release(error_code& __ec)
- { return __base::release(__ec); }
-
- _GLIBCXX_NODISCARD bool
- is_open() const noexcept { return __base::is_open(); }
-
- void close() { close(__throw_on_error{"basic_socket::close"}); }
-
- void close(error_code& __ec) { __base::close(__ec); }
-
- void cancel() { cancel(__throw_on_error{"basic_socket::cancel"}); }
-
- void cancel(error_code& __ec) { __base::cancel(__ec); }
-
- template<typename _SettableSocketOption>
- void
- set_option(const _SettableSocketOption& __option)
- { set_option(__option, __throw_on_error{"basic_socket::set_option"}); }
-
- template<typename _SettableSocketOption>
- void
- set_option(const _SettableSocketOption& __option, error_code& __ec)
- { __base::set_option(__option, __ec); }
-
- template<typename _GettableSocketOption>
- void
- get_option(_GettableSocketOption& __option) const
- { get_option(__option, __throw_on_error{"basic_socket::get_option"}); }
-
- template<typename _GettableSocketOption>
- void
- get_option(_GettableSocketOption& __option, error_code& __ec) const
- { __base::get_option(__option, __ec); }
-
- template<typename _IoControlCommand>
- void
- io_control(_IoControlCommand& __command)
- {
- io_control(__command, __throw_on_error{"basic_socket::io_control"});
- }
-
- template<typename _IoControlCommand>
- void
- io_control(_IoControlCommand& __command, error_code& __ec)
- { __base::io_control(__command, __ec); }
-
- void
- non_blocking(bool __mode)
- { non_blocking(__mode, __throw_on_error{"basic_socket::non_blocking"}); }
-
- void
- non_blocking(bool __mode, error_code& __ec)
- { __base::non_blocking(__mode, __ec); }
-
- bool non_blocking() const { return __base::non_blocking(); }
-
- void
- native_non_blocking(bool __mode)
- {
- native_non_blocking(__mode, __throw_on_error{
- "basic_socket::native_non_blocking"});
- }
-
- void
- native_non_blocking(bool __mode, error_code& __ec)
- { __base::native_non_blocking(__mode, __ec); }
-
- bool
- native_non_blocking() const
- { return __base::native_non_blocking(); }
-
- bool at_mark() const
- { return at_mark(__throw_on_error{"basic_socket::at_mark"}); }
-
- bool
- at_mark(error_code& __ec) const
- {
- #ifdef _GLIBCXX_HAVE_SOCKATMARK
- const int __result = ::sockatmark(native_handle());
- if (__result == -1)
- {
- __ec.assign(errno, generic_category());
- return false;
- }
- __ec.clear();
- return (bool)__result;
- #else
- __ec = std::make_error_code(errc::operation_not_supported);
- return false;
- #endif
- }
-
- size_t
- available() const
- { return available(__throw_on_error{"basic_socket::available"}); }
-
- size_t
- available(error_code& __ec) const
- {
- if (!is_open())
- {
- __ec = std::make_error_code(errc::bad_file_descriptor);
- return 0;
- }
- #if defined _GLIBCXX_HAVE_SYS_IOCTL_H && defined FIONREAD
- int __avail = 0;
- if (::ioctl(this->_M_sockfd, FIONREAD, &__avail) == -1)
- {
- __ec.assign(errno, generic_category());
- return 0;
- }
- __ec.clear();
- return __avail;
- #else
- return 0;
- #endif
- }
-
- void
- bind(const endpoint_type& __endpoint)
- { return bind(__endpoint, __throw_on_error{"basic_socket::bind"}); }
-
- void
- bind(const endpoint_type& __endpoint, error_code& __ec)
- { __base::bind(__endpoint, __ec); }
-
- void shutdown(shutdown_type __what)
- { return shutdown(__what, __throw_on_error{"basic_socket::shutdown"}); }
-
- void
- shutdown(shutdown_type __what, error_code& __ec)
- {
- #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
- if (::shutdown(native_handle(), static_cast<int>(__what)) == -1)
- __ec.assign(errno, generic_category());
- else
- __ec.clear();
- #else
- __ec = std::make_error_code(errc::operation_not_supported);
- #endif
- }
-
- endpoint_type
- local_endpoint() const
- {
- return local_endpoint(
- __throw_on_error{"basic_socket::local_endpoint"});
- }
-
- endpoint_type
- local_endpoint(error_code& __ec) const
- { return __base::local_endpoint(__ec); }
-
- endpoint_type
- remote_endpoint() const
- {
- return remote_endpoint(
- __throw_on_error{"basic_socket::remote_endpoint"});
- }
-
- endpoint_type
- remote_endpoint(error_code& __ec) const
- {
- endpoint_type __endpoint;
- #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
- socklen_t __endpoint_len = __endpoint.capacity();
- if (::getpeername(this->_M_sockfd, (sockaddr*)__endpoint.data(),
- &__endpoint_len)
- == -1)
- {
- __ec.assign(errno, generic_category());
- return endpoint_type{};
- }
- __ec.clear();
- __endpoint.resize(__endpoint_len);
- #else
- __ec = std::make_error_code(errc::operation_not_supported);
- #endif
- return __endpoint;
- }
-
- void
- connect(const endpoint_type& __endpoint)
- {
- return connect(__endpoint, __throw_on_error{"basic_socket::connect"});
- }
-
- void
- connect(const endpoint_type& __endpoint, error_code& __ec)
- {
- #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
- if (!is_open())
- {
- open(__endpoint.protocol(), __ec);
- if (__ec)
- return;
- }
- if (::connect(native_handle(), (const sockaddr*)__endpoint.data(),
- __endpoint.size()) == -1)
- __ec.assign(errno, generic_category());
- else
- __ec.clear();
- #else
- __ec = std::make_error_code(errc::operation_not_supported);
- #endif
- }
-
- template<typename _CompletionToken>
- __deduced_t<_CompletionToken, void(error_code)>
- async_connect(const endpoint_type& __endpoint,
- _CompletionToken&& __token)
- {
- async_completion<_CompletionToken, void(error_code)> __init{__token};
-
- if (!is_open())
- {
- error_code __ec;
- open(__endpoint.protocol(), __ec);
- if (__ec)
- {
- auto __ex = net::get_associated_executor(
- __init.completion_handler, get_executor());
- auto __a = get_associated_allocator(
- __init.completion_handler, std::allocator<void>());
- __ex.post(
- [__h = std::move(__init.completion_handler), __ec]
- () mutable
- { __h(__ec); }, __a);
- return __init.result.get();
- }
- }
-
- get_executor().context().async_wait( native_handle(),
- socket_base::wait_read,
- [__h = std::move(__init.completion_handler),
- __ep = std::move(__endpoint),
- __fd = native_handle()]
- (error_code __ec) mutable {
- #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
- if (!__ec && ::connect(__fd, (const sockaddr*)__ep.data(),
- __ep.size()) == -1)
- __ec.assign(errno, generic_category());
- #else
- __ec = std::make_error_code(errc::operation_not_supported);
- #endif
- __h(__ec);
- });
- return __init.result.get();
- }
-
- void
- wait(wait_type __w)
- { return wait(__w, __throw_on_error{"basic_socket::wait"}); }
-
- void
- wait(wait_type __w, error_code& __ec)
- {
- #ifdef _GLIBCXX_HAVE_POLL_H
- ::pollfd __fd;
- __fd.fd = native_handle();
- __fd.events = static_cast<int>(__w);
- int __res = ::poll(&__fd, 1, -1);
- if (__res == -1)
- __ec.assign(errno, generic_category());
- else
- __ec.clear();
- #else
- __ec = std::make_error_code(errc::operation_not_supported);
- #endif
- }
-
- template<typename _CompletionToken>
- __deduced_t<_CompletionToken, void(error_code)>
- async_wait(wait_type __w, _CompletionToken&& __token)
- {
- async_completion<_CompletionToken, void(error_code)> __init{__token};
- get_executor().context().async_wait( native_handle(),
- static_cast<int>(__w),
- [__h = std::move(__init.completion_handler)]
- (error_code __ec) mutable {
- __h(__ec);
- });
- return __init.result.get();
- }
-
- protected:
- // construct / copy / destroy:
-
- using __base::__base;
-
- explicit
- basic_socket(io_context& __ctx) : __base(__ctx) { }
-
- basic_socket(io_context& __ctx, const protocol_type& __protocol)
- : __base(__ctx)
- { open(__protocol); }
-
- basic_socket(io_context& __ctx, const endpoint_type& __endpoint)
- : basic_socket(__ctx, __endpoint.protocol())
- { bind(__endpoint); }
-
- basic_socket(io_context& __ctx, const protocol_type& __protocol,
- const native_handle_type& __native_socket)
- : __base(__ctx)
- { assign(__protocol, __native_socket); }
-
- basic_socket(const basic_socket&) = delete;
-
- basic_socket(basic_socket&& __rhs) = default;
-
- template<typename _OtherProtocol, typename _Requires
- = _Require<is_convertible<_OtherProtocol, _Protocol>>>
- basic_socket(basic_socket<_OtherProtocol>&& __rhs)
- : __base(std::move(__rhs)) { }
-
- ~basic_socket() = default;
-
- basic_socket& operator=(const basic_socket&) = delete;
-
- basic_socket& operator=(basic_socket&& __rhs) = default;
-
- template<typename _OtherProtocol>
- enable_if_t<is_convertible<_OtherProtocol, _Protocol>::value,
- basic_socket&>
- operator=(basic_socket<_OtherProtocol>&& __rhs)
- { return *this = basic_socket{std::move(__rhs)}; }
- };
-
- template<typename _Protocol>
- class basic_datagram_socket : public basic_socket<_Protocol>
- {
- using __base = basic_socket<_Protocol>;
-
- public:
- // types:
-
- typedef int native_handle_type;
- typedef _Protocol protocol_type;
- typedef typename protocol_type::endpoint endpoint_type;
-
- // construct / copy / destroy:
-
- explicit
- basic_datagram_socket(io_context& __ctx) : __base(__ctx) { }
-
- basic_datagram_socket(io_context& __ctx, const protocol_type& __protocol)
- : __base(__ctx, __protocol) { }
-
- basic_datagram_socket(io_context& __ctx, const endpoint_type& __endpoint)
- : __base(__ctx, __endpoint) { }
-
- basic_datagram_socket(io_context& __ctx, const protocol_type& __protocol,
- const native_handle_type& __native_socket)
- : __base(__ctx, __protocol, __native_socket) { }
-
- basic_datagram_socket(const basic_datagram_socket&) = delete;
-
- basic_datagram_socket(basic_datagram_socket&& __rhs) = default;
-
- template<typename _OtherProtocol, typename _Requires
- = _Require<is_convertible<_OtherProtocol, _Protocol>>>
- basic_datagram_socket(basic_datagram_socket<_OtherProtocol>&& __rhs)
- : __base(std::move(__rhs)) { }
-
- ~basic_datagram_socket() = default;
-
- basic_datagram_socket& operator=(const basic_datagram_socket&) = delete;
-
- basic_datagram_socket& operator=(basic_datagram_socket&& __rhs) = default;
-
- template<typename _OtherProtocol>
- enable_if_t<is_convertible<_OtherProtocol, _Protocol>::value,
- basic_datagram_socket&>
- operator=(basic_datagram_socket<_OtherProtocol>&& __rhs)
- {
- __base::operator=(std::move(__rhs));
- return *this;
- }
-
- // basic_datagram_socket operations:
-
- template<typename _MutableBufferSequence>
- size_t
- receive(const _MutableBufferSequence& __buffers)
- {
- return receive(__buffers, socket_base::message_flags(),
- __throw_on_error{"basic_datagram_socket::receive"});
- }
-
- template<typename _MutableBufferSequence>
- size_t
- receive(const _MutableBufferSequence& __buffers, error_code& __ec)
- { return receive(__buffers, socket_base::message_flags(), __ec); }
-
- template<typename _MutableBufferSequence>
- size_t
- receive(const _MutableBufferSequence& __buffers,
- socket_base::message_flags __flags)
- {
- return receive(__buffers, __flags,
- __throw_on_error{"basic_datagram_socket::receive"});
- }
-
- template<typename _MutableBufferSequence>
- size_t
- receive(const _MutableBufferSequence& __buffers,
- socket_base::message_flags __flags, error_code& __ec)
- {
- #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
- socket_base::__msg_hdr __msg(__buffers);
- ssize_t __result = ::recvmsg(this->native_handle(), &__msg,
- static_cast<int>(__flags));
- if (__result == -1)
- {
- __ec.assign(errno, generic_category());
- return 0;
- }
- __ec.clear();
- return __result;
- #else
- __ec = std::make_error_code(errc::operation_not_supported);
- return 0;
- #endif
- }
-
- template<typename _MutableBufferSequence, typename _CompletionToken>
- __deduced_t<_CompletionToken, void(error_code, size_t)>
- async_receive(const _MutableBufferSequence& __buffers,
- _CompletionToken&& __token)
- {
- return async_receive(__buffers, socket_base::message_flags(),
- std::forward<_CompletionToken>(__token));
- }
-
- template<typename _MutableBufferSequence, typename _CompletionToken>
- __deduced_t<_CompletionToken, void(error_code, size_t)>
- async_receive(const _MutableBufferSequence& __buffers,
- socket_base::message_flags __flags,
- _CompletionToken&& __token)
- {
- async_completion<_CompletionToken, void(error_code, size_t)>
- __init{__token};
-
- this->get_executor().context().async_wait(this->native_handle(),
- socket_base::wait_read,
- [__h = std::move(__init.completion_handler),
- &__buffers, __flags = static_cast<int>(__flags),
- __fd = this->native_handle()]
- (error_code __ec) mutable {
- if (__ec)
- {
- __h(__ec);
- return;
- }
- #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
- socket_base::__msg_hdr __msg(__buffers);
- ssize_t __result = ::recvmsg(__fd, &__msg, __flags);
- if (__result == -1)
- {
- __ec.assign(errno, generic_category());
- __result = 0;
- }
- else
- __ec.clear();
- __h(__ec, __result);
- #else
- __h(std::make_error_code(errc::operation_not_supported), 0);
- #endif
- });
- return __init.result.get();
- }
-
- template<typename _MutableBufferSequence>
- size_t
- receive_from(const _MutableBufferSequence& __buffers,
- endpoint_type& __sender)
- {
- return receive_from(__buffers, __sender,
- socket_base::message_flags(),
- __throw_on_error{
- "basic_datagram_socket::receive_from"});
- }
-
- template<typename _MutableBufferSequence>
- size_t
- receive_from(const _MutableBufferSequence& __buffers,
- endpoint_type& __sender, error_code& __ec)
- {
- return receive_from(__buffers, __sender,
- socket_base::message_flags(), __ec);
- }
-
- template<typename _MutableBufferSequence>
- size_t
- receive_from(const _MutableBufferSequence& __buffers,
- endpoint_type& __sender,
- socket_base::message_flags __flags)
- {
- return receive_from(__buffers, __sender, __flags,
- __throw_on_error{
- "basic_datagram_socket::receive_from"});
- }
-
- template<typename _MutableBufferSequence>
- size_t
- receive_from(const _MutableBufferSequence& __buffers,
- endpoint_type& __sender,
- socket_base::message_flags __flags,
- error_code& __ec)
- {
- #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
- socket_base::__msg_hdr __msg(__buffers, __sender);
- ssize_t __result = ::recvmsg(this->native_handle(), &__msg,
- static_cast<int>(__flags));
- if (__result == -1)
- {
- __ec.assign(errno, generic_category());
- return 0;
- }
- __ec.clear();
- __sender.resize(__msg.msg_namelen);
- return __result;
- #else
- __ec = std::make_error_code(errc::operation_not_supported);
- return 0;
- #endif
- }
-
- template<typename _MutableBufferSequence, typename _CompletionToken>
- __deduced_t<_CompletionToken, void(error_code, size_t)>
- async_receive_from(const _MutableBufferSequence& __buffers,
- endpoint_type& __sender,
- _CompletionToken&& __token)
- {
- return async_receive_from(__buffers, __sender,
- socket_base::message_flags(),
- std::forward<_CompletionToken>(__token));
- }
-
- template<typename _MutableBufferSequence, typename _CompletionToken>
- __deduced_t<_CompletionToken, void(error_code, size_t)>
- async_receive_from(const _MutableBufferSequence& __buffers,
- endpoint_type& __sender,
- socket_base::message_flags __flags,
- _CompletionToken&& __token)
- {
- async_completion<_CompletionToken, void(error_code, size_t)>
- __init{__token};
-
- this->get_executor().context().async_wait( this->native_handle(),
- socket_base::wait_read,
- [__h = std::move(__init.completion_handler),
- &__buffers, __flags = static_cast<int>(__flags),
- __sender = std::move(__sender),
- __fd = this->native_handle()]
- (error_code __ec) mutable {
- if (__ec)
- {
- __h(__ec);
- return;
- }
- #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
- socket_base::__msg_hdr __msg(__buffers, __sender);
- ssize_t __result = ::recvmsg(__fd, &__msg, __flags);
- if (__result == -1)
- {
- __ec.assign(errno, generic_category());
- __result = 0;
- }
- else
- {
- __ec.clear();
- __sender.resize(__msg.msg_namelen);
- }
- __h(__ec, __result);
- #else
- __h(std::make_error_code(errc::operation_not_supported), 0);
- #endif
- });
- return __init.result.get();
- }
-
- template<typename _ConstBufferSequence>
- size_t
- send(const _ConstBufferSequence& __buffers)
- {
- return send(__buffers, socket_base::message_flags(),
- __throw_on_error{"basic_datagram_socket::send"});
- }
-
- template<typename _ConstBufferSequence>
- size_t
- send(const _ConstBufferSequence& __buffers, error_code& __ec)
- { return send(__buffers, socket_base::message_flags(), __ec); }
-
- template<typename _ConstBufferSequence>
- size_t
- send(const _ConstBufferSequence& __buffers,
- socket_base::message_flags __flags)
- {
- return send(__buffers, __flags,
- __throw_on_error{"basic_datagram_socket::send"});
- }
-
- template<typename _ConstBufferSequence>
- size_t
- send(const _ConstBufferSequence& __buffers,
- socket_base::message_flags __flags, error_code& __ec)
- {
- #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
- socket_base::__msg_hdr __msg(__buffers);
- ssize_t __result = ::sendmsg(this->native_handle(), &__msg,
- static_cast<int>(__flags));
- if (__result == -1)
- {
- __ec.assign(errno, generic_category());
- return 0;
- }
- __ec.clear();
- return __result;
- #else
- __ec = std::make_error_code(errc::operation_not_supported);
- return 0;
- #endif
- }
-
- template<typename _ConstBufferSequence, typename _CompletionToken>
- __deduced_t<_CompletionToken, void(error_code, size_t)>
- async_send(const _ConstBufferSequence& __buffers,
- _CompletionToken&& __token)
- {
- return async_send(__buffers, socket_base::message_flags(),
- std::forward<_CompletionToken>(__token));
- }
-
- template<typename _ConstBufferSequence, typename _CompletionToken>
- __deduced_t<_CompletionToken, void(error_code, size_t)>
- async_send(const _ConstBufferSequence& __buffers,
- socket_base::message_flags __flags,
- _CompletionToken&& __token)
- {
- async_completion<_CompletionToken, void(error_code, size_t)>
- __init{__token};
-
- this->get_executor().context().async_wait( this->native_handle(),
- socket_base::wait_write,
- [__h = std::move(__init.completion_handler),
- &__buffers, __flags = static_cast<int>(__flags),
- __fd = this->native_handle()]
- (error_code __ec) mutable {
- if (__ec)
- {
- __h(__ec);
- return;
- }
- #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
- socket_base::__msg_hdr __msg(__buffers);
- ssize_t __result = ::sendmsg(__fd, &__msg, __flags);
- if (__result == -1)
- {
- __ec.assign(errno, generic_category());
- __result = 0;
- }
- else
- __ec.clear();
- __h(__ec, __result);
- #else
- __h(std::make_error_code(errc::operation_not_supported), 0);
- #endif
- });
- return __init.result.get();
- }
-
- template<typename _ConstBufferSequence>
- size_t
- send_to(const _ConstBufferSequence& __buffers,
- const endpoint_type& __recipient)
- {
- return send_to(__buffers, __recipient,
- socket_base::message_flags(),
- __throw_on_error{"basic_datagram_socket::send_to"});
- }
-
- template<typename _ConstBufferSequence>
- size_t
- send_to(const _ConstBufferSequence& __buffers,
- const endpoint_type& __recipient, error_code& __ec)
- {
- return send_to(__buffers, __recipient,
- socket_base::message_flags(), __ec);
- }
-
- template<typename _ConstBufferSequence>
- size_t
- send_to(const _ConstBufferSequence& __buffers,
- const endpoint_type& __recipient,
- socket_base::message_flags __flags)
- {
- return send_to(__buffers, __recipient, __flags,
- __throw_on_error{"basic_datagram_socket::send_to"});
- }
-
- template<typename _ConstBufferSequence>
- size_t
- send_to(const _ConstBufferSequence& __buffers,
- const endpoint_type& __recipient,
- socket_base::message_flags __flags, error_code& __ec)
- {
- #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
- socket_base::__msg_hdr __msg(__buffers, __recipient);
- ssize_t __result = ::sendmsg(this->native_handle(), &__msg,
- static_cast<int>(__flags));
- if (__result == -1)
- {
- __ec.assign(errno, generic_category());
- return 0;
- }
- __ec.clear();
- __recipient.resize(__msg.msg_namelen);
- return __result;
- #else
- __ec = std::make_error_code(errc::operation_not_supported);
- return 0;
- #endif
- }
-
- template<typename _ConstBufferSequence, typename _CompletionToken>
- __deduced_t<_CompletionToken, void(error_code, size_t)>
- async_send_to(const _ConstBufferSequence& __buffers,
- const endpoint_type& __recipient,
- _CompletionToken&& __token)
- {
- return async_send_to(__buffers, __recipient,
- socket_base::message_flags(),
- std::forward<_CompletionToken>(__token));
- }
-
- template<typename _ConstBufferSequence, typename _CompletionToken>
- __deduced_t<_CompletionToken, void(error_code, size_t)>
- async_send_to(const _ConstBufferSequence& __buffers,
- const endpoint_type& __recipient,
- socket_base::message_flags __flags,
- _CompletionToken&& __token)
- {
- async_completion<_CompletionToken, void(error_code, size_t)>
- __init{__token};
-
- this->get_executor().context().async_wait( this->native_handle(),
- socket_base::wait_write,
- [__h = std::move(__init.completion_handler),
- &__buffers, __flags = static_cast<int>(__flags),
- __recipient = std::move(__recipient),
- __fd = this->native_handle()]
- (error_code __ec) mutable {
- if (__ec)
- {
- __h(__ec);
- return;
- }
- #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
- socket_base::__msg_hdr __msg(__buffers, __recipient);
- ssize_t __result = ::sendmsg(__fd, &__msg, __flags);
- if (__result == -1)
- {
- __ec.assign(errno, generic_category());
- __result = 0;
- }
- else
- {
- __ec.clear();
- __recipient.resize(__msg.msg_namelen);
- }
- __h(__ec, __result);
- #else
- __h(std::make_error_code(errc::operation_not_supported), 0);
- #endif
- });
- return __init.result.get();
- }
- };
-
- template<typename _Protocol>
- class basic_stream_socket : public basic_socket<_Protocol>
- {
- using __base = basic_socket<_Protocol>;
-
- public:
- // types:
-
- typedef int native_handle_type;
- typedef _Protocol protocol_type;
- typedef typename protocol_type::endpoint endpoint_type;
-
- // construct / copy / destroy:
-
- explicit
- basic_stream_socket(io_context& __ctx) : __base(__ctx) { }
-
- basic_stream_socket(io_context& __ctx, const protocol_type& __protocol)
- : __base(__ctx, __protocol) { }
-
- basic_stream_socket(io_context& __ctx, const endpoint_type& __endpoint)
- : __base(__ctx, __endpoint) { }
-
- basic_stream_socket(io_context& __ctx, const protocol_type& __protocol,
- const native_handle_type& __native_socket)
- : __base(__ctx, __protocol, __native_socket) { }
-
- basic_stream_socket(const basic_stream_socket&) = delete;
-
- basic_stream_socket(basic_stream_socket&& __rhs) = default;
-
- template<typename _OtherProtocol, typename _Requires
- = _Require<is_convertible<_OtherProtocol, _Protocol>>>
- basic_stream_socket(basic_stream_socket<_OtherProtocol>&& __rhs)
- : __base(std::move(__rhs)) { }
-
- ~basic_stream_socket() = default;
-
- basic_stream_socket& operator=(const basic_stream_socket&) = delete;
-
- basic_stream_socket& operator=(basic_stream_socket&& __rhs) = default;
-
- template<class _OtherProtocol>
- enable_if_t<is_convertible<_OtherProtocol, _Protocol>::value,
- basic_stream_socket&>
- operator=(basic_stream_socket<_OtherProtocol>&& __rhs)
- {
- __base::operator=(std::move(__rhs));
- return *this;
- }
-
- // basic_stream_socket operations:
-
- template<class _MutableBufferSequence>
- size_t
- receive(const _MutableBufferSequence& __buffers)
- {
- return receive(__buffers, socket_base::message_flags(),
- __throw_on_error{"basic_stream_socket::receive"});
- }
-
- template<class _MutableBufferSequence>
- size_t
- receive(const _MutableBufferSequence& __buffers, error_code& __ec)
- { return receive(__buffers, socket_base::message_flags(), __ec); }
-
- template<class _MutableBufferSequence>
- size_t
- receive(const _MutableBufferSequence& __buffers,
- socket_base::message_flags __flags)
- {
- return receive(__buffers, __flags,
- __throw_on_error{"basic_stream_socket::receive"});
- }
-
- template<class _MutableBufferSequence>
- size_t
- receive(const _MutableBufferSequence& __buffers,
- socket_base::message_flags __flags, error_code& __ec)
- {
- if (__buffer_empty(__buffers))
- {
- __ec.clear();
- return 0;
- }
- #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
- socket_base::__msg_hdr __msg(__buffers);
- ssize_t __result = ::recvmsg(this->native_handle(), &__msg,
- static_cast<int>(__flags));
- if (__result >= 0)
- {
- __ec.clear();
- return __result;
- }
- __ec.assign(errno, generic_category());
- #else
- __ec = std::make_error_code(errc::operation_not_supported);
- #endif
- return 0;
- }
-
- template<class _MutableBufferSequence, class _CompletionToken>
- __deduced_t<_CompletionToken, void(error_code, size_t)>
- async_receive(const _MutableBufferSequence& __buffers,
- _CompletionToken&& __token)
- {
- return async_receive(__buffers, socket_base::message_flags(),
- std::forward<_CompletionToken>(__token));
- }
-
- template<class _MutableBufferSequence, class _CompletionToken>
- __deduced_t<_CompletionToken, void(error_code, size_t)>
- async_receive(const _MutableBufferSequence& __buffers,
- socket_base::message_flags __flags,
- _CompletionToken&& __token)
- {
- async_completion<_CompletionToken, void(error_code, size_t)>
- __init{__token};
-
- if (__buffer_empty(__buffers))
- {
- auto __ex = net::get_associated_executor(
- __init.completion_handler, this->get_executor());
- auto __a = get_associated_allocator(
- __init.completion_handler, std::allocator<void>());
- __ex.post(
- [__h=std::move(__init.completion_handler)] () mutable
- { __h(error_code{}, 0); }, __a);
- return __init.result.get();
- }
-
- this->get_executor().context().async_wait(this->native_handle(),
- socket_base::wait_read,
- [__h = std::move(__init.completion_handler),
- &__buffers, __flags = static_cast<int>(__flags),
- __fd = this->native_handle()]
- (error_code __ec) mutable {
- if (__ec)
- {
- __h(__ec);
- return;
- }
- #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
- socket_base::__msg_hdr __msg(__buffers);
- ssize_t __result = ::recvmsg(__fd, &__msg, __flags);
- if (__result == -1)
- {
- __ec.assign(errno, generic_category());
- __result = 0;
- }
- else
- __ec.clear();
- __h(__ec, __result);
- #else
- __h(std::make_error_code(errc::operation_not_supported), 0);
- #endif
- });
- return __init.result.get();
- }
-
- template<class _ConstBufferSequence>
- size_t
- send(const _ConstBufferSequence& __buffers)
- {
- return send(__buffers, socket_base::message_flags(),
- __throw_on_error{"basic_stream_socket::send"});
- }
-
- template<class _ConstBufferSequence>
- size_t
- send(const _ConstBufferSequence& __buffers, error_code& __ec)
- { return send(__buffers, socket_base::message_flags(), __ec); }
-
- template<class _ConstBufferSequence>
- size_t
- send(const _ConstBufferSequence& __buffers,
- socket_base::message_flags __flags)
- {
- return send(__buffers, socket_base::message_flags(),
- __throw_on_error{"basic_stream_socket::send"});
- }
-
- template<class _ConstBufferSequence>
- size_t
- send(const _ConstBufferSequence& __buffers,
- socket_base::message_flags __flags, error_code& __ec)
- {
- if (__buffer_empty(__buffers))
- {
- __ec.clear();
- return 0;
- }
- #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
- socket_base::__msg_hdr __msg(__buffers);
- ssize_t __result = ::sendmsg(this->native_handle(), &__msg,
- static_cast<int>(__flags));
- if (__result >= 0)
- {
- __ec.clear();
- return __result;
- }
- __ec.assign(errno, generic_category());
- #else
- __ec = std::make_error_code(errc::operation_not_supported);
- #endif
- return 0;
- }
-
- template<class _ConstBufferSequence, class _CompletionToken>
- __deduced_t<_CompletionToken, void(error_code, size_t)>
- async_send(const _ConstBufferSequence& __buffers,
- _CompletionToken&& __token)
- {
- return async_send(__buffers, socket_base::message_flags(),
- std::forward<_CompletionToken>(__token));
- }
-
- template<class _ConstBufferSequence, class _CompletionToken>
- __deduced_t<_CompletionToken, void(error_code, size_t)>
- async_send(const _ConstBufferSequence& __buffers,
- socket_base::message_flags __flags,
- _CompletionToken&& __token)
- {
- async_completion<_CompletionToken, void(error_code, size_t)>
- __init{__token};
-
- if (__buffer_empty(__buffers))
- {
- auto __ex = net::get_associated_executor(
- __init.completion_handler, this->get_executor());
- auto __a = get_associated_allocator(
- __init.completion_handler, std::allocator<void>());
- __ex.post(
- [__h=std::move(__init.completion_handler)] () mutable
- { __h(error_code{}, 0); }, __a);
- return __init.result.get();
- }
-
- this->get_executor().context().async_wait(this->native_handle(),
- socket_base::wait_write,
- [__h = std::move(__init.completion_handler),
- &__buffers, __flags = static_cast<int>(__flags),
- __fd = this->native_handle()]
- (error_code __ec) mutable {
- if (__ec)
- {
- __h(__ec);
- return;
- }
- #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
- socket_base::__msg_hdr __msg(__buffers);
- ssize_t __result = ::sendmsg(__fd, &__msg, __flags);
- if (__result == -1)
- {
- __ec.assign(errno, generic_category());
- __result = 0;
- }
- else
- __ec.clear();
- __h(__ec, __result);
- #else
- __h(std::make_error_code(errc::operation_not_supported), 0);
- #endif
- });
- return __init.result.get();
- }
-
- template<class _MutableBufferSequence>
- size_t
- read_some(const _MutableBufferSequence& __buffers)
- {
- return receive(__buffers,
- __throw_on_error{"basic_stream_socket::read_some"});
- }
-
- template<class _MutableBufferSequence>
- size_t
- read_some(const _MutableBufferSequence& __buffers, error_code& __ec)
- { return receive(__buffers, __ec); }
-
- template<class _MutableBufferSequence, class _CompletionToken>
- __deduced_t<_CompletionToken, void(error_code, size_t)>
- async_read_some(const _MutableBufferSequence& __buffers,
- _CompletionToken&& __token)
- {
- return async_receive(__buffers,
- std::forward<_CompletionToken>(__token));
- }
-
- template<class _ConstBufferSequence>
- size_t
- write_some(const _ConstBufferSequence& __buffers)
- {
- return send(__buffers,
- __throw_on_error{"basic_stream_socket:write_some"});
- }
-
- template<class _ConstBufferSequence>
- size_t
- write_some(const _ConstBufferSequence& __buffers, error_code& __ec)
- { return send(__buffers, __ec); }
-
- template<class _ConstBufferSequence, class _CompletionToken>
- __deduced_t<_CompletionToken, void(error_code, size_t)>
- async_write_some(const _ConstBufferSequence& __buffers,
- _CompletionToken&& __token)
- {
- return async_send(__buffers,
- std::forward<_CompletionToken>(__token));
- }
- };
-
- template<typename _AcceptableProtocol>
- class basic_socket_acceptor
- : public socket_base, private __basic_socket_impl<_AcceptableProtocol>
- {
- using __base = __basic_socket_impl<_AcceptableProtocol>;
-
- public:
- // types:
-
- typedef io_context::executor_type executor_type;
- typedef int native_handle_type;
- typedef _AcceptableProtocol protocol_type;
- typedef typename protocol_type::endpoint endpoint_type;
- typedef typename protocol_type::socket socket_type;
-
- // construct / copy / destroy:
-
- explicit
- basic_socket_acceptor(io_context& __ctx)
- : __base(__ctx), _M_protocol(endpoint_type{}.protocol()) { }
-
- basic_socket_acceptor(io_context& __ctx,
- const protocol_type& __protocol)
- : __base(__ctx), _M_protocol(__protocol)
- { open(__protocol); }
-
- basic_socket_acceptor(io_context& __ctx, const endpoint_type& __endpoint,
- bool __reuse_addr = true)
- : basic_socket_acceptor(__ctx, __endpoint.protocol())
- {
- if (__reuse_addr)
- set_option(reuse_address(true));
- bind(__endpoint);
- listen();
- }
-
- basic_socket_acceptor(io_context& __ctx, const protocol_type& __protocol,
- const native_handle_type& __native_acceptor)
- : basic_socket_acceptor(__ctx, __protocol)
- { assign(__protocol, __native_acceptor); }
-
- basic_socket_acceptor(const basic_socket_acceptor&) = delete;
-
- basic_socket_acceptor(basic_socket_acceptor&&) = default;
-
- template<typename _OtherProtocol, typename _Requires
- = _Require<is_convertible<_OtherProtocol, protocol_type>>>
- basic_socket_acceptor(basic_socket_acceptor<_OtherProtocol>&& __rhs)
- : __base(std::move(__rhs)) { }
-
- ~basic_socket_acceptor() = default;
-
- basic_socket_acceptor& operator=(const basic_socket_acceptor&) = delete;
-
- basic_socket_acceptor& operator=(basic_socket_acceptor&&) = default;
-
- template<class _OtherProtocol>
- enable_if_t<is_convertible<_OtherProtocol, protocol_type>::value,
- basic_socket_acceptor&>
- operator=(basic_socket_acceptor<_OtherProtocol>&& __rhs)
- {
- __base::operator=(std::move(__rhs));
- return *this;
- }
-
- // basic_socket_acceptor operations:
-
- executor_type get_executor() noexcept { return __base::get_executor(); }
-
- native_handle_type
- native_handle() noexcept { return __base::native_handle(); }
-
- void
- open(const protocol_type& __protocol = protocol_type())
- { open(__protocol, __throw_on_error{"basic_socket_acceptor::open"}); }
-
- void
- open(const protocol_type& __protocol, error_code& __ec)
- { __base::open(__protocol, __ec); }
-
- void
- assign(const protocol_type& __protocol,
- const native_handle_type& __native_acceptor)
- {
- assign(__protocol, __native_acceptor,
- __throw_on_error{"basic_socket_acceptor::assign"});
- }
-
- void
- assign(const protocol_type& __protocol,
- const native_handle_type& __native_acceptor,
- error_code& __ec)
- { __base::assign(__protocol, __native_acceptor, __ec); }
-
- native_handle_type release()
- { return release(__throw_on_error{"basic_socket_acceptor::release"}); }
-
- native_handle_type release(error_code& __ec)
- { return __base::release(__ec); }
-
- _GLIBCXX_NODISCARD bool
- is_open() const noexcept { return __base::is_open(); }
-
- void
- close() { close(__throw_on_error{"basic_socket_acceptor::close"}); }
-
- void
- close(error_code& __ec) { __base::_close(__ec); }
-
- void
- cancel() { cancel(__throw_on_error{"basic_socket_acceptor::cancel"}); }
-
- void
- cancel(error_code& __ec) { __base::cancel(__ec); }
-
- template<typename _SettableSocketOption>
- void
- set_option(const _SettableSocketOption& __option)
- {
- set_option(__option,
- __throw_on_error{"basic_socket_acceptor::set_option"});
- }
-
- template<typename _SettableSocketOption>
- void
- set_option(const _SettableSocketOption& __option, error_code& __ec)
- { __base::set_option(__option, __ec); }
-
- template<typename _GettableSocketOption>
- void
- get_option(_GettableSocketOption& __option) const
- {
- get_option(__option,
- __throw_on_error{"basic_socket_acceptor::get_option"});
- }
-
- template<typename _GettableSocketOption>
- void
- get_option(_GettableSocketOption& __option, error_code& __ec) const
- { __base::get_option(__option, __ec); }
-
- template<typename _IoControlCommand>
- void
- io_control(_IoControlCommand& __command)
- {
- io_control(__command,
- __throw_on_error{"basic_socket_acceptor::io_control"});
- }
-
- template<typename _IoControlCommand>
- void
- io_control(_IoControlCommand& __command, error_code& __ec)
- { __base::io_control(__command, __ec); }
-
- void
- non_blocking(bool __mode)
- {
- non_blocking(__mode,
- __throw_on_error{"basic_socket_acceptor::non_blocking"});
- }
-
- void
- non_blocking(bool __mode, error_code& __ec)
- { __base::non_blocking(__mode, __ec); }
-
- bool non_blocking() const { return __base::non_blocking(); }
-
- void
- native_non_blocking(bool __mode)
- {
- native_non_blocking(__mode, __throw_on_error{
- "basic_socket_acceptor::native_non_blocking"});
- }
-
- void
- native_non_blocking(bool __mode, error_code& __ec)
- { __base::native_non_blocking(__mode, __ec); }
-
- bool
- native_non_blocking() const
- { return __base::native_non_blocking(); }
-
- void
- bind(const endpoint_type& __endpoint)
- {
- return bind(__endpoint,
- __throw_on_error{"basic_socket_acceptor::bind"});
- }
-
- void
- bind(const endpoint_type& __endpoint, error_code& __ec)
- { __base::bind(__endpoint, __ec); }
-
- void
- listen(int __backlog = max_listen_connections)
- {
- return listen(__backlog,
- __throw_on_error{"basic_socket_acceptor::listen"});
- }
-
- void
- listen(int __backlog, error_code& __ec)
- {
- #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
- if (::listen(native_handle(), __backlog) == -1)
- __ec.assign(errno, generic_category());
- else
- __ec.clear();
- #else
- __ec = std::make_error_code(errc::operation_not_supported);
- #endif
- }
-
- endpoint_type
- local_endpoint() const
- {
- return local_endpoint(
- __throw_on_error{"basic_socket_acceptor::local_endpoint"});
- }
-
- endpoint_type
- local_endpoint(error_code& __ec) const
- { return __base::local_endpoint(__ec); }
-
- void
- enable_connection_aborted(bool __mode)
- { __base::_M_bits.enable_connection_aborted = __mode; }
-
- bool
- enable_connection_aborted() const
- { return __base::_M_bits.enable_connection_aborted; }
-
- socket_type
- accept()
- { return accept(__throw_on_error{"basic_socket_acceptor::accept"}); }
-
- socket_type
- accept(error_code& __ec)
- { return accept(get_executor().context(), __ec); }
-
- socket_type accept(io_context& __ctx)
- {
- return accept(__ctx,
- __throw_on_error{"basic_socket_acceptor::accept"});
- }
-
- socket_type
- accept(io_context& __ctx, error_code& __ec)
- {
- #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
- do
- {
- int __h = ::accept(native_handle(), nullptr, 0);
- if (__h != -1)
- {
- __ec.clear();
- return socket_type{__ctx, _M_protocol, __h};
- }
- } while (errno == ECONNABORTED && enable_connection_aborted());
- __ec.assign(errno, generic_category());
- #else
- __ec = std::make_error_code(errc::operation_not_supported);
- #endif
- return socket_type{__ctx};
- }
-
- template<class _CompletionToken>
- __deduced_t<_CompletionToken, void(error_code, socket_type)>
- async_accept(_CompletionToken&& __token)
- {
- return async_accept(get_executor().context(),
- std::forward<_CompletionToken>(__token));
- }
-
- template<class _CompletionToken>
- __deduced_t<_CompletionToken, void(error_code, socket_type)>
- async_accept(io_context& __ctx, _CompletionToken&& __token)
- {
- async_completion<_CompletionToken, void(error_code, socket_type)>
- __init{__token};
-
- __ctx.get_executor().context().async_wait(native_handle(),
- socket_base::wait_read,
- [__h = std::move(__init.completion_handler),
- __connabort = enable_connection_aborted(),
- __fd = native_handle(),
- __protocol = _M_protocol,
- &__ctx
- ]
- (error_code __ec) mutable {
- if (__ec)
- {
- __h(__ec, socket_type(__ctx));
- return;
- }
- #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
- do
- {
- int __newfd = ::accept(__fd, nullptr, 0);
- if (__newfd != -1)
- {
- __ec.clear();
- __h(__ec, socket_type{__ctx, __protocol, __newfd});
- return;
- }
- } while (errno == ECONNABORTED && __connabort);
- __ec.assign(errno, generic_category());
- __h(__ec, socket_type(__ctx));
- #else
- __h(std::make_error_code(errc::operation_not_supported), 0);
- #endif
- });
- return __init.result.get();
- }
-
- socket_type
- accept(endpoint_type& __endpoint)
- {
- return accept(get_executor().context(), __endpoint,
- __throw_on_error{"basic_socket_acceptor::accept"});
- }
-
- socket_type
- accept(endpoint_type& __endpoint, error_code& __ec)
- { return accept(get_executor().context(), __endpoint, __ec); }
-
- socket_type
- accept(io_context& __ctx, endpoint_type& __endpoint)
- {
- return accept(__ctx, __endpoint,
- __throw_on_error{"basic_socket_acceptor::accept"});
- }
-
- socket_type
- accept(io_context& __ctx, endpoint_type& __endpoint, error_code& __ec)
- {
- #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
- do
- {
- socklen_t __len = __endpoint.capacity();
- int __h = ::accept(native_handle(), (sockaddr*)__endpoint.data(),
- &__len);
- if (__h != -1)
- {
- __endpoint.resize(__len);
- return socket_type{__ctx, _M_protocol, __h};
- }
- } while (errno == ECONNABORTED && enable_connection_aborted());
- __ec.assign(errno, generic_category());
- #else
- __ec = std::make_error_code(errc::operation_not_supported);
- #endif
- return socket_type{__ctx};
- }
-
- template<class _CompletionToken>
- __deduced_t<_CompletionToken, void(error_code, socket_type)>
- async_accept(endpoint_type& __endpoint,
- _CompletionToken&& __token)
- {
- return async_accept(get_executor().context(), __endpoint,
- std::forward<_CompletionToken>(__token));
- }
-
- template<class _CompletionToken>
- __deduced_t<_CompletionToken, void(error_code, socket_type)>
- async_accept(io_context& __ctx, endpoint_type& __endpoint,
- _CompletionToken&& __token)
- {
- async_completion<_CompletionToken, void(error_code, socket_type)>
- __init{__token};
-
- __ctx.get_executor().context().async_wait(native_handle(),
- socket_base::wait_read,
- [__h = std::move(__init.completion_handler),
- __ep = std::move(__endpoint),
- __connabort = enable_connection_aborted(),
- __fd = native_handle(),
- &__ctx
- ]
- (error_code __ec) mutable {
- if (__ec)
- {
- __h(__ec, socket_type(__ctx));
- return;
- }
- #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
- do
- {
- socklen_t __len = __ep.capacity();
- int __newfd = ::accept(__fd, __ep.data, &__len);
- if (__newfd != -1)
- {
- __ep.resize(__len);
- auto __protocol = __ep.protocol();
- __ec.clear();
- __h(__ec, socket_type{__ctx, __protocol, __newfd});
- return;
- }
- } while (errno == ECONNABORTED && __connabort);
- __ec.assign(errno, generic_category());
- #else
- __ec = std::make_error_code(errc::operation_not_supported);
- #endif
- __h(__ec, socket_type(__ctx));
- });
- return __init.result.get();
- }
-
- void
- wait(wait_type __w)
- { wait(__w, __throw_on_error{"basic_socket_acceptor::wait"}); }
-
- void
- wait(wait_type __w, error_code& __ec)
- {
- #ifdef _GLIBCXX_HAVE_POLL_H
- ::pollfd __fds;
- __fds.fd = native_handle();
- __fds.events = __w; // __w | POLLIN;
- if (::poll(&__fds, 1, -1) == -1)
- __ec.assign(errno, generic_category());
- else
- __ec.clear();
- #else
- __ec = std::make_error_code(errc::operation_not_supported);
- #endif
- }
-
- template<class _CompletionToken>
- __deduced_t<_CompletionToken, void(error_code)>
- async_wait(wait_type __w, _CompletionToken&& __token)
- {
- async_completion<_CompletionToken, void(error_code)> __init{__token};
- get_executor().context().async_wait( native_handle(),
- static_cast<int>(__w),
- [__h = std::move(__init.completion_handler)]
- (error_code __ec) mutable {
- __h(__ec);
- });
- return __init.result.get();
- }
-
- private:
- protocol_type _M_protocol;
- };
-
- // @}
-
- /** @brief Socket streams
- * @{
- */
-
- template<typename _Protocol, typename _Clock, typename _WaitTraits>
- class basic_socket_streambuf : public basic_streambuf<char>
- {
- public:
- // types:
-
- typedef _Protocol protocol_type;
- typedef typename protocol_type::endpoint endpoint_type;
- typedef _Clock clock_type;
- typedef typename clock_type::time_point time_point;
- typedef typename clock_type::duration duration;
- typedef _WaitTraits wait_traits_type;
-
- // construct / copy / destroy:
-
- basic_socket_streambuf() : _M_socket(_S_ctx()) { }
-
- explicit
- basic_socket_streambuf(basic_stream_socket<protocol_type> __s)
- : _M_socket(std::move(__s)) { }
-
- basic_socket_streambuf(const basic_socket_streambuf&) = delete;
-
- basic_socket_streambuf(basic_socket_streambuf&& __rhs); // TODO
-
-
- virtual ~basic_socket_streambuf(); // TODO
-
- basic_socket_streambuf& operator=(const basic_socket_streambuf&) = delete;
-
- basic_socket_streambuf& operator=(basic_socket_streambuf&& __rhs); // TODO
-
- // members:
-
- basic_socket_streambuf* connect(const endpoint_type& __e); // TODO
-
- template<typename... _Args>
- basic_socket_streambuf* connect(_Args&&... ); // TODO
-
- basic_socket_streambuf* close(); // TODO
-
- basic_socket<protocol_type>& socket() { return _M_socket; }
-
- error_code error() const noexcept { return _M_ec; }
-
- time_point expiry() const { return _M_expiry; }
-
- void
- expires_at(const time_point& __t)
- { _M_expiry = __t; }
-
- void
- expires_after(const duration& __d)
- { expires_at(clock_type::now() + __d); }
-
- protected:
- // overridden virtual functions: // TODO
- virtual int_type underflow() override;
- virtual int_type pbackfail(int_type __c = traits_type::eof()) override;
- virtual int_type overflow(int_type __c = traits_type::eof()) override;
- virtual int sync() override;
- virtual streambuf* setbuf(char_type* __s, streamsize __n) override;
-
- private:
- static io_context&
- _S_ctx()
- {
- static io_context __ctx;
- return __ctx;
- }
-
- basic_stream_socket<protocol_type> _M_socket;
- error_code _M_ec;
- time_point _M_expiry{ time_point::max() };
- };
-
- template<typename _Protocol, class _Clock, typename _WaitTraits>
- class basic_socket_iostream : public basic_iostream<char>
- {
- using __streambuf_type
- = basic_socket_streambuf<_Protocol, _Clock, _WaitTraits>;
-
- public:
- // types:
-
- typedef _Protocol protocol_type;
- typedef typename protocol_type::endpoint endpoint_type;
- typedef _Clock clock_type;
- typedef typename clock_type::time_point time_point;
- typedef typename clock_type::duration duration;
- typedef _WaitTraits wait_traits_type;
-
- // construct / copy / destroy:
-
- // TODO base-from-member ?
- basic_socket_iostream() : basic_iostream(nullptr), _M_sb()
- {
- this->init(std::addressof(_M_sb));
- this->setf(std::ios::unitbuf);
- }
-
- explicit
- basic_socket_iostream(basic_stream_socket<protocol_type> __s)
- : basic_iostream(nullptr), _M_sb(std::move(__s))
- {
- this->init(std::addressof(_M_sb));
- this->setf(std::ios::unitbuf);
- }
-
- basic_socket_iostream(const basic_socket_iostream&) = delete;
-
- basic_socket_iostream(basic_socket_iostream&& __rhs)
- : basic_iostream(nullptr), _M_sb(std::move(__rhs._M_sb))
- // XXX ??? ^^^^^^^
- {
- // XXX ??? this->init(std::addressof(_M_sb));
- this->set_rbduf(std::addressof(_M_sb));
- }
-
- template<typename... _Args>
- explicit
- basic_socket_iostream(_Args&&... __args)
- : basic_iostream(nullptr), _M_sb()
- {
- this->init(std::addressof(_M_sb));
- this->setf(std::ios::unitbuf);
- connect(forward<_Args>(__args)...);
- }
-
- basic_socket_iostream& operator=(const basic_socket_iostream&) = delete;
-
- basic_socket_iostream& operator=(basic_socket_iostream&& __rhs); // TODO
-
- // members:
-
- template<typename... _Args>
- void
- connect(_Args&&... __args)
- {
- if (rdbuf()->connect(forward<_Args>(__args)...) == nullptr)
- this->setstate(failbit);
- }
-
- void
- close()
- {
- if (rdbuf()->close() == nullptr)
- this->setstate(failbit);
- }
-
- basic_socket_streambuf<protocol_type, clock_type, wait_traits_type>*
- rdbuf() const
- { return const_cast<__streambuf_type*>(std::addressof(_M_sb)); }
-
- basic_socket<protocol_type>& socket() { return rdbuf()->socket(); }
- error_code error() const noexcept { return rdbuf()->error(); }
-
- time_point expiry() const { return rdbuf()->expiry(); }
- void expires_at(const time_point& __t) { rdbuf()->expires_at(__t); }
- void expires_after(const duration& __d) { rdbuf()->expires_after(__d); }
-
- private:
- __streambuf_type _M_sb;
- };
-
- // @}
-
- /** @brief synchronous connect operations
- * @{
- */
-
- template<typename _Protocol, typename _EndpointSequence,
- typename _ConnectCondition>
- inline typename _Protocol::endpoint
- connect(basic_socket<_Protocol>& __s,
- const _EndpointSequence& __endpoints,
- _ConnectCondition __c, error_code& __ec)
- {
- __ec.clear();
- bool __found = false;
- for (auto& __ep : __endpoints)
- {
- if (__c(__ec, __ep))
- {
- __found = true;
- __s.close(__ec);
- if (!__ec)
- __s.open(__ep.protocol(), __ec);
- if (!__ec)
- __s.connect(__ep, __ec);
- if (!__ec)
- return __ep;
- }
- }
- if (!__found)
- __ec = socket_errc::not_found;
- return typename _Protocol::endpoint{};
- }
-
- template<typename _Protocol, typename _InputIterator,
- typename _ConnectCondition>
- inline _InputIterator
- connect(basic_socket<_Protocol>& __s,
- _InputIterator __first, _InputIterator __last,
- _ConnectCondition __c, error_code& __ec)
- {
- __ec.clear();
- bool __found = false;
- for (auto __i = __first; __i != __last; ++__i)
- {
- if (__c(__ec, *__i))
- {
- __found = true;
- __s.close(__ec);
- if (!__ec)
- __s.open(typename _Protocol::endpoint(*__i).protocol(), __ec);
- if (!__ec)
- __s.connect(*__i, __ec);
- if (!__ec)
- return __i;
- }
- }
- if (!__found)
- __ec = socket_errc::not_found;
- return __last;
- }
-
- template<typename _Protocol, typename _EndpointSequence,
- typename _ConnectCondition>
- inline typename _Protocol::endpoint
- connect(basic_socket<_Protocol>& __s,
- const _EndpointSequence& __endpoints,
- _ConnectCondition __c)
- {
- return net::connect(__s, __endpoints, __c, __throw_on_error{"connect"});
- }
-
- template<typename _Protocol, typename _InputIterator,
- typename _ConnectCondition>
- inline _InputIterator
- connect(basic_socket<_Protocol>& __s,
- _InputIterator __first, _InputIterator __last,
- _ConnectCondition __c)
- {
- return net::connect(__s, __first, __last, __c,
- __throw_on_error{"connect"});
- }
-
- template<typename _Protocol, typename _EndpointSequence>
- inline typename _Protocol::endpoint
- connect(basic_socket<_Protocol>& __s,
- const _EndpointSequence& __endpoints)
- {
- return net::connect(__s, __endpoints, [](auto, auto){ return true; },
- __throw_on_error{"connect"});
- }
-
- template<typename _Protocol, typename _EndpointSequence>
- inline typename _Protocol::endpoint
- connect(basic_socket<_Protocol>& __s,
- const _EndpointSequence& __endpoints,
- error_code& __ec)
- {
- return net::connect(__s, __endpoints, [](auto, auto){ return true; },
- __ec);
- }
-
- template<typename _Protocol, typename _InputIterator>
- inline _InputIterator
- connect(basic_socket<_Protocol>& __s,
- _InputIterator __first, _InputIterator __last)
- {
- return net::connect(__s, __first, __last, [](auto, auto){ return true; },
- __throw_on_error{"connect"});
- }
-
- template<typename _Protocol, typename _InputIterator>
- inline _InputIterator
- connect(basic_socket<_Protocol>& __s,
- _InputIterator __first, _InputIterator __last,
- error_code& __ec)
- {
- return net::connect(__s, __first, __last, [](auto, auto){ return true; },
- __ec);
- }
-
- // @}
-
- /** @brief asynchronous connect operations
- * @{
- */
-
- template<typename _Protocol, typename _EndpointSequence,
- typename _ConnectCondition, typename _CompletionToken>
- inline
- __deduced_t<_CompletionToken,
- void(error_code, typename _Protocol::endpoint)>
- async_connect(basic_socket<_Protocol>& __s,
- const _EndpointSequence& __endpoints,
- _ConnectCondition __c, _CompletionToken&& __token); // TODO
-
- template<typename _Protocol, typename _EndpointSequence,
- typename _CompletionToken>
- inline
- __deduced_t<_CompletionToken,
- void(error_code, typename _Protocol::endpoint)>
- async_connect(basic_socket<_Protocol>& __s,
- const _EndpointSequence& __endpoints,
- _CompletionToken&& __token)
- {
- return net::async_connect(__s, __endpoints,
- [](auto, auto){ return true; },
- forward<_CompletionToken>(__token));
- }
-
- template<typename _Protocol, typename _InputIterator,
- typename _ConnectCondition, typename _CompletionToken>
- inline
- __deduced_t<_CompletionToken, void(error_code, _InputIterator)>
- async_connect(basic_socket<_Protocol>& __s,
- _InputIterator __first, _InputIterator __last,
- _ConnectCondition __c, _CompletionToken&& __token); // TODO
-
- template<typename _Protocol, typename _InputIterator,
- typename _CompletionToken>
- inline
- __deduced_t<_CompletionToken, void(error_code, _InputIterator)>
- async_connect(basic_socket<_Protocol>& __s,
- _InputIterator __first, _InputIterator __last,
- _CompletionToken&& __token)
- {
- return net::async_connect(__s, __first, __last,
- [](auto, auto){ return true; },
- forward<_CompletionToken>(__token));
- }
-
- // @}
-
- #endif // _GLIBCXX_HAVE_UNISTD_H
-
- // @}
-
- } // namespace v1
- } // namespace net
- } // namespace experimental
-
- _GLIBCXX_END_NAMESPACE_VERSION
- } // namespace std
-
- #endif // C++14
-
- #endif // _GLIBCXX_EXPERIMENTAL_SOCKET
|