23
23
24
24
#include < atomic>
25
25
#include < cstddef>
26
+ #include < cstdint>
26
27
#include < memory>
28
+ #include < ostream>
27
29
#include < system_error>
28
30
#include < thread>
29
31
#include < type_traits>
30
32
#include < utility>
31
33
32
34
#include " asio/dispatch.hpp"
33
35
#include " asio/io_context.hpp"
36
+ #include " asio/ip/address.hpp"
34
37
#include " async_simple/Signal.h"
35
- #include " async_simple/coro/FutureAwaiter.h"
36
- #include " async_simple/coro/SpinLock.h"
37
38
#include " ylt/easylog.hpp"
38
39
#include " ylt/util/type_traits.h"
39
40
49
50
#include < asio/read_until.hpp>
50
51
#include < asio/write.hpp>
51
52
#include < asio/write_at.hpp>
52
- #include < chrono>
53
- #include < deque>
54
53
55
54
#include " io_context_pool.hpp"
56
55
#if __has_include("ylt/util/type_traits.h")
61
60
#ifdef __linux__
62
61
#include < sys/sendfile.h>
63
62
#endif
64
-
65
63
namespace coro_io {
66
64
template <typename T>
67
65
constexpr inline bool is_lazy_v =
@@ -136,6 +134,8 @@ class callback_awaitor_base {
136
134
}
137
135
void resume () const { obj->coro_ .resume (); }
138
136
137
+ auto handler () const { return (std::size_t )obj; }
138
+
139
139
private:
140
140
Derived *obj;
141
141
};
@@ -185,6 +185,30 @@ struct post_helper {
185
185
Func func;
186
186
};
187
187
188
+ template <typename R, typename Func, typename Executor>
189
+ struct dispatch_helper {
190
+ void operator ()(auto handler) {
191
+ asio::dispatch (e, [this , handler]() {
192
+ try {
193
+ if constexpr (std::is_same_v<R, async_simple::Try<void >>) {
194
+ func ();
195
+ handler.resume ();
196
+ }
197
+ else {
198
+ auto r = func ();
199
+ handler.set_value_then_resume (std::move (r));
200
+ }
201
+ } catch (const std::exception &e) {
202
+ R er;
203
+ er.setException (std::current_exception ());
204
+ handler.set_value_then_resume (std::move (er));
205
+ }
206
+ });
207
+ }
208
+ Executor e;
209
+ Func func;
210
+ };
211
+
188
212
template <typename Func, typename Executor>
189
213
inline async_simple::coro::Lazy<
190
214
async_simple::Try<typename util::function_traits<Func>::return_type>>
@@ -205,6 +229,17 @@ post(Func func,
205
229
return post (std::move (func), e->get_asio_executor ());
206
230
}
207
231
232
+ template <typename Func, typename Executor>
233
+ inline async_simple::coro::Lazy<
234
+ async_simple::Try<typename util::function_traits<Func>::return_type>>
235
+ dispatch (Func func, Executor executor) {
236
+ using R =
237
+ async_simple::Try<typename util::function_traits<Func>::return_type>;
238
+ callback_awaitor<R> awaitor;
239
+ dispatch_helper<R, Func, Executor> helper{executor, std::move (func)};
240
+ co_return co_await awaitor.await_resume (helper);
241
+ }
242
+
208
243
namespace detail {
209
244
210
245
template <typename T>
@@ -261,7 +296,7 @@ inline async_simple::coro::Lazy<ret_type> async_io(IO_func io_func,
261
296
}
262
297
}
263
298
});
264
- if (hasCanceled) {
299
+ if (hasCanceled) [[unlikely]] {
265
300
asio::dispatch (executor, [handler]() {
266
301
handler.set_value (
267
302
std::make_error_code (std::errc::operation_canceled));
@@ -324,7 +359,8 @@ inline async_simple::coro::Lazy<std::error_code> async_accept(
324
359
asio::ip::tcp::acceptor &acceptor, asio::ip::tcp::socket &socket) noexcept {
325
360
return async_io<std::error_code>(
326
361
[&](auto &&cb) {
327
- acceptor.async_accept (socket, std::move (cb));
362
+ ELOG_INFO << " call asio acceptor.async_accept" ;
363
+ acceptor.async_accept (socket, cb);
328
364
},
329
365
acceptor);
330
366
}
@@ -415,37 +451,56 @@ template <typename executor_t>
415
451
inline async_simple::coro::Lazy<std::error_code> async_connect (
416
452
executor_t *executor, asio::ip::tcp::socket &socket,
417
453
const std::string &host, const std::string &port) noexcept {
418
- asio::ip::tcp::resolver resolver (executor->get_asio_executor ());
419
- auto result = co_await async_io<
420
- std::pair<std::error_code, asio::ip::tcp::resolver::iterator>>(
421
- [&](auto &&cb) {
422
- resolver.async_resolve (host, port, std::move (cb));
423
- },
424
- resolver);
425
-
426
- if (result.first ) {
427
- co_return result.first ;
454
+ std::error_code ec;
455
+ auto address = asio::ip::make_address (host, ec);
456
+ std::pair<std::error_code, asio::ip::tcp::resolver::iterator> result;
457
+ if (ec) {
458
+ asio::ip::tcp::resolver resolver (executor->get_asio_executor ());
459
+ result = co_await async_io<
460
+ std::pair<std::error_code, asio::ip::tcp::resolver::iterator>>(
461
+ [&](auto &&cb) {
462
+ ELOG_INFO << " call asio resolver.async_resolve" ;
463
+ resolver.async_resolve (host, port, std::move (cb));
464
+ ELOG_INFO << " call asio resolver.async_resolve over, waiting cb" ;
465
+ },
466
+ resolver);
467
+ ELOG_INFO << " call asio resolver.async_resolve cbover" ;
468
+ if (result.first ) {
469
+ co_return result.first ;
470
+ }
471
+ co_return co_await async_io<std::error_code>(
472
+ [&](auto &&cb) {
473
+ ELOG_INFO << " call asio socket.async_connect" ;
474
+ asio::async_connect (socket, result.second , std::move (cb));
475
+ },
476
+ socket);
428
477
}
429
- result = co_await async_io<
430
- std::pair<std::error_code, asio::ip::tcp::resolver::iterator>>(
478
+ else {
479
+ ELOG_INFO << " direct call without resolve" ;
480
+ uint16_t port_v;
481
+ auto result =
482
+ std::from_chars (port.data (), port.data () + port.size (), port_v);
483
+ if (result.ec != std::errc{}) {
484
+ co_return std::make_error_code (result.ec );
485
+ }
486
+ asio::ip::tcp::endpoint ep{address, port_v};
487
+ co_return co_await async_io<std::error_code>(
488
+ [&](auto &&cb) {
489
+ ELOG_INFO << " call asio socket.async_connect" ;
490
+ asio::async_connect (socket, std::span{&ep, 1 }, std::move (cb));
491
+ },
492
+ socket);
493
+ }
494
+ }
495
+
496
+ template <typename EndPointSeq>
497
+ inline async_simple::coro::Lazy<std::error_code> async_connect (
498
+ asio::ip::tcp::socket &socket, const EndPointSeq &endpoint) noexcept {
499
+ auto result = co_await async_io<std::error_code>(
431
500
[&](auto &&cb) {
432
- asio::async_connect (socket, result. second , std::move (cb));
501
+ asio::async_connect (socket, endpoint , std::move (cb));
433
502
},
434
503
socket);
435
- co_return result.first ;
436
- }
437
-
438
- template <typename executor_t , typename EndPointSeq>
439
- inline async_simple::coro::Lazy<
440
- std::pair<std::error_code, asio::ip::tcp::endpoint>>
441
- async_connect (executor_t *executor, asio::ip::tcp::socket &socket,
442
- const EndPointSeq &endpoint) noexcept {
443
- auto result =
444
- co_await async_io<std::pair<std::error_code, asio::ip::tcp::endpoint>>(
445
- [&](auto &&cb) {
446
- asio::async_connect (socket, endpoint, std::move (cb));
447
- },
448
- socket);
449
504
co_return result;
450
505
}
451
506
@@ -463,6 +518,20 @@ async_resolve(executor_t *executor, asio::ip::tcp::socket &socket,
463
518
resolver);
464
519
}
465
520
521
+ template <typename executor_t >
522
+ inline async_simple::coro::Lazy<
523
+ std::pair<std::error_code, asio::ip::tcp::resolver::iterator>>
524
+ async_resolve (executor_t *executor, const std::string &host,
525
+ const std::string &port) noexcept {
526
+ asio::ip::tcp::resolver resolver (executor->get_asio_executor ());
527
+ co_return co_await async_io<
528
+ std::pair<std::error_code, asio::ip::tcp::resolver::iterator>>(
529
+ [&](auto &&cb) {
530
+ resolver.async_resolve (host, port, std::move (cb));
531
+ },
532
+ resolver);
533
+ }
534
+
466
535
template <typename Socket>
467
536
inline async_simple::coro::Lazy<void > async_close (Socket &socket) noexcept {
468
537
callback_awaitor<void > awaitor;
@@ -479,13 +548,37 @@ inline async_simple::coro::Lazy<void> async_close(Socket &socket) noexcept {
479
548
480
549
#if defined(YLT_ENABLE_SSL) || defined(CINATRA_ENABLE_SSL)
481
550
inline async_simple::coro::Lazy<std::error_code> async_handshake (
482
- auto &ssl_stream, asio::ssl::stream_base::handshake_type type) noexcept {
551
+ auto && ssl_stream, asio::ssl::stream_base::handshake_type type) noexcept {
483
552
return async_io<std::error_code>(
484
553
[&, type](auto &&cb) {
485
554
ssl_stream->async_handshake (type, std::move (cb));
486
555
},
487
556
*ssl_stream);
488
557
}
558
+ template <typename executor_t >
559
+ inline async_simple::coro::Lazy<std::error_code> async_connect (
560
+ executor_t *executor, asio::ssl::stream<asio::ip::tcp::socket &> &socket,
561
+ const std::string &host, const std::string &port) noexcept {
562
+ auto ec = co_await async_connect (executor, socket, host, port);
563
+ if (ec) [[unlikely]] {
564
+ co_return ec;
565
+ }
566
+ ec = co_await coro_io::async_handshake (&socket,
567
+ asio::ssl::stream_base::client);
568
+ co_return ec;
569
+ }
570
+ template <typename EndPointSeq>
571
+ inline async_simple::coro::Lazy<std::error_code> async_connect (
572
+ asio::ssl::stream<asio::ip::tcp::socket &> &socket,
573
+ const EndPointSeq &endpoint) noexcept {
574
+ auto ec = co_await async_connect (socket.next_layer (), endpoint);
575
+ if (ec) [[unlikely]] {
576
+ co_return ec;
577
+ }
578
+ ec = co_await coro_io::async_handshake (&socket,
579
+ asio::ssl::stream_base::client);
580
+ co_return ec;
581
+ }
489
582
#endif
490
583
class period_timer : public asio ::steady_timer {
491
584
public:
@@ -689,34 +782,15 @@ async_sendfile(asio::ip::tcp::socket &socket, int fd, off_t offset,
689
782
}
690
783
#endif
691
784
692
- struct socket_wrapper_t {
693
- socket_wrapper_t (asio::ip::tcp::socket &&soc,
694
- coro_io::ExecutorWrapper<> *executor)
695
- : socket_(std::make_unique<asio::ip::tcp::socket>(std::move(soc))),
696
- executor_ (executor) {}
697
-
698
- private:
699
- std::unique_ptr<asio::ip::tcp::socket> socket_;
700
- coro_io::ExecutorWrapper<> *executor_;
701
- #ifdef YLT_ENABLE_SSL
702
- std::unique_ptr<asio::ssl::stream<asio::ip::tcp::socket &>> ssl_stream_;
703
- #endif
704
- public:
705
- bool use_ssl () const noexcept {
706
- #ifdef YLT_ENABLE_SSL
707
- return ssl_stream_ != nullptr ;
708
- #else
709
- return false ;
710
- #endif
711
- }
712
- auto get_executor () const noexcept { return executor_; }
713
- std::unique_ptr<asio::ip::tcp::socket> &socket () noexcept { return socket_; }
714
- #ifdef YLT_ENABLE_SSL
715
- std::unique_ptr<asio::ssl::stream<asio::ip::tcp::socket &>>
716
- &ssl_stream () noexcept {
717
- return ssl_stream_;
718
- }
719
- #endif
785
+ enum protocal { tcp, tcp_with_ssl, rdma };
786
+ struct endpoint {
787
+ asio::ip::address address;
788
+ asio::ip::port_type port;
789
+ protocal proto;
720
790
};
721
791
792
+ inline std::ostream &operator <<(std::ostream &stream, const endpoint &ep) {
793
+ return stream << ep.address .to_string () << " :" << ep.port ;
794
+ }
795
+
722
796
} // namespace coro_io
0 commit comments