From 75c51453708590aebf0cdd6bb74441ed8c4ded3a Mon Sep 17 00:00:00 2001 From: Relintai Date: Sat, 12 Feb 2022 10:42:45 +0100 Subject: [PATCH] After a lot of thinking, I reverted moving trantor to core. I realized I want to change so many things in it, that I might as well just not take compromises with the license. --- core/SCsub | 6 - core/containers/concurrent_task_queue.h | 100 -- core/containers/lock_free_queue.h | 123 -- core/containers/serial_task_queue.cpp | 65 - core/containers/serial_task_queue.h | 114 -- core/containers/task_queue.h | 76 -- core/log/async_file_logger.h | 160 --- core/log/log_stream.h | 261 ---- core/log/logger.cpp | 197 --- core/log/logger.h | 380 ------ core/loops/event_loop.h | 324 ----- core/loops/event_loop_thread.cpp | 80 -- core/loops/event_loop_thread.h | 87 -- core/loops/event_loop_thread_pool.cpp | 77 -- core/loops/event_loop_thread_pool.h | 109 -- core/loops/timer.cpp | 69 - core/loops/timer.h | 83 -- core/loops/timer_queue.h | 93 -- core/math/math.h | 18 - core/net/acceptor.cpp | 100 -- core/net/acceptor.h | 76 -- core/net/callbacks.h | 57 - core/net/channel.cpp | 113 -- core/net/channel.h | 306 ----- core/net/connections/tcp_connection_impl.h | 326 ----- core/net/connector.h | 112 -- core/net/inet_address.h | 113 -- core/net/platform/windows_support.cpp | 61 - core/net/platform/windows_support.h | 41 - core/net/resolver.h | 53 - core/net/resolvers/ares_resolver.h | 163 --- core/net/resolvers/normal_resolver.h | 80 -- core/net/socket.h | 166 --- core/net/tcp_client.h | 162 --- core/net/tcp_connection.h | 121 -- core/net/tcp_server.h | 161 --- core/polling/poller.cpp | 49 - core/polling/poller.h | 71 - core/polling/poller/epoll_poller.h | 75 -- core/polling/poller/kqueue.h | 66 - core/utilities.h | 19 - web_backends/drogon/SCsub | 13 + web_backends/drogon/detect.py | 2 + web_backends/drogon/drogon/README.md | 2 +- .../drogon/drogon/examples/benchmark/main.cc | 2 +- .../drogon/examples/client_example/main.cc | 2 +- .../plugins/SimpleReverseProxy.cc | 2 +- .../websocket_client/WebSocketClient.cc | 2 +- .../drogon/lib/inc/drogon/HttpAppFramework.h | 22 +- .../drogon/drogon/lib/inc/drogon/HttpClient.h | 10 +- .../drogon/lib/inc/drogon/HttpViewData.h | 4 +- .../drogon/lib/inc/drogon/IOThreadStorage.h | 2 +- .../drogon/lib/inc/drogon/WebSocketClient.h | 8 +- .../lib/inc/drogon/WebSocketConnection.h | 6 +- .../drogon/drogon/lib/inc/drogon/drogon.h | 8 +- .../drogon/lib/inc/drogon/drogon_test.h | 2 +- .../lib/inc/drogon/plugins/AccessLogger.h | 44 +- .../drogon/lib/inc/drogon/plugins/Plugin.h | 4 +- .../drogon/lib/inc/drogon/utils/Utilities.h | 14 +- .../drogon/lib/inc/drogon/utils/string_view.h | 5 +- .../drogon/drogon/lib/inc/http/Attribute.h | 2 +- .../drogon/drogon/lib/inc/http/CacheFile.cc | 2 +- .../drogon/drogon/lib/inc/http/CacheFile.h | 2 +- .../drogon/drogon/lib/inc/http/CacheMap.h | 16 +- .../drogon/drogon/lib/inc/http/Cookie.h | 10 +- .../drogon/drogon/lib/inc/http/HttpRequest.h | 16 +- .../drogon/lib/inc/http/HttpRequestImpl.cc | 2 +- .../drogon/lib/inc/http/HttpRequestImpl.h | 36 +- .../drogon/lib/inc/http/HttpRequestParser.cc | 10 +- .../drogon/lib/inc/http/HttpRequestParser.h | 18 +- .../drogon/drogon/lib/inc/http/HttpResponse.h | 4 +- .../drogon/lib/inc/http/HttpResponseImpl.cc | 28 +- .../drogon/lib/inc/http/HttpResponseImpl.h | 28 +- .../drogon/lib/inc/http/HttpResponseParser.cc | 8 +- .../drogon/lib/inc/http/HttpResponseParser.h | 12 +- .../drogon/drogon/lib/inc/http/HttpUtils.cc | 2 +- .../drogon/drogon/lib/inc/http/HttpUtils.h | 2 +- .../drogon/drogon/lib/inc/http/Session.h | 2 +- .../drogon/lib/inc/http/SessionManager.cc | 2 +- .../drogon/lib/inc/http/SessionManager.h | 8 +- .../drogon/drogon/lib/src/AccessLogger.cc | 64 +- .../drogon/lib/src/HttpAppFrameworkImpl.cc | 24 +- .../drogon/lib/src/HttpAppFrameworkImpl.h | 24 +- .../drogon/drogon/lib/src/HttpClientImpl.cc | 46 +- .../drogon/drogon/lib/src/HttpClientImpl.h | 28 +- .../drogon/drogon/lib/src/HttpServer.cc | 10 +- .../drogon/drogon/lib/src/HttpServer.h | 38 +- .../drogon/drogon/lib/src/ListenerManager.cc | 14 +- .../drogon/drogon/lib/src/ListenerManager.h | 24 +- .../drogon/drogon/lib/src/PluginsManager.cc | 2 +- .../drogon/drogon/lib/src/PluginsManager.h | 2 +- .../drogon/drogon/lib/src/SharedLibManager.cc | 2 +- .../drogon/drogon/lib/src/SharedLibManager.h | 8 +- .../drogon/drogon/lib/src/StaticFileRouter.cc | 2 +- .../drogon/drogon/lib/src/StaticFileRouter.h | 2 +- .../drogon/drogon/lib/src/TaskTimeoutFlag.cc | 2 +- .../drogon/drogon/lib/src/TaskTimeoutFlag.h | 8 +- .../drogon/drogon/lib/src/Utilities.cc | 10 +- .../drogon/lib/src/WebSocketClientImpl.cc | 40 +- .../drogon/lib/src/WebSocketClientImpl.h | 28 +- .../drogon/lib/src/WebSocketConnectionImpl.cc | 14 +- .../drogon/lib/src/WebSocketConnectionImpl.h | 26 +- .../lib/src/WebsocketControllersRouter.h | 2 +- .../drogon/drogon/lib/src/impl_forwards.h | 4 +- .../lib/tests/integration_test/client/main.cc | 6 +- .../integration_test/server/PipeliningTest.cc | 4 +- .../integration_test/server/TimeFilter.cc | 8 +- .../server/a-directory/page.html | 256 ++-- .../server/api_v1_CoroTest.cc | 2 +- .../tests/integration_test/server/index.html | 256 ++-- .../lib/tests/integration_test/server/main.cc | 6 +- .../lib/tests/unittests/CacheMapTest.cc | 4 +- .../drogon/lib/tests/unittests/CookieTest.cc | 2 +- .../lib/tests/unittests/MsgBufferTest.cc | 4 +- .../drogon/drogon/lib/tests/unittests/main.cc | 2 +- web_backends/drogon/drogon_web_server.cpp | 96 +- web_backends/drogon/drogon_web_server.h | 22 +- web_backends/drogon/trantor/net/Channel.cc | 97 ++ web_backends/drogon/trantor/net/Channel.h | 314 +++++ .../drogon/trantor/net/EventLoop.cc | 54 +- web_backends/drogon/trantor/net/EventLoop.h | 321 +++++ .../drogon/trantor/net/EventLoopThread.cc | 65 + .../drogon/trantor/net/EventLoopThread.h | 72 ++ .../drogon/trantor/net/EventLoopThreadPool.cc | 61 + .../drogon/trantor/net/EventLoopThreadPool.h | 92 ++ .../drogon/trantor/net/InetAddress.cc | 43 +- web_backends/drogon/trantor/net/InetAddress.h | 226 ++++ web_backends/drogon/trantor/net/Resolver.h | 57 + .../drogon/trantor/net/TcpClient.cc | 110 +- web_backends/drogon/trantor/net/TcpClient.h | 247 ++++ .../drogon/trantor/net/TcpConnection.h | 261 ++++ .../drogon/trantor/net/TcpServer.cc | 115 +- web_backends/drogon/trantor/net/TcpServer.h | 250 ++++ web_backends/drogon/trantor/net/callbacks.h | 43 + .../drogon/trantor/net/inner/Acceptor.cc | 85 ++ .../drogon/trantor/net/inner/Acceptor.h | 56 + .../drogon/trantor/net/inner/AresResolver.cc | 89 +- .../drogon/trantor/net/inner/AresResolver.h | 148 +++ .../drogon/trantor/net/inner/Connector.cc | 52 +- .../drogon/trantor/net/inner/Connector.h | 88 ++ .../trantor/net/inner/NormalResolver.cc | 46 +- .../drogon/trantor/net/inner/NormalResolver.h | 62 + .../drogon/trantor/net/inner/Poller.cc | 31 + .../drogon/trantor/net/inner/Poller.h | 54 + .../drogon/trantor/net/inner/Socket.cc | 52 +- .../drogon/trantor/net/inner/Socket.h | 157 +++ .../trantor/net/inner/TcpConnectionImpl.cc | 472 +++---- .../trantor/net/inner/TcpConnectionImpl.h | 344 +++++ .../drogon/trantor/net/inner/Timer.cc | 55 + web_backends/drogon/trantor/net/inner/Timer.h | 68 + .../drogon/trantor/net/inner/TimerQueue.cc | 49 +- .../drogon/trantor/net/inner/TimerQueue.h | 76 ++ .../trantor/net/inner/poller/EpollPoller.cc | 52 +- .../trantor/net/inner/poller/EpollPoller.h | 64 + .../drogon/trantor/net/inner/poller/KQueue.cc | 41 +- .../drogon/trantor/net/inner/poller/KQueue.h | 55 + .../trantor/tests/AsyncFileLoggerTest.cc | 45 + .../trantor/tests/AsyncFileLoggerTest1.cc | 33 + .../drogon/trantor/tests/CMakeLists.txt | 51 + .../trantor/tests/ConcurrentTaskQueueTest.cc | 37 + .../trantor/tests/DelayedSSLClientTest.cc | 64 + .../trantor/tests/DelayedSSLServerTest.cc | 46 + web_backends/drogon/trantor/tests/DnsTest.cc | 48 + .../drogon/trantor/tests/KickoffTest.cc | 46 + .../drogon/trantor/tests/LoggerTest.cc | 1139 +++++++++++++++++ .../drogon/trantor/tests/RunInLoopTest1.cc | 30 + .../drogon/trantor/tests/RunInLoopTest2.cc | 44 + .../drogon/trantor/tests/RunOnQuitTest.cc | 27 + .../drogon/trantor/tests/SSLClientTest.cc | 54 + .../drogon/trantor/tests/SSLServerTest.cc | 43 + .../drogon/trantor/tests/SendfileTest.cc | 91 ++ .../trantor/tests/SerialTaskQueueTest1.cc | 29 + .../trantor/tests/SerialTaskQueueTest2.cc | 42 + .../drogon/trantor/tests/TcpClientTest.cc | 53 + .../drogon/trantor/tests/TcpServerTest.cc | 41 + .../drogon/trantor/tests/TimerTest.cc | 33 + .../drogon/trantor/tests/TimerTest1.cc | 23 + .../drogon/trantor/tests/TimingWheelTest.cc | 48 + web_backends/drogon/trantor/tests/server.pem | 49 + .../trantor/third_party}/wepoll/LICENSE | 0 .../trantor/third_party}/wepoll/README.md | 2 +- .../trantor/third_party}/wepoll/Wepoll.c | 0 .../trantor/third_party}/wepoll/Wepoll.h | 0 .../drogon/trantor/unittests/CMakeLists.txt | 19 + .../drogon/trantor/unittests/DateUnittest.cc | 43 + .../trantor/unittests/InetAddressUnittest.cc | 22 + .../trantor/unittests/MsgBufferUnittest.cc | 78 ++ .../trantor/unittests/splitStringUnittest.cc | 159 +++ .../drogon/trantor/utils/AsyncFileLogger.cc | 48 +- .../drogon/trantor/utils/AsyncFileLogger.h | 140 ++ .../trantor/utils/ConcurrentTaskQueue.cc | 48 +- .../trantor/utils/ConcurrentTaskQueue.h | 89 ++ .../drogon/trantor/utils/Date.cc | 59 +- .../drogon/trantor/utils/Date.h | 48 +- web_backends/drogon/trantor/utils/Funcs.h | 56 + .../drogon/trantor/utils/LockFreeQueue.h | 114 ++ .../drogon/trantor/utils/LogStream.cc | 72 +- web_backends/drogon/trantor/utils/LogStream.h | 277 ++++ web_backends/drogon/trantor/utils/Logger.cc | 187 +++ web_backends/drogon/trantor/utils/Logger.h | 383 ++++++ .../drogon/trantor/utils/MsgBuffer.cc | 56 +- .../drogon/trantor/utils/MsgBuffer.h | 52 +- .../drogon/trantor/utils/NonCopyable.h | 4 + .../drogon/trantor/utils/ObjectPool.h | 76 ++ .../drogon/trantor/utils/SerialTaskQueue.cc | 49 + .../drogon/trantor/utils/SerialTaskQueue.h | 100 ++ web_backends/drogon/trantor/utils/TaskQueue.h | 58 + .../drogon/trantor/utils/TimingWheel.cc | 47 +- .../drogon/trantor/utils/TimingWheel.h | 58 +- .../drogon/trantor/utils/WindowsSupport.cc | 45 + .../drogon/trantor/utils/WindowsSupport.h | 26 + 211 files changed, 8864 insertions(+), 6660 deletions(-) delete mode 100644 core/containers/concurrent_task_queue.h delete mode 100644 core/containers/lock_free_queue.h delete mode 100644 core/containers/serial_task_queue.cpp delete mode 100644 core/containers/serial_task_queue.h delete mode 100644 core/containers/task_queue.h delete mode 100644 core/log/async_file_logger.h delete mode 100644 core/log/log_stream.h delete mode 100644 core/loops/event_loop.h delete mode 100644 core/loops/event_loop_thread.cpp delete mode 100644 core/loops/event_loop_thread.h delete mode 100644 core/loops/event_loop_thread_pool.cpp delete mode 100644 core/loops/event_loop_thread_pool.h delete mode 100644 core/loops/timer.cpp delete mode 100644 core/loops/timer.h delete mode 100644 core/loops/timer_queue.h delete mode 100644 core/net/acceptor.cpp delete mode 100644 core/net/acceptor.h delete mode 100644 core/net/callbacks.h delete mode 100644 core/net/channel.cpp delete mode 100644 core/net/channel.h delete mode 100644 core/net/connections/tcp_connection_impl.h delete mode 100644 core/net/connector.h delete mode 100644 core/net/inet_address.h delete mode 100644 core/net/platform/windows_support.cpp delete mode 100644 core/net/platform/windows_support.h delete mode 100644 core/net/resolver.h delete mode 100644 core/net/resolvers/ares_resolver.h delete mode 100644 core/net/resolvers/normal_resolver.h delete mode 100644 core/net/socket.h delete mode 100644 core/net/tcp_client.h delete mode 100644 core/net/tcp_connection.h delete mode 100644 core/net/tcp_server.h delete mode 100644 core/polling/poller.cpp delete mode 100644 core/polling/poller.h delete mode 100644 core/polling/poller/epoll_poller.h delete mode 100644 core/polling/poller/kqueue.h create mode 100644 web_backends/drogon/trantor/net/Channel.cc create mode 100644 web_backends/drogon/trantor/net/Channel.h rename core/loops/event_loop.cpp => web_backends/drogon/trantor/net/EventLoop.cc (80%) create mode 100644 web_backends/drogon/trantor/net/EventLoop.h create mode 100644 web_backends/drogon/trantor/net/EventLoopThread.cc create mode 100644 web_backends/drogon/trantor/net/EventLoopThread.h create mode 100644 web_backends/drogon/trantor/net/EventLoopThreadPool.cc create mode 100644 web_backends/drogon/trantor/net/EventLoopThreadPool.h rename core/net/inet_address.cpp => web_backends/drogon/trantor/net/InetAddress.cc (75%) create mode 100644 web_backends/drogon/trantor/net/InetAddress.h create mode 100644 web_backends/drogon/trantor/net/Resolver.h rename core/net/tcp_client.cpp => web_backends/drogon/trantor/net/TcpClient.cc (56%) create mode 100644 web_backends/drogon/trantor/net/TcpClient.h create mode 100644 web_backends/drogon/trantor/net/TcpConnection.h rename core/net/tcp_server.cpp => web_backends/drogon/trantor/net/TcpServer.cc (55%) create mode 100644 web_backends/drogon/trantor/net/TcpServer.h create mode 100644 web_backends/drogon/trantor/net/callbacks.h create mode 100644 web_backends/drogon/trantor/net/inner/Acceptor.cc create mode 100644 web_backends/drogon/trantor/net/inner/Acceptor.h rename core/net/resolvers/ares_resolver.cpp => web_backends/drogon/trantor/net/inner/AresResolver.cc (65%) create mode 100644 web_backends/drogon/trantor/net/inner/AresResolver.h rename core/net/connector.cpp => web_backends/drogon/trantor/net/inner/Connector.cc (72%) create mode 100644 web_backends/drogon/trantor/net/inner/Connector.h rename core/net/resolvers/normal_resolver.cpp => web_backends/drogon/trantor/net/inner/NormalResolver.cc (53%) create mode 100644 web_backends/drogon/trantor/net/inner/NormalResolver.h create mode 100644 web_backends/drogon/trantor/net/inner/Poller.cc create mode 100644 web_backends/drogon/trantor/net/inner/Poller.h rename core/net/socket.cpp => web_backends/drogon/trantor/net/inner/Socket.cc (73%) create mode 100644 web_backends/drogon/trantor/net/inner/Socket.h rename core/net/connections/tcp_connection_impl.cpp => web_backends/drogon/trantor/net/inner/TcpConnectionImpl.cc (80%) create mode 100644 web_backends/drogon/trantor/net/inner/TcpConnectionImpl.h create mode 100644 web_backends/drogon/trantor/net/inner/Timer.cc create mode 100644 web_backends/drogon/trantor/net/inner/Timer.h rename core/loops/timer_queue.cpp => web_backends/drogon/trantor/net/inner/TimerQueue.cc (78%) create mode 100644 web_backends/drogon/trantor/net/inner/TimerQueue.h rename core/polling/poller/epoll_poller.cpp => web_backends/drogon/trantor/net/inner/poller/EpollPoller.cc (74%) create mode 100644 web_backends/drogon/trantor/net/inner/poller/EpollPoller.h rename core/polling/poller/kqueue.cpp => web_backends/drogon/trantor/net/inner/poller/KQueue.cc (73%) create mode 100644 web_backends/drogon/trantor/net/inner/poller/KQueue.h create mode 100644 web_backends/drogon/trantor/tests/AsyncFileLoggerTest.cc create mode 100644 web_backends/drogon/trantor/tests/AsyncFileLoggerTest1.cc create mode 100644 web_backends/drogon/trantor/tests/CMakeLists.txt create mode 100644 web_backends/drogon/trantor/tests/ConcurrentTaskQueueTest.cc create mode 100644 web_backends/drogon/trantor/tests/DelayedSSLClientTest.cc create mode 100644 web_backends/drogon/trantor/tests/DelayedSSLServerTest.cc create mode 100644 web_backends/drogon/trantor/tests/DnsTest.cc create mode 100644 web_backends/drogon/trantor/tests/KickoffTest.cc create mode 100644 web_backends/drogon/trantor/tests/LoggerTest.cc create mode 100644 web_backends/drogon/trantor/tests/RunInLoopTest1.cc create mode 100644 web_backends/drogon/trantor/tests/RunInLoopTest2.cc create mode 100644 web_backends/drogon/trantor/tests/RunOnQuitTest.cc create mode 100644 web_backends/drogon/trantor/tests/SSLClientTest.cc create mode 100644 web_backends/drogon/trantor/tests/SSLServerTest.cc create mode 100644 web_backends/drogon/trantor/tests/SendfileTest.cc create mode 100755 web_backends/drogon/trantor/tests/SerialTaskQueueTest1.cc create mode 100644 web_backends/drogon/trantor/tests/SerialTaskQueueTest2.cc create mode 100644 web_backends/drogon/trantor/tests/TcpClientTest.cc create mode 100644 web_backends/drogon/trantor/tests/TcpServerTest.cc create mode 100644 web_backends/drogon/trantor/tests/TimerTest.cc create mode 100644 web_backends/drogon/trantor/tests/TimerTest1.cc create mode 100644 web_backends/drogon/trantor/tests/TimingWheelTest.cc create mode 100644 web_backends/drogon/trantor/tests/server.pem rename {core/polling/poller => web_backends/drogon/trantor/third_party}/wepoll/LICENSE (100%) rename {core/polling/poller => web_backends/drogon/trantor/third_party}/wepoll/README.md (93%) rename {core/polling/poller => web_backends/drogon/trantor/third_party}/wepoll/Wepoll.c (100%) rename {core/polling/poller => web_backends/drogon/trantor/third_party}/wepoll/Wepoll.h (100%) create mode 100644 web_backends/drogon/trantor/unittests/CMakeLists.txt create mode 100644 web_backends/drogon/trantor/unittests/DateUnittest.cc create mode 100644 web_backends/drogon/trantor/unittests/InetAddressUnittest.cc create mode 100644 web_backends/drogon/trantor/unittests/MsgBufferUnittest.cc create mode 100644 web_backends/drogon/trantor/unittests/splitStringUnittest.cc rename core/log/async_file_logger.cpp => web_backends/drogon/trantor/utils/AsyncFileLogger.cc (75%) create mode 100644 web_backends/drogon/trantor/utils/AsyncFileLogger.h rename core/containers/concurrent_task_queue.cpp => web_backends/drogon/trantor/utils/ConcurrentTaskQueue.cc (50%) create mode 100644 web_backends/drogon/trantor/utils/ConcurrentTaskQueue.h rename core/math/date.cpp => web_backends/drogon/trantor/utils/Date.cc (79%) rename core/math/date.h => web_backends/drogon/trantor/utils/Date.h (80%) create mode 100644 web_backends/drogon/trantor/utils/Funcs.h create mode 100644 web_backends/drogon/trantor/utils/LockFreeQueue.h rename core/log/log_stream.cpp => web_backends/drogon/trantor/utils/LogStream.cc (67%) create mode 100644 web_backends/drogon/trantor/utils/LogStream.h create mode 100644 web_backends/drogon/trantor/utils/Logger.cc create mode 100644 web_backends/drogon/trantor/utils/Logger.h rename core/containers/msg_buffer.cpp => web_backends/drogon/trantor/utils/MsgBuffer.cc (72%) rename core/containers/msg_buffer.h => web_backends/drogon/trantor/utils/MsgBuffer.h (81%) create mode 100644 web_backends/drogon/trantor/utils/ObjectPool.h create mode 100644 web_backends/drogon/trantor/utils/SerialTaskQueue.cc create mode 100644 web_backends/drogon/trantor/utils/SerialTaskQueue.h create mode 100644 web_backends/drogon/trantor/utils/TaskQueue.h rename core/loops/timing_wheel.cpp => web_backends/drogon/trantor/utils/TimingWheel.cc (58%) rename core/loops/timing_wheel.h => web_backends/drogon/trantor/utils/TimingWheel.h (53%) create mode 100644 web_backends/drogon/trantor/utils/WindowsSupport.cc create mode 100644 web_backends/drogon/trantor/utils/WindowsSupport.h diff --git a/core/SCsub b/core/SCsub index bb20aab..bcd7833 100644 --- a/core/SCsub +++ b/core/SCsub @@ -6,12 +6,6 @@ env.core_sources = [] env.add_source_files(env.core_sources, "*.cpp") env.add_source_files(env.core_sources, "./math/*.cpp") -env.add_source_files(env.core_sources, "./net/*.cpp") -env.add_source_files(env.core_sources, "./net/resolvers/*.cpp") -env.add_source_files(env.core_sources, "./net/connections/*.cpp") -env.add_source_files(env.core_sources, "./loops/*.cpp") -env.add_source_files(env.core_sources, "./polling/poller/*.cpp") -env.add_source_files(env.core_sources, "./polling/*.cpp") env.add_source_files(env.core_sources, "./containers/*.cpp") env.add_source_files(env.core_sources, "./log/*.cpp") env.add_source_files(env.core_sources, "./os/*.cpp") diff --git a/core/containers/concurrent_task_queue.h b/core/containers/concurrent_task_queue.h deleted file mode 100644 index e8ed695..0000000 --- a/core/containers/concurrent_task_queue.h +++ /dev/null @@ -1,100 +0,0 @@ - -// This file is originally from Trantor - ConcurrentTaskQueue.h - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include "core/containers/task_queue.h" -#include -#include -#include -#include -#include - -/** - * @brief This class implements a task queue running in parallel. Basically this - * can be called a threads pool. - * - */ -class ConcurrentTaskQueue : public TaskQueue { -public: - ConcurrentTaskQueue() {} - - /** - * @brief Construct a new concurrent task queue instance. - * - * @param threadNum The number of threads in the queue. - * @param name The name of the queue. - */ - ConcurrentTaskQueue(size_t threadNum, const std::string &name); - - /** - * @brief Run a task in the queue. - * - * @param task - */ - virtual void runTaskInQueue(const std::function &task); - virtual void runTaskInQueue(std::function &&task); - - /** - * @brief Get the name of the queue. - * - * @return std::string - */ - virtual std::string getName() const { - return queueName_; - }; - - /** - * @brief Get the number of tasks to be executed in the queue. - * - * @return size_t - */ - size_t getTaskCount(); - - /** - * @brief Stop all threads in the queue. - * - */ - void stop(); - - ~ConcurrentTaskQueue(); - -private: - size_t queueCount_; - std::string queueName_; - - std::queue > taskQueue_; - std::vector threads_; - - std::mutex taskMutex_; - std::condition_variable taskCond_; - std::atomic_bool stop_; - void queueFunc(int queueNum); -}; diff --git a/core/containers/lock_free_queue.h b/core/containers/lock_free_queue.h deleted file mode 100644 index 0b56a42..0000000 --- a/core/containers/lock_free_queue.h +++ /dev/null @@ -1,123 +0,0 @@ - -// This file is originally from Trantor - LockFreeQueue.h - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once -#include -#include -#include -#include - -/** - * @brief This class template represents a lock-free multiple producers single - * consumer queue - * - * @tparam T The type of the items in the queue. - */ -template -class MpscQueue { -protected: - MpscQueue(const MpscQueue &) = delete; - MpscQueue &operator=(const MpscQueue &) = delete; - // some uncopyable classes maybe support move constructor.... - MpscQueue(MpscQueue &&) noexcept(true) = default; - MpscQueue &operator=(MpscQueue &&) noexcept(true) = default; - -public: - MpscQueue() : - head_(new BufferNode), tail_(head_.load(std::memory_order_relaxed)) { - } - ~MpscQueue() { - T output; - while (this->dequeue(output)) { - } - BufferNode *front = head_.load(std::memory_order_relaxed); - delete front; - } - - /** - * @brief Put a item into the queue. - * - * @param input - * @note This method can be called in multiple threads. - */ - void enqueue(T &&input) { - BufferNode *node{ new BufferNode(std::move(input)) }; - BufferNode *prevhead{ head_.exchange(node, std::memory_order_acq_rel) }; - prevhead->next_.store(node, std::memory_order_release); - } - void enqueue(const T &input) { - BufferNode *node{ new BufferNode(input) }; - BufferNode *prevhead{ head_.exchange(node, std::memory_order_acq_rel) }; - prevhead->next_.store(node, std::memory_order_release); - } - - /** - * @brief Get a item from the queue. - * - * @param output - * @return false if the queue is empty. - * @note This method must be called in a single thread. - */ - bool dequeue(T &output) { - BufferNode *tail = tail_.load(std::memory_order_relaxed); - BufferNode *next = tail->next_.load(std::memory_order_acquire); - - if (next == nullptr) { - return false; - } - output = std::move(*(next->dataPtr_)); - delete next->dataPtr_; - tail_.store(next, std::memory_order_release); - delete tail; - return true; - } - - bool empty() { - BufferNode *tail = tail_.load(std::memory_order_relaxed); - BufferNode *next = tail->next_.load(std::memory_order_acquire); - return next == nullptr; - } - -private: - struct BufferNode { - BufferNode() = default; - BufferNode(const T &data) : - dataPtr_(new T(data)) { - } - BufferNode(T &&data) : - dataPtr_(new T(std::move(data))) { - } - T *dataPtr_; - std::atomic next_{ nullptr }; - }; - - std::atomic head_; - std::atomic tail_; -}; diff --git a/core/containers/serial_task_queue.cpp b/core/containers/serial_task_queue.cpp deleted file mode 100644 index 35a3cbe..0000000 --- a/core/containers/serial_task_queue.cpp +++ /dev/null @@ -1,65 +0,0 @@ - -// This file is originally from Trantor - SerialTaskQueue.cc - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "core/log/logger.h" -#include "serial_task_queue.h" -#ifdef __linux__ -#include -#endif - - -SerialTaskQueue::SerialTaskQueue(const std::string &name) : - queueName_(name.empty() ? "SerailTaskQueue" : name), - loopThread_(queueName_) { - loopThread_.run(); -} -void SerialTaskQueue::stop() { - stop_ = true; - loopThread_.getLoop()->quit(); - loopThread_.wait(); -} -SerialTaskQueue::~SerialTaskQueue() { - if (!stop_) - stop(); - LOG_TRACE << "destruct SerialTaskQueue('" << queueName_ << "')"; -} -void SerialTaskQueue::runTaskInQueue(const std::function &task) { - loopThread_.getLoop()->runInLoop(task); -} -void SerialTaskQueue::runTaskInQueue(std::function &&task) { - loopThread_.getLoop()->runInLoop(std::move(task)); -} - -void SerialTaskQueue::waitAllTasksFinished() { - syncTaskInQueue([]() { - - }); -} - diff --git a/core/containers/serial_task_queue.h b/core/containers/serial_task_queue.h deleted file mode 100644 index 953257d..0000000 --- a/core/containers/serial_task_queue.h +++ /dev/null @@ -1,114 +0,0 @@ - -// This file is originally from Trantor - SerialTaskQueue.h - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include "task_queue.h" -#include "core/loops/event_loop_thread.h" -#include -#include -#include -#include - - -/** - * @brief This class represents a task queue in which all tasks are executed one - * by one. - * - */ -class SerialTaskQueue : public TaskQueue -{ - public: - /** - * @brief Run a task in the queue. - * - * @param task - */ - virtual void runTaskInQueue(const std::function &task); - virtual void runTaskInQueue(std::function &&task); - - /** - * @brief Get the name of the queue. - * - * @return std::string - */ - virtual std::string getName() const - { - return queueName_; - }; - - /** - * @brief Wait until all tasks in the queue are finished. - * - */ - void waitAllTasksFinished(); - - SerialTaskQueue() = delete; - - /** - * @brief Construct a new serail task queue instance. - * - * @param name - */ - explicit SerialTaskQueue(const std::string &name); - - virtual ~SerialTaskQueue(); - - /** - * @brief Check whether a task is running in the queue. - * - * @return true - * @return false - */ - bool isRuningTask() - { - return loopThread_.getLoop() - ? loopThread_.getLoop()->isCallingFunctions() - : false; - } - - /** - * @brief Get the number of tasks in the queue. - * - * @return size_t - */ - size_t getTaskCount(); - - /** - * @brief Stop the queue. - * - */ - void stop(); - - protected: - std::string queueName_; - EventLoopThread loopThread_; - bool stop_{false}; -}; diff --git a/core/containers/task_queue.h b/core/containers/task_queue.h deleted file mode 100644 index 57e412b..0000000 --- a/core/containers/task_queue.h +++ /dev/null @@ -1,76 +0,0 @@ - -// This file is originally from Trantor - TaskQueue.h - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include -#include -#include - -/** - * @brief This class is a pure virtual class that can be implemented as a - * SerialTaskQueue or a ConcurrentTaskQueue. - * - */ -class TaskQueue { -protected: - TaskQueue(const TaskQueue &) = delete; - TaskQueue &operator=(const TaskQueue &) = delete; - // some uncopyable classes maybe support move constructor.... - TaskQueue(TaskQueue &&) noexcept(true) = default; - TaskQueue &operator=(TaskQueue &&) noexcept(true) = default; - -public: - TaskQueue() {} - virtual void runTaskInQueue(const std::function &task) = 0; - virtual void runTaskInQueue(std::function &&task) = 0; - virtual std::string getName() const { - return ""; - }; - - /** - * @brief Run a task in the queue sychronously. This means that the task is - * executed before the method returns. - * - * @param task - */ - void syncTaskInQueue(const std::function &task) { - std::promise prom; - std::future fut = prom.get_future(); - runTaskInQueue([&]() { - task(); - prom.set_value(1); - }); - fut.get(); - }; - virtual ~TaskQueue() { - } -}; - diff --git a/core/log/async_file_logger.h b/core/log/async_file_logger.h deleted file mode 100644 index 0630ddd..0000000 --- a/core/log/async_file_logger.h +++ /dev/null @@ -1,160 +0,0 @@ - -// This file is originally from Trantor - AsyncFileLogger.h - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include "core/math/date.h" -#include -#include -#include -#include -#include -#include -#include - -using StringPtr = std::shared_ptr; -using StringPtrQueue = std::queue; - -/** - * @brief This class implements utility functions for writing logs to files - * asynchronously. - * - */ -class AsyncFileLogger { -protected: - AsyncFileLogger(const AsyncFileLogger &) = delete; - AsyncFileLogger &operator=(const AsyncFileLogger &) = delete; - // some uncopyable classes maybe support move constructor.... - AsyncFileLogger(AsyncFileLogger &&) noexcept(true) = default; - AsyncFileLogger &operator=(AsyncFileLogger &&) noexcept(true) = default; - -public: - /** - * @brief Write the message to the log file. - * - * @param msg - * @param len - */ - void output(const char *msg, const uint64_t len); - - /** - * @brief Flush data from memory buffer to the log file. - * - */ - void flush(); - - /** - * @brief Start writing log files. - * - */ - void startLogging(); - - /** - * @brief Set the size limit of log files. When the log file size reaches - * the limit, the log file is switched. - * - * @param limit - */ - void setFileSizeLimit(uint64_t limit) { - sizeLimit_ = limit; - } - - /** - * @brief Set the log file name. - * - * @param baseName The base name of the log file. - * @param extName The extended name of the log file. - * @param path The location where the log file is stored. - */ - void setFileName(const std::string &baseName, - const std::string &extName = ".log", - const std::string &path = "./") { - fileBaseName_ = baseName; - extName[0] == '.' ? fileExtName_ = extName : fileExtName_ = std::string(".") + extName; - filePath_ = path; - if (filePath_.length() == 0) - filePath_ = "./"; - if (filePath_[filePath_.length() - 1] != '/') - filePath_ = filePath_ + "/"; - } - ~AsyncFileLogger(); - AsyncFileLogger(); - -protected: - std::mutex mutex_; - std::condition_variable cond_; - StringPtr logBufferPtr_; - StringPtr nextBufferPtr_; - StringPtrQueue writeBuffers_; - StringPtrQueue tmpBuffers_; - void writeLogToFile(const StringPtr buf); - std::unique_ptr threadPtr_; - bool stopFlag_{ false }; - void logThreadFunc(); - std::string filePath_{ "./" }; - std::string fileBaseName_{ "trantor" }; - std::string fileExtName_{ ".log" }; - uint64_t sizeLimit_{ 20 * 1024 * 1024 }; - - class LoggerFile { - protected: - LoggerFile(const LoggerFile &) = delete; - LoggerFile &operator=(const LoggerFile &) = delete; - // some uncopyable classes maybe support move constructor.... - LoggerFile(LoggerFile &&) noexcept(true) = default; - LoggerFile &operator=(LoggerFile &&) noexcept(true) = default; - - public: - LoggerFile(const std::string &filePath, - const std::string &fileBaseName, - const std::string &fileExtName); - ~LoggerFile(); - void writeLog(const StringPtr buf); - uint64_t getLength(); - explicit operator bool() const { - return fp_ != nullptr; - } - void flush(); - - protected: - FILE *fp_{ nullptr }; - Date creationDate_; - std::string fileFullName_; - std::string filePath_; - std::string fileBaseName_; - std::string fileExtName_; - static uint64_t fileSeq_; - }; - - std::unique_ptr loggerFilePtr_; - - uint64_t lostCounter_{ 0 }; - void swapBuffer(); -}; diff --git a/core/log/log_stream.h b/core/log/log_stream.h deleted file mode 100644 index 60e67de..0000000 --- a/core/log/log_stream.h +++ /dev/null @@ -1,261 +0,0 @@ - -// This file is originally from Moduo -> Trantor - LogStream.h - -// Copyright (c) 2016-2021, Tao An. All rights reserved. -// Copyright (c) 2010, Shuo Chen. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -// Taken from muduo lib and modified. Classes in this file are used internally. -#include -#include // memcpy -#include - -namespace detail { -static constexpr size_t kSmallBuffer{ 4000 }; -static constexpr size_t kLargeBuffer{ 4000 * 1000 }; - -template -class FixedBuffer { -protected: - FixedBuffer(const FixedBuffer &) = delete; - FixedBuffer &operator=(const FixedBuffer &) = delete; - // some uncopyable classes maybe support move constructor.... - FixedBuffer(FixedBuffer &&) noexcept(true) = default; - FixedBuffer &operator=(FixedBuffer &&) noexcept(true) = default; - -public: - FixedBuffer() : - cur_(data_) { - setCookie(cookieStart); - } - - ~FixedBuffer() { - setCookie(cookieEnd); - } - - bool append(const char * /*restrict*/ buf, size_t len) { - if ((size_t)(avail()) > len) { - memcpy(cur_, buf, len); - cur_ += len; - return true; - } - return false; - } - - const char *data() const { - return data_; - } - int length() const { - return static_cast(cur_ - data_); - } - - // write to data_ directly - char *current() { - return cur_; - } - int avail() const { - return static_cast(end() - cur_); - } - void add(size_t len) { - cur_ += len; - } - - void reset() { - cur_ = data_; - } - void zeroBuffer() { - memset(data_, 0, sizeof(data_)); - } - - // for used by GDB - const char *debugString(); - void setCookie(void (*cookie)()) { - cookie_ = cookie; - } - // for used by unit test - std::string toString() const { - return std::string(data_, length()); - } - // StringPiece toStringPiece() const { return StringPiece(data_, length()); - // } - -private: - const char *end() const { - return data_ + sizeof data_; - } - // Must be outline function for cookies. - static void cookieStart(); - static void cookieEnd(); - - void (*cookie_)(); - char data_[SIZE]; - char *cur_; -}; - -} // namespace detail - -class LogStream { - using self = LogStream; - -protected: - LogStream(const LogStream &) = delete; - LogStream &operator=(const LogStream &) = delete; - // some uncopyable classes maybe support move constructor.... - LogStream(LogStream &&) noexcept(true) = default; - LogStream &operator=(LogStream &&) noexcept(true) = default; - -public: - using Buffer = detail::FixedBuffer; - - self &operator<<(bool v) { - append(v ? "1" : "0", 1); - return *this; - } - - self &operator<<(short); - self &operator<<(unsigned short); - self &operator<<(int); - self &operator<<(unsigned int); - self &operator<<(long); - self &operator<<(unsigned long); - self &operator<<(const long long &); - self &operator<<(const unsigned long long &); - - self &operator<<(const void *); - - self &operator<<(float &v) { - *this << static_cast(v); - return *this; - } - self &operator<<(const double &); - self &operator<<(const long double &v); - - self &operator<<(char v) { - append(&v, 1); - return *this; - } - - // self& operator<<(signed char); - // self& operator<<(unsigned char); - template - self &operator<<(const char (&buf)[N]) { - assert(strnlen(buf, N) == N - 1); - append(buf, N - 1); - return *this; - } - - self &operator<<(char *str) { - if (str) { - append(str, strlen(str)); - } else { - append("(null)", 6); - } - return *this; - } - - self &operator<<(const char *str) { - if (str) { - append(str, strlen(str)); - } else { - append("(null)", 6); - } - return *this; - } - - self &operator<<(const unsigned char *str) { - return operator<<(reinterpret_cast(str)); - } - - self &operator<<(const std::string &v) { - append(v.c_str(), v.size()); - return *this; - } - - void append(const char *data, size_t len) { - if (exBuffer_.empty()) { - if (!buffer_.append(data, len)) { - exBuffer_.append(buffer_.data(), buffer_.length()); - exBuffer_.append(data, len); - } - } else { - exBuffer_.append(data, len); - } - } - // const Buffer& buffer() const { return buffer_; } - const char *bufferData() const { - if (!exBuffer_.empty()) { - return exBuffer_.data(); - } - return buffer_.data(); - } - - size_t bufferLength() const { - if (!exBuffer_.empty()) { - return exBuffer_.length(); - } - return buffer_.length(); - } - void resetBuffer() { - buffer_.reset(); - exBuffer_.clear(); - } - - LogStream() {} - -private: - template - void formatInteger(T); - - Buffer buffer_; - std::string exBuffer_; -}; - -class Fmt // : boost::noncopyable -{ -public: - template - Fmt(const char *fmt, T val); - - const char *data() const { - return buf_; - } - int length() const { - return length_; - } - -private: - char buf_[48]; - int length_; -}; - -inline LogStream &operator<<(LogStream &s, const Fmt &fmt) { - s.append(fmt.data(), fmt.length()); - return s; -} - diff --git a/core/log/logger.cpp b/core/log/logger.cpp index 92ed214..ce679a5 100644 --- a/core/log/logger.cpp +++ b/core/log/logger.cpp @@ -1,34 +1,4 @@ -// This file contains code from Trantor - Logger.cc - -// Copyright (c) 2022 Péter Magyar -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - #include "logger.h" #include "core/string.h" @@ -37,15 +7,6 @@ #include #include "logger.h" #include -#ifndef _WIN32 -#include -#include -#else -#include -#endif -#ifdef __FreeBSD__ -#include -#endif void RLogger::log_trace(const String &str) { log_trace(str.data()); @@ -87,161 +48,3 @@ void RLogger::_log_msg_error(const char *p_function, const char *p_file, int p_l void RLogger::_log_index_error(const char *p_function, const char *p_file, int p_line, const int index, const int size, const char *str) { printf("!INDEX ERROR: (%s) %s:%d :: index: %d/%d. %s\n", p_file, p_function, p_line, index, size, str); } - -// helper class for known string length at compile time -class T { -public: - T(const char *str, unsigned len) : - str_(str), len_(len) { - assert(strlen(str) == len_); - } - - const char *str_; - const unsigned len_; -}; - -const char *strerror_tl(int savedErrno) { -#ifndef _MSC_VER - return strerror(savedErrno); -#else - static thread_local char errMsg[64]; - (void)strerror_s(errMsg, savedErrno); - return errMsg; -#endif -} - -inline LogStream &operator<<(LogStream &s, T v) { - s.append(v.str_, v.len_); - return s; -} - -inline LogStream &operator<<(LogStream &s, const Logger::SourceFile &v) { - s.append(v.data_, v.size_); - return s; -} - -static thread_local uint64_t lastSecond_{ 0 }; -static thread_local char lastTimeString_[32] = { 0 }; -#ifdef __linux__ -static thread_local pid_t threadId_{ 0 }; -#else -static thread_local uint64_t threadId_{ 0 }; -#endif -// static thread_local LogStream logStream_; - -void Logger::formatTime() { - uint64_t now = static_cast(date_.secondsSinceEpoch()); - uint64_t microSec = - static_cast(date_.microSecondsSinceEpoch() - - date_.roundSecond().microSecondsSinceEpoch()); - if (now != lastSecond_) { - lastSecond_ = now; -#ifndef _MSC_VER - strncpy(lastTimeString_, - date_.toFormattedString(false).c_str(), - sizeof(lastTimeString_) - 1); -#else - strncpy_s( - lastTimeString_, - date_.toFormattedString(false).c_str(), - sizeof(lastTimeString_) - 1); -#endif - } - logStream_ << T(lastTimeString_, 17); - char tmp[32]; - snprintf(tmp, - sizeof(tmp), - ".%06llu UTC ", - static_cast(microSec)); - logStream_ << T(tmp, 12); -#ifdef __linux__ - if (threadId_ == 0) - threadId_ = static_cast(::syscall(SYS_gettid)); -#elif defined __FreeBSD__ - if (threadId_ == 0) { - threadId_ = pthread_getthreadid_np(); - } -#elif defined __OpenBSD__ - if (threadId_ == 0) { - threadId_ = getthrid(); - } -#elif defined _WIN32 - if (threadId_ == 0) { - std::stringstream ss; - ss << std::this_thread::get_id(); - threadId_ = std::stoull(ss.str()); - } -#else - if (threadId_ == 0) { - pthread_threadid_np(NULL, &threadId_); - } -#endif - logStream_ << threadId_; -} -static const char *logLevelStr[Logger::LogLevel::kNumberOfLogLevels] = { - " TRACE ", - " DEBUG ", - " INFO ", - " WARN ", - " ERROR ", - " FATAL ", -}; -Logger::Logger(SourceFile file, int line) : - sourceFile_(file), fileLine_(line), level_(kInfo) { - formatTime(); - logStream_ << T(logLevelStr[level_], 7); -} -Logger::Logger(SourceFile file, int line, LogLevel level) : - sourceFile_(file), fileLine_(line), level_(level) { - formatTime(); - logStream_ << T(logLevelStr[level_], 7); -} -Logger::Logger(SourceFile file, int line, LogLevel level, const char *func) : - sourceFile_(file), fileLine_(line), level_(level) { - formatTime(); - logStream_ << T(logLevelStr[level_], 7) << "[" << func << "] "; -} -Logger::Logger(SourceFile file, int line, bool) : - sourceFile_(file), fileLine_(line), level_(kFatal) { - formatTime(); - logStream_ << T(logLevelStr[level_], 7); - if (errno != 0) { - logStream_ << strerror_tl(errno) << " (errno=" << errno << ") "; - } -} -RawLogger::~RawLogger() { - if (index_ < 0) { - auto &oFunc = Logger::outputFunc_(); - if (!oFunc) - return; - oFunc(logStream_.bufferData(), logStream_.bufferLength()); - } else { - auto &oFunc = Logger::outputFunc_(index_); - if (!oFunc) - return; - oFunc(logStream_.bufferData(), logStream_.bufferLength()); - } -} -Logger::~Logger() { - logStream_ << T(" - ", 3) << sourceFile_ << ':' << fileLine_ << '\n'; - if (index_ < 0) { - auto &oFunc = Logger::outputFunc_(); - if (!oFunc) - return; - oFunc(logStream_.bufferData(), logStream_.bufferLength()); - if (level_ >= kError) - Logger::flushFunc_()(); - } else { - auto &oFunc = Logger::outputFunc_(index_); - if (!oFunc) - return; - oFunc(logStream_.bufferData(), logStream_.bufferLength()); - if (level_ >= kError) - Logger::flushFunc_(index_)(); - } - - // logStream_.resetBuffer(); -} -LogStream &Logger::stream() { - return logStream_; -} diff --git a/core/log/logger.h b/core/log/logger.h index 13ca6b8..f05c06a 100644 --- a/core/log/logger.h +++ b/core/log/logger.h @@ -1,39 +1,7 @@ -// This file contains code from Trantor - Logger.h - -// Copyright (c) 2022 Péter Magyar -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - #ifndef LOGGER_H #define LOGGER_H -#include "core/math/date.h" -#include "log_stream.h" #include #include #include @@ -61,352 +29,4 @@ public: static void _log_index_error(const char *p_function, const char *p_file, int p_line, const int index, const int size, const char *str); }; -/** - * @brief This class implements log functions. - * - */ -class Logger { -protected: - Logger(const Logger &) = delete; - Logger &operator=(const Logger &) = delete; - // some uncopyable classes maybe support move constructor.... - Logger(Logger &&) noexcept(true) = default; - Logger &operator=(Logger &&) noexcept(true) = default; - -public: - enum LogLevel { - kTrace = 0, - kDebug, - kInfo, - kWarn, - kError, - kFatal, - kNumberOfLogLevels - }; - - /** - * @brief Calculate of basename of source files in compile time. - * - */ - class SourceFile { - public: - template - inline SourceFile(const char (&arr)[N]) : - data_(arr), size_(N - 1) { - // std::cout<(data_ - arr); - } - } - - explicit SourceFile(const char *filename) : - data_(filename) { - const char *slash = strrchr(filename, '/'); - if (slash) { - data_ = slash + 1; - } - size_ = static_cast(strlen(data_)); - } - - const char *data_; - int size_; - }; - Logger(SourceFile file, int line); - Logger(SourceFile file, int line, LogLevel level); - Logger(SourceFile file, int line, bool isSysErr); - Logger(SourceFile file, int line, LogLevel level, const char *func); - ~Logger(); - Logger &setIndex(int index) { - index_ = index; - return *this; - } - LogStream &stream(); - - /** - * @brief Set the output function. - * - * @param outputFunc The function to output a log message. - * @param flushFunc The function to flush. - * @note Logs are output to the standard output by default. - */ - static void setOutputFunction( - std::function outputFunc, - std::function flushFunc, - int index = -1) { - if (index < 0) { - outputFunc_() = outputFunc; - flushFunc_() = flushFunc; - } else { - outputFunc_(index) = outputFunc; - flushFunc_(index) = flushFunc; - } - } - - /** - * @brief Set the log level. Logs below the level are not printed. - * - * @param level - */ - static void setLogLevel(LogLevel level) { - logLevel_() = level; - } - - /** - * @brief Get the current log level. - * - * @return LogLevel - */ - static LogLevel logLevel() { - return logLevel_(); - } - -protected: - static void defaultOutputFunction(const char *msg, const uint64_t len) { - fwrite(msg, 1, len, stdout); - } - static void defaultFlushFunction() { - fflush(stdout); - } - void formatTime(); - static LogLevel &logLevel_() { -#ifdef RELEASE - static LogLevel logLevel = LogLevel::kInfo; -#else - static LogLevel logLevel = LogLevel::kDebug; -#endif - return logLevel; - } - static std::function - &outputFunc_() { - static std::function - outputFunc = Logger::defaultOutputFunction; - return outputFunc; - } - static std::function &flushFunc_() { - static std::function flushFunc = Logger::defaultFlushFunction; - return flushFunc; - } - static std::function - &outputFunc_(size_t index) { - static std::vector< - std::function > - outputFuncs; - if (index < outputFuncs.size()) { - return outputFuncs[index]; - } - while (index >= outputFuncs.size()) { - outputFuncs.emplace_back(outputFunc_()); - } - return outputFuncs[index]; - } - static std::function &flushFunc_(size_t index) { - static std::vector > flushFuncs; - if (index < flushFuncs.size()) { - return flushFuncs[index]; - } - while (index >= flushFuncs.size()) { - flushFuncs.emplace_back(flushFunc_()); - } - return flushFuncs[index]; - } - friend class RawLogger; - LogStream logStream_; - Date date_{ Date::now() }; - SourceFile sourceFile_; - int fileLine_; - LogLevel level_; - int index_{ -1 }; -}; - -class RawLogger { -protected: - RawLogger(const RawLogger &) = delete; - RawLogger &operator=(const RawLogger &) = delete; - // some uncopyable classes maybe support move constructor.... - RawLogger(RawLogger &&) noexcept(true) = default; - RawLogger &operator=(RawLogger &&) noexcept(true) = default; - -public: - RawLogger() {} - ~RawLogger(); - RawLogger &setIndex(int index) { - index_ = index; - return *this; - } - LogStream &stream() { - return logStream_; - } - -private: - LogStream logStream_; - int index_{ -1 }; -}; - - -#ifdef NDEBUG -#define LOG_TRACE \ - if (0) \ - Logger(__FILE__, __LINE__, Logger::kTrace, __func__) \ - .stream() -#else -#define LOG_TRACE \ - if (Logger::logLevel() <= Logger::kTrace) \ - Logger(__FILE__, __LINE__, Logger::kTrace, __func__) \ - .stream() -#define LOG_TRACE_TO(index) \ - if (Logger::logLevel() <= Logger::kTrace) \ - Logger(__FILE__, __LINE__, Logger::kTrace, __func__) \ - .setIndex(index) \ - .stream() - -#endif - -#define LOG_DEBUG \ - if (Logger::logLevel() <= Logger::kDebug) \ - Logger(__FILE__, __LINE__, Logger::kDebug, __func__) \ - .stream() -#define LOG_DEBUG_TO(index) \ - if (Logger::logLevel() <= Logger::kDebug) \ - Logger(__FILE__, __LINE__, Logger::kDebug, __func__) \ - .setIndex(index) \ - .stream() -#define LOG_INFO \ - if (Logger::logLevel() <= Logger::kInfo) \ - Logger(__FILE__, __LINE__).stream() -#define LOG_INFO_TO(index) \ - if (Logger::logLevel() <= Logger::kInfo) \ - Logger(__FILE__, __LINE__).setIndex(index).stream() -#define LOG_WARN \ - Logger(__FILE__, __LINE__, Logger::kWarn).stream() -#define LOG_WARN_TO(index) \ - Logger(__FILE__, __LINE__, Logger::kWarn) \ - .setIndex(index) \ - .stream() -#define LOG_ERROR \ - Logger(__FILE__, __LINE__, Logger::kError).stream() -#define LOG_ERROR_TO(index) \ - Logger(__FILE__, __LINE__, Logger::kError) \ - .setIndex(index) \ - .stream() -#define LOG_FATAL \ - Logger(__FILE__, __LINE__, Logger::kFatal).stream() -#define LOG_FATAL_TO(index) \ - Logger(__FILE__, __LINE__, Logger::kFatal) \ - .setIndex(index) \ - .stream() -#define LOG_SYSERR Logger(__FILE__, __LINE__, true).stream() -#define LOG_SYSERR_TO(index) \ - Logger(__FILE__, __LINE__, true).setIndex(index).stream() - -#define LOG_RAW RawLogger().stream() -#define LOG_RAW_TO(index) RawLogger().setIndex(index).stream() - -#define LOG_TRACE_IF(cond) \ - if ((Logger::logLevel() <= Logger::kTrace) && (cond)) \ - Logger(__FILE__, __LINE__, Logger::kTrace, __func__) \ - .stream() -#define LOG_DEBUG_IF(cond) \ - if ((Tensor::Logger::logLevel() <= Tensor::Logger::kDebug) && (cond)) \ - Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kDebug, __func__) \ - .stream() -#define LOG_INFO_IF(cond) \ - if ((Tensor::Logger::logLevel() <= Tensor::Logger::kInfo) && (cond)) \ - Tensor::Logger(__FILE__, __LINE__).stream() -#define LOG_WARN_IF(cond) \ - if (cond) \ - Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kWarn).stream() -#define LOG_ERROR_IF(cond) \ - if (cond) \ - Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kError).stream() -#define LOG_FATAL_IF(cond) \ - if (cond) \ - Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kFatal).stream() - -#ifdef NDEBUG -#define DLOG_TRACE \ - if (0) \ - Logger(__FILE__, __LINE__, Logger::kTrace, __func__) \ - .stream() -#define DLOG_DEBUG \ - if (0) \ - Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kDebug, __func__) \ - .stream() -#define DLOG_INFO \ - if (0) \ - Tensor::Logger(__FILE__, __LINE__).stream() -#define DLOG_WARN \ - if (0) \ - Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kWarn).stream() -#define DLOG_ERROR \ - if (0) \ - Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kError).stream() -#define DLOG_FATAL \ - if (0) \ - Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kFatal).stream() - -#define DLOG_TRACE_IF(cond) \ - if (0) \ - Logger(__FILE__, __LINE__, Logger::kTrace, __func__) \ - .stream() -#define DLOG_DEBUG_IF(cond) \ - if (0) \ - Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kDebug, __func__) \ - .stream() -#define DLOG_INFO_IF(cond) \ - if (0) \ - Tensor::Logger(__FILE__, __LINE__).stream() -#define DLOG_WARN_IF(cond) \ - if (0) \ - Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kWarn).stream() -#define DLOG_ERROR_IF(cond) \ - if (0) \ - Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kError).stream() -#define DLOG_FATAL_IF(cond) \ - if (0) \ - Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kFatal).stream() -#else -#define DLOG_TRACE \ - if (Logger::logLevel() <= Logger::kTrace) \ - Logger(__FILE__, __LINE__, Logger::kTrace, __func__) \ - .stream() -#define DLOG_DEBUG \ - if (Tensor::Logger::logLevel() <= Tensor::Logger::kDebug) \ - Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kDebug, __func__) \ - .stream() -#define DLOG_INFO \ - if (Tensor::Logger::logLevel() <= Tensor::Logger::kInfo) \ - Tensor::Logger(__FILE__, __LINE__).stream() -#define DLOG_WARN \ - Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kWarn).stream() -#define DLOG_ERROR \ - Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kError).stream() -#define DLOG_FATAL \ - Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kFatal).stream() - -#define DLOG_TRACE_IF(cond) \ - if ((Logger::logLevel() <= Logger::kTrace) && (cond)) \ - Logger(__FILE__, __LINE__, Logger::kTrace, __func__) \ - .stream() -#define DLOG_DEBUG_IF(cond) \ - if ((Tensor::Logger::logLevel() <= Tensor::Logger::kDebug) && (cond)) \ - Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kDebug, __func__) \ - .stream() -#define DLOG_INFO_IF(cond) \ - if ((Tensor::Logger::logLevel() <= Tensor::Logger::kInfo) && (cond)) \ - Tensor::Logger(__FILE__, __LINE__).stream() -#define DLOG_WARN_IF(cond) \ - if (cond) \ - Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kWarn).stream() -#define DLOG_ERROR_IF(cond) \ - if (cond) \ - Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kError).stream() -#define DLOG_FATAL_IF(cond) \ - if (cond) \ - Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kFatal).stream() -#endif - -const char *strerror_tl(int savedErrno); - #endif diff --git a/core/loops/event_loop.h b/core/loops/event_loop.h deleted file mode 100644 index 5d6d779..0000000 --- a/core/loops/event_loop.h +++ /dev/null @@ -1,324 +0,0 @@ - -// This file is originally from Moduo -> Trantor - EventLoop.h - -// Copyright (c) 2016-2021, Tao An. All rights reserved. -// Copyright (c) 2010, Shuo Chen. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include "core/containers/lock_free_queue.h" -#include "core/math/date.h" -#include -#include -#include -#include -#include -#include -#include -#include - -class Poller; -class TimerQueue; -class Channel; -using ChannelList = std::vector; -using Func = std::function; -using TimerId = uint64_t; -enum { - InvalidTimerId = 0 -}; - -/** - * @brief As the name implies, this class represents an event loop that runs in - * a perticular thread. The event loop can handle network I/O events and timers - * in asynchronous mode. - * @note An event loop object always belongs to a separate thread, and there is - * one event loop object at most in a thread. We can call an event loop object - * the event loop of the thread it belongs to, or call that thread the thread of - * the event loop. - */ -class EventLoop { -protected: - EventLoop(const EventLoop &) = delete; - EventLoop &operator=(const EventLoop &) = delete; - // some uncopyable classes maybe support move constructor.... - EventLoop(EventLoop &&) noexcept(true) = default; - EventLoop &operator=(EventLoop &&) noexcept(true) = default; - -public: - EventLoop(); - ~EventLoop(); - - /** - * @brief Run the event loop. This method will be blocked until the event - * loop exits. - * - */ - void loop(); - - /** - * @brief Let the event loop quit. - * - */ - void quit(); - - /** - * @brief Assertion that the current thread is the thread to which the event - * loop belongs. If the assertion fails, the program aborts. - */ - void assertInLoopThread() { - if (!isInLoopThread()) { - abortNotInLoopThread(); - } - }; -#ifdef __linux__ - /** - * @brief Make the timer queue works after calling the fork() function. - * - */ - void resetTimerQueue(); -#endif - /** - * @brief Make the event loop works after calling the fork() function. - * - */ - void resetAfterFork(); - - /** - * @brief Return true if the current thread is the thread to which the event - * loop belongs. - * - * @return true - * @return false - */ - bool isInLoopThread() const { - return threadId_ == std::this_thread::get_id(); - }; - - /** - * @brief Get the event loop of the current thread. Return nullptr if there - * is no event loop in the current thread. - * - * @return EventLoop* - */ - static EventLoop *getEventLoopOfCurrentThread(); - - /** - * @brief Run the function f in the thread of the event loop. - * - * @param f - * @note If the current thread is the thread of the event loop, the function - * f is executed directly before the method exiting. - */ - void runInLoop(const Func &f); - void runInLoop(Func &&f); - - /** - * @brief Run the function f in the thread of the event loop. - * - * @param f - * @note The difference between this method and the runInLoop() method is - * that the function f is executed after the method exiting no matter if the - * current thread is the thread of the event loop. - */ - void queueInLoop(const Func &f); - void queueInLoop(Func &&f); - - /** - * @brief Run a function at a time point. - * - * @param time The time to run the function. - * @param cb The function to run. - * @return TimerId The ID of the timer. - */ - TimerId runAt(const Date &time, const Func &cb); - TimerId runAt(const Date &time, Func &&cb); - - /** - * @brief Run a function after a period of time. - * - * @param delay Represent the period of time in seconds. - * @param cb The function to run. - * @return TimerId The ID of the timer. - */ - TimerId runAfter(double delay, const Func &cb); - TimerId runAfter(double delay, Func &&cb); - - /** - * @brief Run a function after a period of time. - * @note Users could use chrono literals to represent a time duration - * For example: - * @code - runAfter(5s, task); - runAfter(10min, task); - @endcode - */ - TimerId runAfter(const std::chrono::duration &delay, const Func &cb) { - return runAfter(delay.count(), cb); - } - TimerId runAfter(const std::chrono::duration &delay, Func &&cb) { - return runAfter(delay.count(), std::move(cb)); - } - - /** - * @brief Repeatedly run a function every period of time. - * - * @param interval The duration in seconds. - * @param cb The function to run. - * @return TimerId The ID of the timer. - */ - TimerId runEvery(double interval, const Func &cb); - TimerId runEvery(double interval, Func &&cb); - - /** - * @brief Repeatedly run a function every period of time. - * Users could use chrono literals to represent a time duration - * For example: - * @code - runEvery(5s, task); - runEvery(10min, task); - runEvery(0.1h, task); - @endcode - */ - TimerId runEvery(const std::chrono::duration &interval, - const Func &cb) { - return runEvery(interval.count(), cb); - } - TimerId runEvery(const std::chrono::duration &interval, Func &&cb) { - return runEvery(interval.count(), std::move(cb)); - } - - /** - * @brief Invalidate the timer identified by the given ID. - * - * @param id The ID of the timer. - */ - void invalidateTimer(TimerId id); - - /** - * @brief Move the EventLoop to the current thread, this method must be - * called before the loop is running. - * - */ - void moveToCurrentThread(); - - /** - * @brief Update channel status. This method is usually used internally. - * - * @param chl - */ - void updateChannel(Channel *chl); - - /** - * @brief Remove a channel from the event loop. This method is usually used - * internally. - * - * @param chl - */ - void removeChannel(Channel *chl); - - /** - * @brief Return the index of the event loop. - * - * @return size_t - */ - size_t index() { - return index_; - } - - /** - * @brief Set the index of the event loop. - * - * @param index - */ - void setIndex(size_t index) { - index_ = index; - } - - /** - * @brief Return true if the event loop is running. - * - * @return true - * @return false - */ - bool isRunning() { - return looping_ && (!quit_); - } - - /** - * @brief Check if the event loop is calling a function. - * - * @return true - * @return false - */ - bool isCallingFunctions() { - return callingFuncs_; - } - - /** - * @brief Run functions when the event loop quits - * - * @param cb the function to run - * @note the function runs on the thread that quits the EventLoop - */ - void runOnQuit(Func &&cb); - void runOnQuit(const Func &cb); - -private: - void abortNotInLoopThread(); - void wakeup(); - void wakeupRead(); - bool looping_; - std::thread::id threadId_; - bool quit_; - std::unique_ptr poller_; - - ChannelList activeChannels_; - Channel *currentActiveChannel_; - - bool eventHandling_; - MpscQueue funcs_; - std::unique_ptr timerQueue_; - MpscQueue funcsOnQuit_; - bool callingFuncs_{ false }; -#ifdef __linux__ - int wakeupFd_; - std::unique_ptr wakeupChannelPtr_; -#elif defined _WIN32 -#else - int wakeupFd_[2]; - std::unique_ptr wakeupChannelPtr_; -#endif - - void doRunInLoopFuncs(); -#ifdef _WIN32 - size_t index_{ size_t(-1) }; -#else - size_t index_{ std::numeric_limits::max() }; -#endif - EventLoop **threadLocalLoopPtr_; -}; diff --git a/core/loops/event_loop_thread.cpp b/core/loops/event_loop_thread.cpp deleted file mode 100644 index a39f5a5..0000000 --- a/core/loops/event_loop_thread.cpp +++ /dev/null @@ -1,80 +0,0 @@ - -// This file is originally from Trantor - EventLoopThread.cc - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "event_loop_thread.h" -#include "core/log/logger.h" -#ifdef __linux__ -#include -#endif - -EventLoopThread::EventLoopThread(const std::string &threadName) : - loop_(nullptr), - loopThreadName_(threadName), - thread_([this]() { loopFuncs(); }) { - auto f = promiseForLoopPointer_.get_future(); - loop_ = f.get(); -} -EventLoopThread::~EventLoopThread() { - run(); - if (loop_) { - loop_->quit(); - } - if (thread_.joinable()) { - thread_.join(); - } -} -// void EventLoopThread::stop() { -// if(loop_) -// loop_->quit(); -//} -void EventLoopThread::wait() { - thread_.join(); -} -void EventLoopThread::loopFuncs() { -#ifdef __linux__ - ::prctl(PR_SET_NAME, loopThreadName_.c_str()); -#endif - EventLoop loop; - loop.queueInLoop([this]() { promiseForLoop_.set_value(1); }); - promiseForLoopPointer_.set_value(&loop); - auto f = promiseForRun_.get_future(); - (void)f.get(); - loop.loop(); - // LOG_DEBUG << "loop out"; - loop_ = NULL; -} -void EventLoopThread::run() { - std::call_once(once_, [this]() { - auto f = promiseForLoop_.get_future(); - promiseForRun_.set_value(1); - // Make sure the event loop loops before returning. - (void)f.get(); - }); -} diff --git a/core/loops/event_loop_thread.h b/core/loops/event_loop_thread.h deleted file mode 100644 index 5a04a90..0000000 --- a/core/loops/event_loop_thread.h +++ /dev/null @@ -1,87 +0,0 @@ - -// This file is originally from Trantor - EventLoopThread.h - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include "event_loop.h" -#include -#include -#include -#include -#include - -/** - * @brief This class represents an event loop thread. - * - */ -class EventLoopThread { -protected: - EventLoopThread(const EventLoopThread &) = delete; - EventLoopThread &operator=(const EventLoopThread &) = delete; - // some uncopyable classes maybe support move constructor.... - EventLoopThread(EventLoopThread &&) noexcept(true) = default; - EventLoopThread &operator=(EventLoopThread &&) noexcept(true) = default; - -public: - explicit EventLoopThread(const std::string &threadName = "EventLoopThread"); - ~EventLoopThread(); - - /** - * @brief Wait for the event loop to exit. - * @note This method blocks the current thread until the event loop exits. - */ - void wait(); - - /** - * @brief Get the pointer of the event loop of the thread. - * - * @return EventLoop* - */ - EventLoop *getLoop() const { - return loop_; - } - - /** - * @brief Run the event loop of the thread. This method doesn't block the - * current thread. - * - */ - void run(); - -private: - EventLoop *loop_; - std::string loopThreadName_; - void loopFuncs(); - std::promise promiseForLoopPointer_; - std::promise promiseForRun_; - std::promise promiseForLoop_; - std::once_flag once_; - std::thread thread_; -}; diff --git a/core/loops/event_loop_thread_pool.cpp b/core/loops/event_loop_thread_pool.cpp deleted file mode 100644 index ebd5c3a..0000000 --- a/core/loops/event_loop_thread_pool.cpp +++ /dev/null @@ -1,77 +0,0 @@ - -// This file is originally from Trantor - EventLoopThreadPool.cc - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "event_loop_thread_pool.h" - -EventLoopThreadPool::EventLoopThreadPool(size_t threadNum, - const std::string &name) : - loopIndex_(0) { - for (size_t i = 0; i < threadNum; ++i) { - loopThreadVector_.emplace_back(std::make_shared(name)); - } -} -void EventLoopThreadPool::start() { - for (unsigned int i = 0; i < loopThreadVector_.size(); ++i) { - loopThreadVector_[i]->run(); - } -} -// void EventLoopThreadPool::stop(){ -// for(unsigned int i=0;iwait(); - } -} -EventLoop *EventLoopThreadPool::getNextLoop() { - if (loopThreadVector_.size() > 0) { - EventLoop *loop = loopThreadVector_[loopIndex_]->getLoop(); - ++loopIndex_; - if (loopIndex_ >= loopThreadVector_.size()) - loopIndex_ = 0; - return loop; - } - return nullptr; -} -EventLoop *EventLoopThreadPool::getLoop(size_t id) { - if (id < loopThreadVector_.size()) - return loopThreadVector_[id]->getLoop(); - return nullptr; -} -std::vector EventLoopThreadPool::getLoops() const { - std::vector ret; - for (auto &loopThread : loopThreadVector_) { - ret.push_back(loopThread->getLoop()); - } - return ret; -} \ No newline at end of file diff --git a/core/loops/event_loop_thread_pool.h b/core/loops/event_loop_thread_pool.h deleted file mode 100644 index 2fcf8e9..0000000 --- a/core/loops/event_loop_thread_pool.h +++ /dev/null @@ -1,109 +0,0 @@ - -// This file is originally from Trantor - EventLoopThreadPool.h - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include "event_loop_thread.h" -#include -#include - -/** - * @brief This class represents a pool of EventLoopThread objects - * - */ -class EventLoopThreadPool { -protected: - EventLoopThreadPool(const EventLoopThreadPool &) = delete; - EventLoopThreadPool &operator=(const EventLoopThreadPool &) = delete; - // some uncopyable classes maybe support move constructor.... - EventLoopThreadPool(EventLoopThreadPool &&) noexcept(true) = default; - EventLoopThreadPool &operator=(EventLoopThreadPool &&) noexcept(true) = default; - -public: - EventLoopThreadPool() = delete; - - /** - * @brief Construct a new event loop thread pool instance. - * - * @param threadNum The number of threads - * @param name The name of the EventLoopThreadPool object. - */ - EventLoopThreadPool(size_t threadNum, - const std::string &name = "EventLoopThreadPool"); - - /** - * @brief Run all event loops in the pool. - * @note This function doesn't block the current thread. - */ - void start(); - - /** - * @brief Wait for all event loops in the pool to quit. - * - * @note This function blocks the current thread. - */ - void wait(); - - /** - * @brief Return the number of the event loop. - * - * @return size_t - */ - size_t size() { - return loopThreadVector_.size(); - } - - /** - * @brief Get the next event loop in the pool. - * - * @return EventLoop* - */ - EventLoop *getNextLoop(); - - /** - * @brief Get the event loop in the `id` position in the pool. - * - * @param id The id of the first event loop is zero. If the id >= the number - * of event loops, nullptr is returned. - * @return EventLoop* - */ - EventLoop *getLoop(size_t id); - - /** - * @brief Get all event loops in the pool. - * - * @return std::vector - */ - std::vector getLoops() const; - -private: - std::vector > loopThreadVector_; - size_t loopIndex_; -}; diff --git a/core/loops/timer.cpp b/core/loops/timer.cpp deleted file mode 100644 index ac2d74d..0000000 --- a/core/loops/timer.cpp +++ /dev/null @@ -1,69 +0,0 @@ - -// This file is originally from Trantor - Timer.cc - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "timer.h" -#include "core/log/logger.h" -#include "core/loops/event_loop.h" - -std::atomic Timer::timersCreated_ = ATOMIC_VAR_INIT(InvalidTimerId); -Timer::Timer(const TimerCallback &cb, - const TimePoint &when, - const TimeInterval &interval) : - callback_(cb), - when_(when), - interval_(interval), - repeat_(interval.count() > 0), - id_(++timersCreated_) { -} -Timer::Timer(TimerCallback &&cb, - const TimePoint &when, - const TimeInterval &interval) : - callback_(std::move(cb)), - when_(when), - interval_(interval), - repeat_(interval.count() > 0), - id_(++timersCreated_) { - // LOG_TRACE<<"Timer move contrustor"; -} -void Timer::run() const { - callback_(); -} -void Timer::restart(const TimePoint &now) { - if (repeat_) { - when_ = now + interval_; - } else - when_ = std::chrono::steady_clock::now(); -} -bool Timer::operator<(const Timer &t) const { - return when_ < t.when_; -} -bool Timer::operator>(const Timer &t) const { - return when_ > t.when_; -} diff --git a/core/loops/timer.h b/core/loops/timer.h deleted file mode 100644 index 49c1c2e..0000000 --- a/core/loops/timer.h +++ /dev/null @@ -1,83 +0,0 @@ - -// This file is originally from Trantor - Timer.h - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include "core/net/callbacks.h" -#include -#include -#include -#include - -using TimerId = uint64_t; -using TimePoint = std::chrono::steady_clock::time_point; -using TimeInterval = std::chrono::microseconds; - -class Timer { -protected: - Timer(const Timer &) = delete; - Timer &operator=(const Timer &) = delete; - // some uncopyable classes maybe support move constructor.... - Timer(Timer &&) noexcept(true) = default; - Timer &operator=(Timer &&) noexcept(true) = default; - -public: - Timer(const TimerCallback &cb, - const TimePoint &when, - const TimeInterval &interval); - Timer(TimerCallback &&cb, - const TimePoint &when, - const TimeInterval &interval); - ~Timer() { - // std::cout<<"Timer unconstract!"<(const Timer &t) const; - const TimePoint &when() const { - return when_; - } - bool isRepeat() { - return repeat_; - } - TimerId id() { - return id_; - } - -private: - TimerCallback callback_; - TimePoint when_; - const TimeInterval interval_; - const bool repeat_; - const TimerId id_; - static std::atomic timersCreated_; -}; - diff --git a/core/loops/timer_queue.h b/core/loops/timer_queue.h deleted file mode 100644 index 32c2988..0000000 --- a/core/loops/timer_queue.h +++ /dev/null @@ -1,93 +0,0 @@ - -// This file is originally from Trantor - TimerQueue.h - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include "timer.h" -#include "core/net/callbacks.h" -#include -#include -#include -#include - -// class Timer; -class EventLoop; -class Channel; -using TimerPtr = std::shared_ptr; -struct TimerPtrComparer { - bool operator()(const TimerPtr &x, const TimerPtr &y) const { - return *x > *y; - } -}; - -class TimerQueue { -protected: - TimerQueue(const TimerQueue &) = delete; - TimerQueue &operator=(const TimerQueue &) = delete; - // some uncopyable classes maybe support move constructor.... - TimerQueue(TimerQueue &&) noexcept(true) = default; - TimerQueue &operator=(TimerQueue &&) noexcept(true) = default; - -public: - explicit TimerQueue(EventLoop *loop); - ~TimerQueue(); - TimerId addTimer(const TimerCallback &cb, - const TimePoint &when, - const TimeInterval &interval); - TimerId addTimer(TimerCallback &&cb, - const TimePoint &when, - const TimeInterval &interval); - void addTimerInLoop(const TimerPtr &timer); - void invalidateTimer(TimerId id); -#ifdef __linux__ - void reset(); -#else - int64_t getTimeout() const; - void processTimers(); -#endif -protected: - EventLoop *loop_; -#ifdef __linux__ - int timerfd_; - std::shared_ptr timerfdChannelPtr_; - void handleRead(); -#endif - std::priority_queue, TimerPtrComparer> - timers_; - - bool callingExpiredTimers_; - bool insert(const TimerPtr &timePtr); - std::vector getExpired(); - void reset(const std::vector &expired, const TimePoint &now); - std::vector getExpired(const TimePoint &now); - -private: - std::unordered_set timerIdSet_; -}; diff --git a/core/math/math.h b/core/math/math.h index 57359f3..6ffbe9d 100644 --- a/core/math/math.h +++ b/core/math/math.h @@ -323,24 +323,6 @@ public: return hf; } - - // Taken from Trantor (BSD-style License) - Funcs.h - // Copyright (c) 2018 An Tao - static _ALWAYS_INLINE_ uint64_t hton64(uint64_t n) { - static const int one = 1; - static const char sig = *(char *)&one; - if (sig == 0) - return n; // for big endian machine just return the input - char *ptr = reinterpret_cast(&n); - std::reverse(ptr, ptr + sizeof(uint64_t)); - return n; - } - - // Taken from Trantor (BSD-style License) - Funcs.h - // Copyright (c) 2018 An Tao - static _ALWAYS_INLINE_ uint64_t ntoh64(uint64_t n) { - return hton64(n); - } }; #ifndef ABS diff --git a/core/net/acceptor.cpp b/core/net/acceptor.cpp deleted file mode 100644 index 25d7824..0000000 --- a/core/net/acceptor.cpp +++ /dev/null @@ -1,100 +0,0 @@ - -// This file is originally from Trantor - Acceptor.cc - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "acceptor.h" - -#ifndef O_CLOEXEC -#define O_CLOEXEC O_NOINHERIT -#endif - -Acceptor::Acceptor(EventLoop *loop, - const InetAddress &addr, - bool reUseAddr, - bool reUsePort) - - : -#ifndef _WIN32 - idleFd_(::open("/dev/null", O_RDONLY | O_CLOEXEC)), -#endif - sock_( - Socket::createNonblockingSocketOrDie(addr.getSockAddr()->sa_family)), - addr_(addr), - loop_(loop), - acceptChannel_(loop, sock_.fd()) { - sock_.setReuseAddr(reUseAddr); - sock_.setReusePort(reUsePort); - sock_.bindAddress(addr_); - acceptChannel_.setReadCallback(std::bind(&Acceptor::readCallback, this)); - if (addr_.toPort() == 0) { - addr_ = InetAddress{ Socket::getLocalAddr(sock_.fd()) }; - } -} -Acceptor::~Acceptor() { - acceptChannel_.disableAll(); - acceptChannel_.remove(); -#ifndef _WIN32 - ::close(idleFd_); -#endif -} -void Acceptor::listen() { - loop_->assertInLoopThread(); - sock_.listen(); - acceptChannel_.enableReading(); -} - -void Acceptor::readCallback() { - InetAddress peer; - int newsock = sock_.accept(&peer); - if (newsock >= 0) { - if (newConnectionCallback_) { - newConnectionCallback_(newsock, peer); - } else { -#ifndef _WIN32 - ::close(newsock); -#else - closesocket(newsock); -#endif - } - } else { - LOG_SYSERR << "Accpetor::readCallback"; -// Read the section named "The special problem of -// accept()ing when you can't" in libev's doc. -// By Marc Lehmann, author of libev. -/// errno is thread safe -#ifndef _WIN32 - if (errno == EMFILE) { - ::close(idleFd_); - idleFd_ = sock_.accept(&peer); - ::close(idleFd_); - idleFd_ = ::open("/dev/null", O_RDONLY | O_CLOEXEC); - } -#endif - } -} diff --git a/core/net/acceptor.h b/core/net/acceptor.h deleted file mode 100644 index ef549e7..0000000 --- a/core/net/acceptor.h +++ /dev/null @@ -1,76 +0,0 @@ - -// This file is originally from Trantor - Acceptor.h - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include "channel.h" -#include "core/net/inet_address.h" -#include "core/net/socket.h" -#include "core/loops/event_loop.h" -#include - -// Inherit from socket? -// Could be called ServerSocket -// New connection callback -> make it a virtual func? - -using NewConnectionCallback = std::function; -class Acceptor { -protected: - Acceptor(const Acceptor &) = delete; - Acceptor &operator=(const Acceptor &) = delete; - // some uncopyable classes maybe support move constructor.... - Acceptor(Acceptor &&) noexcept(true) = default; - Acceptor &operator=(Acceptor &&) noexcept(true) = default; - -public: - Acceptor(EventLoop *loop, - const InetAddress &addr, - bool reUseAddr = true, - bool reUsePort = true); - ~Acceptor(); - const InetAddress &addr() const { - return addr_; - } - void setNewConnectionCallback(const NewConnectionCallback &cb) { - newConnectionCallback_ = cb; - }; - void listen(); - -protected: -#ifndef _WIN32 - int idleFd_; -#endif - Socket sock_; - InetAddress addr_; - EventLoop *loop_; - NewConnectionCallback newConnectionCallback_; - Channel acceptChannel_; - void readCallback(); -}; diff --git a/core/net/callbacks.h b/core/net/callbacks.h deleted file mode 100644 index 1648dbc..0000000 --- a/core/net/callbacks.h +++ /dev/null @@ -1,57 +0,0 @@ - -// This file is originally from Trantor - callbacks.h - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include -#include - -enum class SSLError -{ - kSSLHandshakeError, - kSSLInvalidCertificate -}; -using TimerCallback = std::function; - -// the data has been read to (buf, len) -class TcpConnection; -class MsgBuffer; -using TcpConnectionPtr = std::shared_ptr; -// tcp server and connection callback -using RecvMessageCallback = - std::function; -using ConnectionErrorCallback = std::function; -using ConnectionCallback = std::function; -using CloseCallback = std::function; -using WriteCompleteCallback = std::function; -using HighWaterMarkCallback = - std::function; -using SSLErrorCallback = std::function; - diff --git a/core/net/channel.cpp b/core/net/channel.cpp deleted file mode 100644 index 4a46e93..0000000 --- a/core/net/channel.cpp +++ /dev/null @@ -1,113 +0,0 @@ - -// This file is originally from Trantor - Channel.cc - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "channel.h" -#include "core/loops/event_loop.h" - -#ifdef _WIN32 -#include "Wepoll.h" -#define POLLIN EPOLLIN -#define POLLPRI EPOLLPRI -#define POLLOUT EPOLLOUT -#define POLLHUP EPOLLHUP -#define POLLNVAL 0 -#define POLLERR EPOLLERR -#else -#include -#endif -#include - -const int Channel::kNoneEvent = 0; - -const int Channel::kReadEvent = POLLIN | POLLPRI; -const int Channel::kWriteEvent = POLLOUT; - -Channel::Channel(EventLoop *loop, int fd) : - loop_(loop), fd_(fd), events_(0), revents_(0), index_(-1), tied_(false) { -} - -void Channel::remove() { - assert(events_ == kNoneEvent); - addedToLoop_ = false; - loop_->removeChannel(this); -} - -void Channel::update() { - loop_->updateChannel(this); -} - -void Channel::handleEvent() { - // LOG_TRACE<<"revents_="< guard = tie_.lock(); - if (guard) { - handleEventSafely(); - } - } else { - handleEventSafely(); - } -} -void Channel::handleEventSafely() { - if (eventCallback_) { - eventCallback_(); - return; - } - if ((revents_ & POLLHUP) && !(revents_ & POLLIN)) { - // LOG_TRACE<<"handle close"; - if (closeCallback_) - closeCallback_(); - } - if (revents_ & (POLLNVAL | POLLERR)) { - // LOG_TRACE<<"handle error"; - if (errorCallback_) - errorCallback_(); - } -#ifdef __linux__ - if (revents_ & (POLLIN | POLLPRI | POLLRDHUP)) -#else - if (revents_ & (POLLIN | POLLPRI)) -#endif - { - // LOG_TRACE<<"handle read"; - if (readCallback_) - readCallback_(); - } -#ifdef _WIN32 - if ((revents_ & POLLOUT) && !(revents_ & POLLHUP)) -#else - if (revents_ & POLLOUT) -#endif - { - // LOG_TRACE<<"handle write"; - if (writeCallback_) - writeCallback_(); - } -} - diff --git a/core/net/channel.h b/core/net/channel.h deleted file mode 100644 index 96b0040..0000000 --- a/core/net/channel.h +++ /dev/null @@ -1,306 +0,0 @@ - -// This file is originally from Trantor - Channel.h - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include "core/log/logger.h" -#include -#include -#include - - -class EventLoop; -/** - * @brief This class is used to implement reactor pattern. A Channel object - * manages a socket fd. Users use a Channel object to receive write or read - * events on the socket it manages. - * - */ -class Channel { -protected: - Channel(const Channel &) = delete; - Channel &operator=(const Channel &) = delete; - // some uncopyable classes maybe support move constructor.... - Channel(Channel &&) noexcept(true) = default; - Channel &operator=(Channel &&) noexcept(true) = default; - -public: - using EventCallback = std::function; - /** - * @brief Construct a new Channel instance. - * - * @param loop The event loop in which the channel works. - * @param fd The socket fd. - */ - Channel(EventLoop *loop, int fd); - - /** - * @brief Set the read callback. - * - * @param cb The callback is called when read event occurs on the socket. - * @note One should call the enableReading() method to ensure that the - * callback would be called when some data is received on the socket. - */ - void setReadCallback(const EventCallback &cb) { - readCallback_ = cb; - }; - void setReadCallback(EventCallback &&cb) { - readCallback_ = std::move(cb); - } - - /** - * @brief Set the write callback. - * - * @param cb The callback is called when write event occurs on the socket. - * @note One should call the enableWriting() method to ensure that the - * callback would be called when the socket can be written. - */ - void setWriteCallback(const EventCallback &cb) { - writeCallback_ = cb; - }; - void setWriteCallback(EventCallback &&cb) { - writeCallback_ = std::move(cb); - } - - /** - * @brief Set the close callback. - * - * @param cb The callback is called when the socket is closed. - */ - void setCloseCallback(const EventCallback &cb) { - closeCallback_ = cb; - } - void setCloseCallback(EventCallback &&cb) { - closeCallback_ = std::move(cb); - } - - /** - * @brief Set the error callback. - * - * @param cb The callback is called when an error occurs on the socket. - */ - void setErrorCallback(const EventCallback &cb) { - errorCallback_ = cb; - } - void setErrorCallback(EventCallback &&cb) { - errorCallback_ = std::move(cb); - } - - /** - * @brief Set the event callback. - * - * @param cb The callback is called when any event occurs on the socket. - * @note If the event callback is set to the channel, any other callback - * wouldn't be called again. - */ - void setEventCallback(const EventCallback &cb) { - eventCallback_ = cb; - } - void setEventCallback(EventCallback &&cb) { - eventCallback_ = std::move(cb); - } - - /** - * @brief Return the fd of the socket. - * - * @return int - */ - int fd() const { - return fd_; - } - - /** - * @brief Return the events enabled on the socket. - * - * @return int - */ - int events() const { - return events_; - } - - /** - * @brief Return the events that occurred on the socket. - * - * @return int - */ - int revents() const { - return revents_; - } - - /** - * @brief Check whether there is no event enabled on the socket. - * - * @return true - * @return false - */ - bool isNoneEvent() const { - return events_ == kNoneEvent; - }; - - /** - * @brief Disable all events on the socket. - * - */ - void disableAll() { - events_ = kNoneEvent; - update(); - } - - /** - * @brief Remove the socket from the poller in the event loop. - * - */ - void remove(); - - /** - * @brief Return the event loop. - * - * @return EventLoop* - */ - EventLoop *ownerLoop() { - return loop_; - }; - - /** - * @brief Enable the read event on the socket. - * - */ - void enableReading() { - events_ |= kReadEvent; - update(); - } - - /** - * @brief Disable the read event on the socket. - * - */ - void disableReading() { - events_ &= ~kReadEvent; - update(); - } - - /** - * @brief Enable the write event on the socket. - * - */ - void enableWriting() { - events_ |= kWriteEvent; - update(); - } - - /** - * @brief Disable the write event on the socket. - * - */ - void disableWriting() { - events_ &= ~kWriteEvent; - update(); - } - - /** - * @brief Check whether the write event is enabled on the socket. - * - * @return true - * @return false - */ - bool isWriting() const { - return events_ & kWriteEvent; - } - - /** - * @brief Check whether the read event is enabled on the socket. - * - * @return true - * @return false - */ - bool isReading() const { - return events_ & kReadEvent; - } - - /** - * @brief Set and update the events enabled. - * - * @param events - */ - void updateEvents(int events) { - events_ = events; - update(); - } - - /** - * @brief This method is used to ensure that the callback owner is valid - * when a callback is called. - * - * @param obj The callback owner. Usually, the owner is also the owner of - * the channel. - * @note The 'obj' is kept in a weak_ptr object, so this method does not - * cause a circular reference problem. - */ - void tie(const std::shared_ptr &obj) { - tie_ = obj; - tied_ = true; - } - - static const int kNoneEvent; - static const int kReadEvent; - static const int kWriteEvent; - -private: - friend class EventLoop; - friend class EpollPoller; - friend class KQueue; - void update(); - void handleEvent(); - void handleEventSafely(); - int setRevents(int revt) { - // LOG_TRACE<<"revents="< tie_; - bool tied_; -}; diff --git a/core/net/connections/tcp_connection_impl.h b/core/net/connections/tcp_connection_impl.h deleted file mode 100644 index 3cbdb96..0000000 --- a/core/net/connections/tcp_connection_impl.h +++ /dev/null @@ -1,326 +0,0 @@ - -// This file is originally from Trantor - TcpConnectionImpl.h - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include "core/loops/timing_wheel.h" -#include "core/net/tcp_connection.h" -#include -#include -#ifndef _WIN32 -#include -#endif -#include -#include - -#ifdef USE_OPENSSL - -enum class SSLStatus { - Handshaking, - Connecting, - Connected, - DisConnecting, - DisConnected -}; - -class SSLContext; -class SSLConn; - -std::shared_ptr newSSLContext(bool useOldTLS, bool validateCert, const std::vector > &sslConfCmds); -std::shared_ptr newSSLServerContext(const std::string &certPath, const std::string &keyPath, bool useOldTLS, const std::vector > &sslConfCmds); -// void initServerSSLContext(const std::shared_ptr &ctx, const std::string &certPath, const std::string &keyPath); - -#endif - -class Channel; -class Socket; -class TcpServer; -void removeConnection(EventLoop *loop, const TcpConnectionPtr &conn); - -class TcpConnectionImpl : public TcpConnection, public std::enable_shared_from_this { - friend class TcpServer; - friend class TcpClient; - - friend void removeConnection(EventLoop *loop, const TcpConnectionPtr &conn); - -protected: - TcpConnectionImpl(const TcpConnectionImpl &) = delete; - TcpConnectionImpl &operator=(const TcpConnectionImpl &) = delete; - // some uncopyable classes maybe support move constructor.... - TcpConnectionImpl(TcpConnectionImpl &&) noexcept(true) = default; - TcpConnectionImpl &operator=(TcpConnectionImpl &&) noexcept(true) = default; - -public: - class KickoffEntry { - public: - explicit KickoffEntry(const std::weak_ptr &conn) : - conn_(conn) { - } - - void reset() { - conn_.reset(); - } - - ~KickoffEntry() { - auto conn = conn_.lock(); - if (conn) { - conn->forceClose(); - } - } - - private: - std::weak_ptr conn_; - }; - - TcpConnectionImpl(EventLoop *loop, int socketfd, const InetAddress &localAddr, const InetAddress &peerAddr); -#ifdef USE_OPENSSL - TcpConnectionImpl(EventLoop *loop, int socketfd, const InetAddress &localAddr, const InetAddress &peerAddr, const std::shared_ptr &ctxPtr, bool isServer = true, bool validateCert = true, const std::string &hostname = ""); -#endif - - virtual ~TcpConnectionImpl(); - - virtual void send(const char *msg, size_t len) override; - virtual void send(const void *msg, size_t len) override; - virtual void send(const std::string &msg) override; - virtual void send(std::string &&msg) override; - virtual void send(const MsgBuffer &buffer) override; - virtual void send(MsgBuffer &&buffer) override; - virtual void send(const std::shared_ptr &msgPtr) override; - virtual void send(const std::shared_ptr &msgPtr) override; - virtual void sendFile(const char *fileName, size_t offset = 0, size_t length = 0) override; - - virtual const InetAddress &localAddr() const override { - return localAddr_; - } - - virtual const InetAddress &peerAddr() const override { - return peerAddr_; - } - - virtual bool connected() const override { - return status_ == ConnStatus::Connected; - } - - virtual bool disconnected() const override { - return status_ == ConnStatus::Disconnected; - } - - // virtual MsgBuffer* getSendBuffer() override{ return &writeBuffer_;} - virtual MsgBuffer *getRecvBuffer() override { - return &readBuffer_; - } - - // set callbacks - virtual void setHighWaterMarkCallback(const HighWaterMarkCallback &cb, size_t markLen) override { - highWaterMarkCallback_ = cb; - highWaterMarkLen_ = markLen; - } - - virtual void keepAlive() override { - idleTimeout_ = 0; - auto entry = kickoffEntry_.lock(); - if (entry) { - entry->reset(); - } - } - - virtual bool isKeepAlive() override { - return idleTimeout_ == 0; - } - - virtual void setTcpNoDelay(bool on) override; - virtual void shutdown() override; - virtual void forceClose() override; - - virtual EventLoop *getLoop() override { - return loop_; - } - - virtual size_t bytesSent() const override { - return bytesSent_; - } - - virtual size_t bytesReceived() const override { - return bytesReceived_; - } - - virtual void startClientEncryption(std::function callback, bool useOldTLS = false, bool validateCert = true, std::string hostname = "", const std::vector > &sslConfCmds = {}) override; - virtual void startServerEncryption(const std::shared_ptr &ctx, std::function callback) override; - virtual bool isSSLConnection() const override { - return isEncrypted_; - } - -private: - /// Internal use only. - - std::weak_ptr kickoffEntry_; - std::weak_ptr timingWheelWeakPtr_; - size_t idleTimeout_{ 0 }; - Date lastTimingWheelUpdateTime_; - - void enableKickingOff(size_t timeout, const std::shared_ptr &timingWheel) { - assert(timingWheel); - assert(timingWheel->getLoop() == loop_); - assert(timeout > 0); - auto entry = std::make_shared(shared_from_this()); - kickoffEntry_ = entry; - timingWheelWeakPtr_ = timingWheel; - idleTimeout_ = timeout; - timingWheel->insertEntry(timeout, entry); - } - - void extendLife(); -#ifndef _WIN32 - void sendFile(int sfd, size_t offset = 0, size_t length = 0); -#else - void sendFile(FILE *fp, size_t offset = 0, size_t length = 0); -#endif - void setRecvMsgCallback(const RecvMessageCallback &cb) { - recvMsgCallback_ = cb; - } - - void setConnectionCallback(const ConnectionCallback &cb) { - connectionCallback_ = cb; - } - - void setWriteCompleteCallback(const WriteCompleteCallback &cb) { - writeCompleteCallback_ = cb; - } - - void setCloseCallback(const CloseCallback &cb) { - closeCallback_ = cb; - } - - void setSSLErrorCallback(const SSLErrorCallback &cb) { - sslErrorCallback_ = cb; - } - - void connectDestroyed(); - virtual void connectEstablished(); - -protected: - struct BufferNode { -#ifndef _WIN32 - int sendFd_{ -1 }; - off_t offset_; -#else - FILE *sendFp_{ nullptr }; - long long offset_; -#endif - ssize_t fileBytesToSend_; - std::shared_ptr msgBuffer_; - - ~BufferNode() { -#ifndef _WIN32 - if (sendFd_ >= 0) - close(sendFd_); -#else - if (sendFp_) - fclose(sendFp_); -#endif - } - }; - - using BufferNodePtr = std::shared_ptr; - enum class ConnStatus { - Disconnected, - Connecting, - Connected, - Disconnecting - }; - - bool isEncrypted_{ false }; - EventLoop *loop_; - std::unique_ptr ioChannelPtr_; - std::unique_ptr socketPtr_; - MsgBuffer readBuffer_; - std::list writeBufferList_; - - void readCallback(); - void writeCallback(); - - InetAddress localAddr_, peerAddr_; - ConnStatus status_{ ConnStatus::Connecting }; - // callbacks - RecvMessageCallback recvMsgCallback_; - ConnectionCallback connectionCallback_; - CloseCallback closeCallback_; - WriteCompleteCallback writeCompleteCallback_; - HighWaterMarkCallback highWaterMarkCallback_; - SSLErrorCallback sslErrorCallback_; - - void handleClose(); - void handleError(); - // virtual void sendInLoop(const std::string &msg); - - void sendFileInLoop(const BufferNodePtr &file); -#ifndef _WIN32 - void sendInLoop(const void *buffer, size_t length); - ssize_t writeInLoop(const void *buffer, size_t length); -#else - void sendInLoop(const char *buffer, size_t length); - ssize_t writeInLoop(const char *buffer, size_t length); -#endif - size_t highWaterMarkLen_; - std::string name_; - - uint64_t sendNum_{ 0 }; - std::mutex sendNumMutex_; - - size_t bytesSent_{ 0 }; - size_t bytesReceived_{ 0 }; - - std::unique_ptr > fileBufferPtr_; - -#ifdef USE_OPENSSL -private: - void doHandshaking(); - bool validatePeerCertificate(); - - struct SSLEncryption { - SSLStatus statusOfSSL_ = SSLStatus::Handshaking; - // OpenSSL - std::shared_ptr sslCtxPtr_; - std::unique_ptr sslPtr_; - std::unique_ptr > sendBufferPtr_; - bool isServer_{ false }; - bool isUpgrade_{ false }; - std::function upgradeCallback_; - std::string hostname_; - }; - - std::unique_ptr sslEncryptionPtr_; - - void startClientEncryptionInLoop(std::function &&callback, bool useOldTLS, bool validateCert, const std::string &hostname, const std::vector > &sslConfCmds); - void startServerEncryptionInLoop(const std::shared_ptr &ctx, std::function &&callback); -#endif -}; - -using TcpConnectionImplPtr = std::shared_ptr; diff --git a/core/net/connector.h b/core/net/connector.h deleted file mode 100644 index 4fc3cb1..0000000 --- a/core/net/connector.h +++ /dev/null @@ -1,112 +0,0 @@ - -// This file is originally from Trantor - Connector.h - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include "core/loops/event_loop.h" -#include "core/net/inet_address.h" -#include -#include - -// inherit from socket? -// Could be called ClientSocket -// New connection callback -> make it a virtual func? - -class Connector : public std::enable_shared_from_this { -protected: - Connector(const Connector &) = delete; - Connector &operator=(const Connector &) = delete; - // some uncopyable classes maybe support move constructor.... - Connector(Connector &&) noexcept(true) = default; - Connector &operator=(Connector &&) noexcept(true) = default; - -public: - using NewConnectionCallback = std::function; - using ConnectionErrorCallback = std::function; - - Connector(EventLoop *loop, const InetAddress &addr, bool retry = true); - Connector(EventLoop *loop, InetAddress &&addr, bool retry = true); - - void setNewConnectionCallback(const NewConnectionCallback &cb) { - newConnectionCallback_ = cb; - } - - void setNewConnectionCallback(NewConnectionCallback &&cb) { - newConnectionCallback_ = std::move(cb); - } - - void setErrorCallback(const ConnectionErrorCallback &cb) { - errorCallback_ = cb; - } - - void setErrorCallback(ConnectionErrorCallback &&cb) { - errorCallback_ = std::move(cb); - } - - const InetAddress &serverAddress() const { - return serverAddr_; - } - - void start(); - void restart(); - void stop(); - -private: - NewConnectionCallback newConnectionCallback_; - ConnectionErrorCallback errorCallback_; - - enum class Status { - Disconnected, - Connecting, - Connected - }; - - static constexpr int kMaxRetryDelayMs = 30 * 1000; - static constexpr int kInitRetryDelayMs = 500; - std::shared_ptr channelPtr_; - EventLoop *loop_; - InetAddress serverAddr_; - - std::atomic_bool connect_{ false }; - std::atomic status_{ Status::Disconnected }; - - int retryInterval_{ kInitRetryDelayMs }; - int maxRetryInterval_{ kMaxRetryDelayMs }; - - bool retry_; - - void startInLoop(); - void connect(); - void connecting(int sockfd); - int removeAndResetChannel(); - void handleWrite(); - void handleError(); - void retry(int sockfd); -}; diff --git a/core/net/inet_address.h b/core/net/inet_address.h deleted file mode 100644 index 45f716b..0000000 --- a/core/net/inet_address.h +++ /dev/null @@ -1,113 +0,0 @@ - -// This file is originally from Moduo -> Trantor - InetAddress.h - -// Copyright (c) 2016-2021, Tao An. All rights reserved. -// Copyright 2010, Shuo Chen. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef MUDUO_NET_INETADDRESS_H -#define MUDUO_NET_INETADDRESS_H - -#ifdef _WIN32 -#include -using sa_family_t = unsigned short; -using in_addr_t = uint32_t; -using uint16_t = unsigned short; -#else -#include -#include -#include -#endif -#include -#include -#include - -class InetAddress { -public: - InetAddress(uint16_t port = 0, bool loopbackOnly = false, bool ipv6 = false); - - InetAddress(const std::string &ip, uint16_t port, bool ipv6 = false); - - explicit InetAddress(const struct sockaddr_in &addr) : - addr_(addr), isUnspecified_(false) { - } - - explicit InetAddress(const struct sockaddr_in6 &addr) : - addr6_(addr), isIpV6_(true), isUnspecified_(false) { - } - - sa_family_t family() const { - return addr_.sin_family; - } - - std::string toIp() const; - std::string toIpPort() const; - uint16_t toPort() const; - - bool isIpV6() const { - return isIpV6_; - } - - bool isIntranetIp() const; - bool isLoopbackIp() const; - - const struct sockaddr *getSockAddr() const { - return static_cast((void *)(&addr6_)); - } - - void setSockAddrInet6(const struct sockaddr_in6 &addr6) { - addr6_ = addr6; - isIpV6_ = (addr6_.sin6_family == AF_INET6); - isUnspecified_ = false; - } - - uint32_t ipNetEndian() const; - const uint32_t *ip6NetEndian() const; - - uint16_t portNetEndian() const { - return addr_.sin_port; - } - - void setPortNetEndian(uint16_t port) { - addr_.sin_port = port; - } - - inline bool isUnspecified() const { - return isUnspecified_; - } - -private: - union { - struct sockaddr_in addr_; - struct sockaddr_in6 addr6_; - }; - - bool isIpV6_{ false }; - bool isUnspecified_{ true }; -}; - -#endif // MUDUO_NET_INETADDRESS_H diff --git a/core/net/platform/windows_support.cpp b/core/net/platform/windows_support.cpp deleted file mode 100644 index 837a80a..0000000 --- a/core/net/platform/windows_support.cpp +++ /dev/null @@ -1,61 +0,0 @@ - -// This file is originally from Trantor - WindowsSupport.cc - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "windows_support.h" -#include - -// from polipo -int win32_read_socket(int fd, void *buf, int n) { - int rc = recv(fd, reinterpret_cast(buf), n, 0); - if (rc == SOCKET_ERROR) { - _set_errno(WSAGetLastError()); - } - return rc; -} - -int readv(int fd, const struct iovec *vector, int count) { - int ret = 0; /* Return value */ - int i; - for (i = 0; i < count; i++) { - int n = vector[i].iov_len; - int rc = win32_read_socket(fd, vector[i].iov_base, n); - if (rc == n) { - ret += rc; - } else { - if (rc < 0) { - ret = (ret == 0 ? rc : ret); - } else { - ret += rc; - } - break; - } - } - return ret; -} diff --git a/core/net/platform/windows_support.h b/core/net/platform/windows_support.h deleted file mode 100644 index 0545bb9..0000000 --- a/core/net/platform/windows_support.h +++ /dev/null @@ -1,41 +0,0 @@ - -// This file is originally from Trantor - WindowsSupport.h - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include - -struct iovec -{ - void *iov_base; /* Starting address */ - int iov_len; /* Number of bytes */ -}; - -int readv(int fd, const struct iovec *vector, int count); diff --git a/core/net/resolver.h b/core/net/resolver.h deleted file mode 100644 index 1b2fdf7..0000000 --- a/core/net/resolver.h +++ /dev/null @@ -1,53 +0,0 @@ - -// This file is originally from Trantor - Resolver.h - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include -#include "core/loops/event_loop.h" -#include "core/net/inet_address.h" - -//make it a reference - -class Resolver -{ - public: - using Callback = std::function; - - static std::shared_ptr newResolver(EventLoop* loop = nullptr, size_t timeout = 60); - - virtual void resolve(const std::string& hostname, const Callback& callback) = 0; - - virtual ~Resolver() - { - } - - static bool isCAresUsed(); -}; diff --git a/core/net/resolvers/ares_resolver.h b/core/net/resolvers/ares_resolver.h deleted file mode 100644 index f77a645..0000000 --- a/core/net/resolvers/ares_resolver.h +++ /dev/null @@ -1,163 +0,0 @@ - -// This file is originally from Trantor - AresResolver.h - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include "core/loops/event_loop_thread.h" -#include "core/net/resolver.h" -#include -#include -#include - -// Resolver will be a ref - -extern "C" { -struct hostent; -struct ares_channeldata; -using ares_channel = struct ares_channeldata *; -} - -class AresResolver : public Resolver, public std::enable_shared_from_this { -protected: - AresResolver(const AresResolver &) = delete; - AresResolver &operator=(const AresResolver &) = delete; - // some uncopyable classes maybe support move constructor.... - AresResolver(AresResolver &&) noexcept(true) = default; - AresResolver &operator=(AresResolver &&) noexcept(true) = default; - -public: - AresResolver(EventLoop *loop, size_t timeout); - ~AresResolver(); - - virtual void resolve(const std::string &hostname, const Callback &cb) override { - bool cached = false; - - InetAddress inet; - { - std::lock_guard lock(globalMutex()); - auto iter = globalCache().find(hostname); - if (iter != globalCache().end()) { - auto &cachedAddr = iter->second; - if (timeout_ == 0 || - cachedAddr.second.after(timeout_) > Date::date()) { - struct sockaddr_in addr; - memset(&addr, 0, sizeof addr); - addr.sin_family = AF_INET; - addr.sin_port = 0; - addr.sin_addr = cachedAddr.first; - inet = InetAddress(addr); - cached = true; - } - } - } - - if (cached) { - cb(inet); - return; - } - - if (loop_->isInLoopThread()) { - resolveInLoop(hostname, cb); - } else { - loop_->queueInLoop([thisPtr = shared_from_this(), hostname, cb]() { - thisPtr->resolveInLoop(hostname, cb); - }); - } - } - -private: - struct QueryData { - AresResolver *owner_; - Callback callback_; - std::string hostname_; - - QueryData(AresResolver *o, const Callback &cb, const std::string &hostname) : - owner_(o), callback_(cb), hostname_(hostname) { - } - }; - - void resolveInLoop(const std::string &hostname, const Callback &cb); - void init(); - - EventLoop *loop_; - ares_channel ctx_{ nullptr }; - bool timerActive_{ false }; - using ChannelList = std::map >; - ChannelList channels_; - static std::unordered_map > & - - globalCache() { - static std::unordered_map > dnsCache; - return dnsCache; - } - - static std::mutex &globalMutex() { - static std::mutex mutex_; - return mutex_; - } - - static EventLoop *getLoop() { - static EventLoopThread loopThread; - loopThread.run(); - return loopThread.getLoop(); - } - - const size_t timeout_{ 60 }; - - void onRead(int sockfd); - void onTimer(); - void onQueryResult(int status, struct hostent *result, const std::string &hostname, const Callback &callback); - void onSockCreate(int sockfd, int type); - void onSockStateChange(int sockfd, bool read, bool write); - - static void ares_hostcallback_(void *data, int status, int timeouts, struct hostent *hostent); - -#ifdef _WIN32 - static int ares_sock_createcallback_(SOCKET sockfd, int type, void *data); -#else - static int ares_sock_createcallback_(int sockfd, int type, void *data); -#endif - static void ares_sock_statecallback_(void *data, -#ifdef _WIN32 - SOCKET sockfd, -#else - int sockfd, -#endif - int read, - int write); - - struct LibraryInitializer { - LibraryInitializer(); - ~LibraryInitializer(); - }; - - static LibraryInitializer libraryInitializer_; -}; diff --git a/core/net/resolvers/normal_resolver.h b/core/net/resolvers/normal_resolver.h deleted file mode 100644 index 5d3265e..0000000 --- a/core/net/resolvers/normal_resolver.h +++ /dev/null @@ -1,80 +0,0 @@ - -// This file is originally from Trantor - NormalResolver.h - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once -#include "core/containers/concurrent_task_queue.h" -#include "core/net/resolver.h" -#include -#include -#include - -//Resolver will be a ref - -constexpr size_t kResolveBufferLength{ 16 * 1024 }; - -class NormalResolver : public Resolver, public std::enable_shared_from_this { - -protected: - NormalResolver(const NormalResolver &) = delete; - NormalResolver &operator=(const NormalResolver &) = delete; - // some uncopyable classes maybe support move constructor.... - NormalResolver(NormalResolver &&) noexcept(true) = default; - NormalResolver &operator=(NormalResolver &&) noexcept(true) = default; - -public: - virtual void resolve(const std::string &hostname, - const Callback &callback) override; - explicit NormalResolver(size_t timeout) : - timeout_(timeout), resolveBuffer_(kResolveBufferLength) { - } - virtual ~NormalResolver() { - } - -private: - static std::unordered_map > &globalCache() { - static std::unordered_map > dnsCache_; - return dnsCache_; - } - - static std::mutex &globalMutex() { - static std::mutex mutex_; - return mutex_; - } - - static ConcurrentTaskQueue &concurrentTaskQueue() { - static ConcurrentTaskQueue queue( - std::thread::hardware_concurrency() < 8 ? 8 : std::thread::hardware_concurrency(), - "Dns Queue"); - return queue; - } - - const size_t timeout_; - std::vector resolveBuffer_; -}; diff --git a/core/net/socket.h b/core/net/socket.h deleted file mode 100644 index c926e3b..0000000 --- a/core/net/socket.h +++ /dev/null @@ -1,166 +0,0 @@ - -// This file is originally from Trantor - Socket.h - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// TODO Re enable logging - -#pragma once - -#include "core/log/logger.h" -#include "core/net/inet_address.h" -#include -#ifndef _WIN32 -#include -#endif -#include - -class Socket { -protected: - Socket(const Socket &) = delete; - Socket &operator=(const Socket &) = delete; - // some uncopyable classes maybe support move constructor.... - Socket(Socket &&) noexcept(true) = default; - Socket &operator=(Socket &&) noexcept(true) = default; - -public: - static int createNonblockingSocketOrDie(int family) { -#ifdef __linux__ - int sock = ::socket(family, - SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, - IPPROTO_TCP); -#else - int sock = static_cast(::socket(family, SOCK_STREAM, IPPROTO_TCP)); - setNonBlockAndCloseOnExec(sock); -#endif - if (sock < 0) { - LOG_SYSERR << "sockets::createNonblockingOrDie"; - exit(1); - } - - LOG_TRACE << "sock=" << sock; - return sock; - } - - static int getSocketError(int sockfd) { - int optval; - socklen_t optlen = static_cast(sizeof optval); -#ifdef _WIN32 - if (::getsockopt( - sockfd, SOL_SOCKET, SO_ERROR, (char *)&optval, &optlen) < 0) -#else - if (::getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) < 0) -#endif - { - return errno; - } else { - return optval; - } - } - - static int connect(int sockfd, const InetAddress &addr) { - if (addr.isIpV6()) - return ::connect(sockfd, addr.getSockAddr(), static_cast(sizeof(struct sockaddr_in6))); - else - return ::connect(sockfd, addr.getSockAddr(), static_cast(sizeof(struct sockaddr_in))); - } - - static bool isSelfConnect(int sockfd); - - explicit Socket(int sockfd) : - sockFd_(sockfd) { - } - - ~Socket(); - - /// abort if address in use - void bindAddress(const InetAddress &localaddr); - /// abort if address in use - void listen(); - int accept(InetAddress *peeraddr); - void closeWrite(); - int read(char *buffer, uint64_t len); - - int fd() { - return sockFd_; - } - - static struct sockaddr_in6 getLocalAddr(int sockfd); - static struct sockaddr_in6 getPeerAddr(int sockfd); - - /// - /// Enable/disable TCP_NODELAY (disable/enable Nagle's algorithm). - /// - void setTcpNoDelay(bool on); - - /// - /// Enable/disable SO_REUSEADDR - /// - void setReuseAddr(bool on); - - /// - /// Enable/disable SO_REUSEPORT - /// - void setReusePort(bool on); - - /// - /// Enable/disable SO_KEEPALIVE - /// - void setKeepAlive(bool on); - int getSocketError(); - -protected: - int sockFd_; - -public: - // taken from muduo - static void setNonBlockAndCloseOnExec(int sockfd) { -#ifdef _WIN32 - // TODO how to set FD_CLOEXEC on windows? is it necessary? - u_long arg = 1; - auto ret = ioctlsocket(sockfd, (long)FIONBIO, &arg); - if (ret) { - LOG_ERROR << "ioctlsocket error"; - } -#else - // non-block - int flags = ::fcntl(sockfd, F_GETFL, 0); - flags |= O_NONBLOCK; - int ret = ::fcntl(sockfd, F_SETFL, flags); - // TODO check - - // close-on-exec - flags = ::fcntl(sockfd, F_GETFD, 0); - flags |= FD_CLOEXEC; - ret = ::fcntl(sockfd, F_SETFD, flags); - // TODO check - - (void)ret; -#endif - } -}; diff --git a/core/net/tcp_client.h b/core/net/tcp_client.h deleted file mode 100644 index 20ab994..0000000 --- a/core/net/tcp_client.h +++ /dev/null @@ -1,162 +0,0 @@ - -// This file is originally from Moduo -> Trantor - TcpClient.h - -// Copyright (c) 2016-2021, Tao An. All rights reserved. -// Copyright 2010, Shuo Chen. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include "core/loops/event_loop.h" -#include "core/net/inet_address.h" -#include "tcp_connection.h" -#include -#include -#include -#include - -class Connector; -using ConnectorPtr = std::shared_ptr; -class SSLContext; - -//maybe: -//Reference -> Socket -> ConnectionListener (Channel?) -> Connector (ClientSocket) -> TcpClient -> HTTP... -// -> Acceptor (ServerSocket) -> TcpServer -> HTTPServer -//Reference -> TcpConnection (with a connectionlistener member) -> TcpConnectionDefault -//Also todo move around the core net classes a bit more - - -//should be ConnectionListener derived -//Inherit from Connector (which Could be called ClientSocket)? - -class TcpClient { -protected: - TcpClient(const TcpClient &) = delete; - TcpClient &operator=(const TcpClient &) = delete; - // some uncopyable classes maybe support move constructor.... - TcpClient(TcpClient &&) noexcept(true) = default; - TcpClient &operator=(TcpClient &&) noexcept(true) = default; - -public: - TcpClient(EventLoop *loop, const InetAddress &serverAddr, const std::string &nameArg); - ~TcpClient(); - - void connect(); - void disconnect(); - - void stop(); - - TcpConnectionPtr connection() const { - std::lock_guard lock(mutex_); - return connection_; - } - - EventLoop *getLoop() const { - return loop_; - } - - bool retry() const { - return retry_; - } - - void enableRetry() { - retry_ = true; - } - - const std::string &name() const { - return name_; - } - - void setConnectionCallback(const ConnectionCallback &cb) { - connectionCallback_ = cb; - } - void setConnectionCallback(ConnectionCallback &&cb) { - connectionCallback_ = std::move(cb); - } - - void setConnectionErrorCallback(const ConnectionErrorCallback &cb) { - connectionErrorCallback_ = cb; - } - - void setMessageCallback(const RecvMessageCallback &cb) { - messageCallback_ = cb; - } - void setMessageCallback(RecvMessageCallback &&cb) { - messageCallback_ = std::move(cb); - } - - /// Not thread safe. - void setWriteCompleteCallback(const WriteCompleteCallback &cb) { - writeCompleteCallback_ = cb; - } - void setWriteCompleteCallback(WriteCompleteCallback &&cb) { - writeCompleteCallback_ = std::move(cb); - } - - void setSSLErrorCallback(const SSLErrorCallback &cb) { - sslErrorCallback_ = cb; - } - void setSSLErrorCallback(SSLErrorCallback &&cb) { - sslErrorCallback_ = std::move(cb); - } - - void enableSSL(bool useOldTLS = false, bool validateCert = true, std::string hostname = "", const std::vector > &sslConfCmds = {}); - -private: - /// Not thread safe, but in loop - void newConnection(int sockfd); - /// Not thread safe, but in loop - void removeConnection(const TcpConnectionPtr &conn); - - EventLoop *loop_; - ConnectorPtr connector_; // avoid revealing Connector - const std::string name_; - ConnectionCallback connectionCallback_; - ConnectionErrorCallback connectionErrorCallback_; - RecvMessageCallback messageCallback_; - WriteCompleteCallback writeCompleteCallback_; - SSLErrorCallback sslErrorCallback_; - std::atomic_bool retry_; // atomic - std::atomic_bool connect_; // atomic - // always in loop thread - mutable std::mutex mutex_; - TcpConnectionPtr connection_; // @GuardedBy mutex_ - std::shared_ptr sslCtxPtr_; - bool validateCert_{ false }; - std::string SSLHostName_; - -#ifndef _WIN32 - class IgnoreSigPipe { - public: - IgnoreSigPipe() { - ::signal(SIGPIPE, SIG_IGN); - } - }; - - static IgnoreSigPipe initObj; -#endif -}; diff --git a/core/net/tcp_connection.h b/core/net/tcp_connection.h deleted file mode 100644 index 91352f5..0000000 --- a/core/net/tcp_connection.h +++ /dev/null @@ -1,121 +0,0 @@ - -// This file is originally from Trantor - TcpConnection.h - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include "core/containers/msg_buffer.h" -#include "core/net/callbacks.h" -#include "core/loops/event_loop.h" -#include "core/net/inet_address.h" -#include -#include -#include - -// add new class TcpConnectionListener or ConnectionListener -//set_listener(ConnectionListener) -// instead of callbacks - -class SSLContext; -std::shared_ptr newSSLServerContext(const std::string &certPath, const std::string &keyPath, bool useOldTLS = false, const std::vector > &sslConfCmds = {}); - -class TcpConnection { -public: - TcpConnection() = default; - virtual ~TcpConnection(){}; - - virtual void send(const char *msg, size_t len) = 0; - virtual void send(const void *msg, size_t len) = 0; - virtual void send(const std::string &msg) = 0; - virtual void send(std::string &&msg) = 0; - virtual void send(const MsgBuffer &buffer) = 0; - virtual void send(MsgBuffer &&buffer) = 0; - virtual void send(const std::shared_ptr &msgPtr) = 0; - virtual void send(const std::shared_ptr &msgPtr) = 0; - - virtual void sendFile(const char *fileName, size_t offset = 0, size_t length = 0) = 0; - - virtual const InetAddress &localAddr() const = 0; - virtual const InetAddress &peerAddr() const = 0; - - virtual bool connected() const = 0; - virtual bool disconnected() const = 0; - - virtual MsgBuffer *getRecvBuffer() = 0; - - - virtual void setHighWaterMarkCallback(const HighWaterMarkCallback &cb, size_t markLen) = 0; - - virtual void setTcpNoDelay(bool on) = 0; - - virtual void shutdown() = 0; - virtual void forceClose() = 0; - - - virtual EventLoop *getLoop() = 0; - - void setContext(const std::shared_ptr &context) { - contextPtr_ = context; - } - void setContext(std::shared_ptr &&context) { - contextPtr_ = std::move(context); - } - - template - std::shared_ptr getContext() const { - return std::static_pointer_cast(contextPtr_); - } - - bool hasContext() const { - return (bool)contextPtr_; - } - - void clearContext() { - contextPtr_.reset(); - } - - virtual void keepAlive() = 0; - virtual bool isKeepAlive() = 0; - - virtual size_t bytesSent() const = 0; - virtual size_t bytesReceived() const = 0; - - virtual bool isSSLConnection() const = 0; - - virtual void startClientEncryption(std::function callback, bool useOldTLS = false, bool validateCert = true, std::string hostname = "", const std::vector > &sslConfCmds = {}) = 0; - - virtual void startServerEncryption(const std::shared_ptr &ctx, std::function callback) = 0; - -protected: - bool validateCert_ = false; - -private: - std::shared_ptr contextPtr_; -}; - diff --git a/core/net/tcp_server.h b/core/net/tcp_server.h deleted file mode 100644 index 8c43ef5..0000000 --- a/core/net/tcp_server.h +++ /dev/null @@ -1,161 +0,0 @@ - -// This file is originally from Trantor - TcpServer.h - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include "core/log/logger.h" -#include "core/net/callbacks.h" -#include "core/loops/event_loop_thread_pool.h" -#include "core/loops/timing_wheel.h" -#include "core/net/inet_address.h" -#include "core/net/tcp_connection.h" -#include -#include -#include -#include - -class Acceptor; -class SSLContext; - -//Inherit from Acceptor (-> Could be called ServerSocket)? - -class TcpServer { -protected: - TcpServer(const TcpServer &) = delete; - TcpServer &operator=(const TcpServer &) = delete; - // some uncopyable classes maybe support move constructor.... - TcpServer(TcpServer &&) noexcept(true) = default; - TcpServer &operator=(TcpServer &&) noexcept(true) = default; - -public: - TcpServer(EventLoop *loop, const InetAddress &address, const std::string &name, bool reUseAddr = true, bool reUsePort = true); - ~TcpServer(); - - void start(); - void stop(); - - void setIoLoopNum(size_t num) { - assert(!started_); - loopPoolPtr_ = std::make_shared(num); - loopPoolPtr_->start(); - } - - void setIoLoopThreadPool(const std::shared_ptr &pool) { - assert(pool->size() > 0); - assert(!started_); - loopPoolPtr_ = pool; - loopPoolPtr_->start(); - } - - void setRecvMessageCallback(const RecvMessageCallback &cb) { - recvMessageCallback_ = cb; - } - void setRecvMessageCallback(RecvMessageCallback &&cb) { - recvMessageCallback_ = std::move(cb); - } - - void setConnectionCallback(const ConnectionCallback &cb) { - connectionCallback_ = cb; - } - void setConnectionCallback(ConnectionCallback &&cb) { - connectionCallback_ = std::move(cb); - } - - void setWriteCompleteCallback(const WriteCompleteCallback &cb) { - writeCompleteCallback_ = cb; - } - void setWriteCompleteCallback(WriteCompleteCallback &&cb) { - writeCompleteCallback_ = std::move(cb); - } - - const std::string &name() const { - return serverName_; - } - - const std::string ipPort() const; - const InetAddress &address() const; - - EventLoop *getLoop() const { - return loop_; - } - - std::vector getIoLoops() const { - return loopPoolPtr_->getLoops(); - } - - void kickoffIdleConnections(size_t timeout) { - loop_->runInLoop([this, timeout]() { - assert(!started_); - idleTimeout_ = timeout; - }); - } - - // certPath The path of the certificate file. - // keyPath The path of the private key file. - // useOldTLS If true, the TLS 1.0 and 1.1 are supported by the server. - // sslConfCmds The commands used to call the SSL_CONF_cmd function in OpenSSL. - // Note: It's well known that TLS 1.0 and 1.1 are not considered secure in 2020. And it's a good practice to only use TLS 1.2 and above. - void enableSSL(const std::string &certPath, const std::string &keyPath, bool useOldTLS = false, const std::vector > &sslConfCmds = {}); - -private: - EventLoop *loop_; - std::unique_ptr acceptorPtr_; - - void newConnection(int fd, const InetAddress &peer); - - std::string serverName_; - std::set connSet_; - - RecvMessageCallback recvMessageCallback_; - ConnectionCallback connectionCallback_; - WriteCompleteCallback writeCompleteCallback_; - - size_t idleTimeout_{ 0 }; - std::map > timingWheelMap_; - void connectionClosed(const TcpConnectionPtr &connectionPtr); - std::shared_ptr loopPoolPtr_; - -#ifndef _WIN32 - class IgnoreSigPipe { - public: - IgnoreSigPipe() { - ::signal(SIGPIPE, SIG_IGN); - LOG_TRACE << "Ignore SIGPIPE"; - } - }; - - IgnoreSigPipe initObj; -#endif - - bool started_{ false }; - - // OpenSSL SSL context Object; - std::shared_ptr sslCtxPtr_; -}; diff --git a/core/polling/poller.cpp b/core/polling/poller.cpp deleted file mode 100644 index 6512d1b..0000000 --- a/core/polling/poller.cpp +++ /dev/null @@ -1,49 +0,0 @@ - -// This file is originally from Trantor - Poller.cc - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "poller.h" - -#ifdef __linux__ -#include "poller/epoll_poller.h" -#elif defined _WIN32 -#include "Wepoll.h" -#include "poller/epoll_poller.h" -#else -#include "poller/kqueue.h" -#endif - - -Poller *Poller::newPoller(EventLoop *loop) { -#if defined __linux__ || defined _WIN32 - return new EpollPoller(loop); -#else - return new KQueue(loop); -#endif -} diff --git a/core/polling/poller.h b/core/polling/poller.h deleted file mode 100644 index 6963b6a..0000000 --- a/core/polling/poller.h +++ /dev/null @@ -1,71 +0,0 @@ - -// This file is originally from Trantor - Poller.h - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include "core/loops/event_loop.h" - -#include -#include - -class Channel; -#ifdef _WIN32 -using EventCallback = std::function; -#endif -class Poller { -protected: - Poller(const Poller &) = delete; - Poller &operator=(const Poller &) = delete; - // some uncopyable classes maybe support move constructor.... - Poller(Poller &&) noexcept(true) = default; - Poller &operator=(Poller &&) noexcept(true) = default; - -public: - explicit Poller(EventLoop *loop) : - ownerLoop_(loop){}; - virtual ~Poller() { - } - void assertInLoopThread() { - ownerLoop_->assertInLoopThread(); - } - virtual void poll(int timeoutMs, ChannelList *activeChannels) = 0; - virtual void updateChannel(Channel *channel) = 0; - virtual void removeChannel(Channel *channel) = 0; -#ifdef _WIN32 - virtual void postEvent(uint64_t event) = 0; - virtual void setEventCallback(const EventCallback &cb) = 0; -#endif - virtual void resetAfterFork() { - } - static Poller *newPoller(EventLoop *loop); - -private: - EventLoop *ownerLoop_; -}; diff --git a/core/polling/poller/epoll_poller.h b/core/polling/poller/epoll_poller.h deleted file mode 100644 index c4d05ff..0000000 --- a/core/polling/poller/epoll_poller.h +++ /dev/null @@ -1,75 +0,0 @@ - -// This file is originally from Trantor - EpollPoller.h - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include "core/loops/event_loop.h" -#include "core/polling/poller.h" - -#if defined __linux__ || defined _WIN32 -#include -#include -using EventList = std::vector; -#endif - -class Channel; - -class EpollPoller : public Poller { -public: - explicit EpollPoller(EventLoop *loop); - virtual ~EpollPoller(); - virtual void poll(int timeoutMs, ChannelList *activeChannels) override; - virtual void updateChannel(Channel *channel) override; - virtual void removeChannel(Channel *channel) override; -#ifdef _WIN32 - virtual void postEvent(uint64_t event) override; - virtual void setEventCallback(const EventCallback &cb) override { - eventCallback_ = cb; - } -#endif - -private: -#if defined __linux__ || defined _WIN32 - static const int kInitEventListSize = 16; -#ifdef _WIN32 - void *epollfd_; - EventCallback eventCallback_{ [](uint64_t event) {} }; -#else - int epollfd_; -#endif - EventList events_; - void update(int operation, Channel *channel); -#ifndef NDEBUG - using ChannelMap = std::map; - ChannelMap channels_; -#endif - void fillActiveChannels(int numEvents, ChannelList *activeChannels) const; -#endif -}; diff --git a/core/polling/poller/kqueue.h b/core/polling/poller/kqueue.h deleted file mode 100644 index 1468a4e..0000000 --- a/core/polling/poller/kqueue.h +++ /dev/null @@ -1,66 +0,0 @@ - -// This file is originally from Trantor - KQueue.h - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once -#include "core/loops/event_loop.h" -#include "core/polling/poller.h" - -#if (defined(__unix__) && !defined(__linux__)) || \ - (defined(__APPLE__) && defined(__MACH__)) -#define USE_KQUEUE -#include -#include -#include -using EventList = std::vector; -#endif - -class Channel; - -class KQueue : public Poller { -public: - explicit KQueue(EventLoop *loop); - virtual ~KQueue(); - virtual void poll(int timeoutMs, ChannelList *activeChannels) override; - virtual void updateChannel(Channel *channel) override; - virtual void removeChannel(Channel *channel) override; - virtual void resetAfterFork() override; - -private: -#ifdef USE_KQUEUE - static const int kInitEventListSize = 16; - int kqfd_; - EventList events_; - using ChannelMap = std::unordered_map >; - ChannelMap channels_; - - void fillActiveChannels(int numEvents, ChannelList *activeChannels) const; - void update(Channel *channel); -#endif -}; diff --git a/core/utilities.h b/core/utilities.h index 6f5b461..14a2415 100644 --- a/core/utilities.h +++ b/core/utilities.h @@ -10,25 +10,6 @@ class Utilities { public: - // Taken from trantor (MIT License) - Funcs.h - // Copyright (c) 2018 An Tao - static _ALWAYS_INLINE_ std::vector splitString(const std::string &s, - const std::string &delimiter, - bool acceptEmptyString = false) { - if (delimiter.empty()) - return std::vector{}; - std::vector v; - size_t last = 0; - size_t next = 0; - while ((next = s.find(delimiter, last)) != std::string::npos) { - if (next > last || acceptEmptyString) - v.push_back(s.substr(last, next - last)); - last = next + delimiter.length(); - } - if (s.length() > last || acceptEmptyString) - v.push_back(s.substr(last)); - return v; - } protected: }; diff --git a/web_backends/drogon/SCsub b/web_backends/drogon/SCsub index 33a87b7..bff34a3 100644 --- a/web_backends/drogon/SCsub +++ b/web_backends/drogon/SCsub @@ -10,6 +10,19 @@ env_mod.add_source_files(env_mod.core_sources, "drogon/lib/src/*.cc") env_mod.add_source_files(env_mod.core_sources, "drogon/lib/inc/http/*.cc") env_mod.add_source_files(env_mod.core_sources, "drogon/lib/src/ssl_funcs/*.cc") +env_mod.add_source_files(env_mod.core_sources, "trantor/net/*.cc") +env_mod.add_source_files(env_mod.core_sources, "trantor/net/inner/*.cc") +env_mod.add_source_files(env_mod.core_sources, "trantor/net/inner/poller/*.cc") + +env_mod.add_source_files(env_mod.core_sources, "trantor/utils/AsyncFileLogger.cc") +env_mod.add_source_files(env_mod.core_sources, "trantor/utils/ConcurrentTaskQueue.cc") +env_mod.add_source_files(env_mod.core_sources, "trantor/utils/Date.cc") +env_mod.add_source_files(env_mod.core_sources, "trantor/utils/Logger.cc") +env_mod.add_source_files(env_mod.core_sources, "trantor/utils/LogStream.cc") +env_mod.add_source_files(env_mod.core_sources, "trantor/utils/MsgBuffer.cc") +env_mod.add_source_files(env_mod.core_sources, "trantor/utils/SerialTaskQueue.cc") +env_mod.add_source_files(env_mod.core_sources, "trantor/utils/TimingWheel.cc") + # Build it all as a library lib = env_mod.add_library("drogon", env_mod.core_sources) env.Prepend(LIBS=[lib]) diff --git a/web_backends/drogon/detect.py b/web_backends/drogon/detect.py index c20cf9e..7ebce55 100644 --- a/web_backends/drogon/detect.py +++ b/web_backends/drogon/detect.py @@ -79,6 +79,8 @@ def configure(env): env.Append(CPPPATH=["#web_backends/drogon"]) env.Append(CPPPATH=["#web_backends/drogon/trantor"]) + env.Append(CPPPATH=["#web_backends/drogon/trantor/net"]) + env.Append(CPPPATH=["#web_backends/drogon/trantor/net/inner"]) env.Append(CPPPATH=["#web_backends/drogon/trantor/utils"]) env.Append(LINKFLAGS=["-ldl"]) diff --git a/web_backends/drogon/drogon/README.md b/web_backends/drogon/drogon/README.md index eb6d839..9e457a8 100755 --- a/web_backends/drogon/drogon/README.md +++ b/web_backends/drogon/drogon/README.md @@ -51,7 +51,7 @@ using namespace drogon; int main() { app().setLogPath("./") - .setLogLevel(Logger::kWarn) + .setLogLevel(trantor::Logger::kWarn) .addListener("0.0.0.0", 80) .setThreadNum(16) .enableRunAsDaemon() diff --git a/web_backends/drogon/drogon/examples/benchmark/main.cc b/web_backends/drogon/drogon/examples/benchmark/main.cc index da5a4c6..5e79fc6 100644 --- a/web_backends/drogon/drogon/examples/benchmark/main.cc +++ b/web_backends/drogon/drogon/examples/benchmark/main.cc @@ -4,7 +4,7 @@ using namespace drogon; int main() { app() .setLogPath("./") - .setLogLevel(Logger::kWarn) + .setLogLevel(trantor::Logger::kWarn) .addListener("0.0.0.0", 7770) .setThreadNum(0) .registerSyncAdvice([](const HttpRequestPtr &req) -> HttpResponsePtr { diff --git a/web_backends/drogon/drogon/examples/client_example/main.cc b/web_backends/drogon/drogon/examples/client_example/main.cc index 916e8a2..3a4bb6a 100644 --- a/web_backends/drogon/drogon/examples/client_example/main.cc +++ b/web_backends/drogon/drogon/examples/client_example/main.cc @@ -7,7 +7,7 @@ using namespace drogon; int nth_resp = 0; int main() { - Logger::setLogLevel(Logger::kTrace); + trantor::Logger::setLogLevel(trantor::Logger::kTrace); { auto client = HttpClient::newHttpClient("http://www.baidu.com"); auto req = HttpRequest::newHttpRequest(); diff --git a/web_backends/drogon/drogon/examples/simple_reverse_proxy/plugins/SimpleReverseProxy.cc b/web_backends/drogon/drogon/examples/simple_reverse_proxy/plugins/SimpleReverseProxy.cc index 27198f1..668a44a 100644 --- a/web_backends/drogon/drogon/examples/simple_reverse_proxy/plugins/SimpleReverseProxy.cc +++ b/web_backends/drogon/drogon/examples/simple_reverse_proxy/plugins/SimpleReverseProxy.cc @@ -64,7 +64,7 @@ void SimpleReverseProxy::preRouting(const HttpRequestPtr &req, if (!clientPtr) { auto &addr = backendAddrs_[index % backendAddrs_.size()]; clientPtr = HttpClient::newHttpClient( - addr, EventLoop::getEventLoopOfCurrentThread()); + addr, trantor::EventLoop::getEventLoopOfCurrentThread()); clientPtr->setPipeliningDepth(pipeliningDepth_); } req->setPassThrough(true); diff --git a/web_backends/drogon/drogon/examples/websocket_client/WebSocketClient.cc b/web_backends/drogon/drogon/examples/websocket_client/WebSocketClient.cc index 812f1cc..9ee67ff 100644 --- a/web_backends/drogon/drogon/examples/websocket_client/WebSocketClient.cc +++ b/web_backends/drogon/drogon/examples/websocket_client/WebSocketClient.cc @@ -68,7 +68,7 @@ int main(int argc, char *argv[]) { // Quit the application after 15 seconds app().getLoop()->runAfter(15, []() { app().quit(); }); - app().setLogLevel(Logger::kDebug); + app().setLogLevel(trantor::Logger::kDebug); app().run(); LOG_INFO << "bye!"; return 0; diff --git a/web_backends/drogon/drogon/lib/inc/drogon/HttpAppFramework.h b/web_backends/drogon/drogon/lib/inc/drogon/HttpAppFramework.h index 811c60a..cbc4d18 100644 --- a/web_backends/drogon/drogon/lib/inc/drogon/HttpAppFramework.h +++ b/web_backends/drogon/drogon/lib/inc/drogon/HttpAppFramework.h @@ -25,8 +25,8 @@ #include #include #include -#include "core/loops/event_loop.h" -#include "core/net/resolver.h" +#include +#include #include #include #include @@ -59,7 +59,7 @@ using DefaultHandler = std::function &&)>; -class HttpAppFramework : public NonCopyable { +class HttpAppFramework : public trantor::NonCopyable { public: virtual ~HttpAppFramework() = default; /// Get the instance of HttpAppFramework @@ -104,7 +104,7 @@ public: * User can run some timer tasks or other tasks in this loop; * This method can be call in any thread. */ - virtual EventLoop *getLoop() const = 0; + virtual trantor::EventLoop *getLoop() const = 0; /// Get an IO loop with id. E.g. 0 <= id < #Total thread-loops /** @@ -114,7 +114,7 @@ public: * REMARKS : Function assumed the number of threads will not exceed 2^32. * Change to long long for alien computers. */ - virtual EventLoop *getIOLoop(size_t id) const = 0; + virtual trantor::EventLoop *getIOLoop(size_t id) const = 0; /// Set custom 404 page /** @@ -191,8 +191,8 @@ public: * Users can use this advice to implement some security policies. */ virtual HttpAppFramework ®isterNewConnectionAdvice( - const std::function &advice) = 0; + const std::function &advice) = 0; /** * @brief Register an advice for new HTTP responses. @@ -878,7 +878,7 @@ public: * @note * This operation can be performed by an option in the configuration file. */ - virtual HttpAppFramework &setLogLevel(Logger::LogLevel level) = 0; + virtual HttpAppFramework &setLogLevel(trantor::Logger::LogLevel level) = 0; /// Enable the sendfile system call in linux. /** @@ -1179,7 +1179,7 @@ public: * When the c-ares library is installed in the system, it runs with the best * performance. */ - virtual const std::shared_ptr &getResolver() const = 0; + virtual const std::shared_ptr &getResolver() const = 0; /// Return true is drogon supports SSL(https) virtual bool supportSSL() const = 0; @@ -1204,11 +1204,11 @@ public: /** * @brief Get the addresses of listeners. * - * @return std::vector + * @return std::vector * @note This method should be called after calling the app().run(). One * could run this method in an AOP join point (such as the BeginningAdvice). */ - virtual std::vector getListeners() const = 0; + virtual std::vector getListeners() const = 0; /** * @brief Enable ReusePort mode or not. If the mode is enabled, one can run diff --git a/web_backends/drogon/drogon/lib/inc/drogon/HttpClient.h b/web_backends/drogon/drogon/lib/inc/drogon/HttpClient.h index b577215..fc86ca4 100644 --- a/web_backends/drogon/drogon/lib/inc/drogon/HttpClient.h +++ b/web_backends/drogon/drogon/lib/inc/drogon/HttpClient.h @@ -19,7 +19,7 @@ #include #include -#include "core/loops/event_loop.h" +#include #include #include #include @@ -42,7 +42,7 @@ using HttpClientPtr = std::shared_ptr; * response callbacks are invoked without fear of accidental deconstruction. * */ -class HttpClient : public NonCopyable { +class HttpClient : public trantor::NonCopyable { public: /** * @brief Send a request asynchronously to the server @@ -178,12 +178,12 @@ public: static HttpClientPtr newHttpClient(const std::string &ip, uint16_t port, bool useSSL = false, - EventLoop *loop = nullptr, + trantor::EventLoop *loop = nullptr, bool useOldTLS = false, bool validateCert = true); /// Get the event loop of the client; - virtual EventLoop *getLoop() = 0; + virtual trantor::EventLoop *getLoop() = 0; /// Get the number of bytes sent or received virtual size_t bytesSent() const = 0; @@ -221,7 +221,7 @@ public: * */ static HttpClientPtr newHttpClient(const std::string &hostString, - EventLoop *loop = nullptr, + trantor::EventLoop *loop = nullptr, bool useOldTLS = false, bool validateCert = true); diff --git a/web_backends/drogon/drogon/lib/inc/drogon/HttpViewData.h b/web_backends/drogon/drogon/lib/inc/drogon/HttpViewData.h index 9c35844..ca2525f 100644 --- a/web_backends/drogon/drogon/lib/inc/drogon/HttpViewData.h +++ b/web_backends/drogon/drogon/lib/inc/drogon/HttpViewData.h @@ -19,8 +19,8 @@ #include #include #include -#include "core/log/logger.h" -#include "core/containers/msg_buffer.h" +#include +#include #include #include #include diff --git a/web_backends/drogon/drogon/lib/inc/drogon/IOThreadStorage.h b/web_backends/drogon/drogon/lib/inc/drogon/IOThreadStorage.h index bb4fc7b..aa79662 100644 --- a/web_backends/drogon/drogon/lib/inc/drogon/IOThreadStorage.h +++ b/web_backends/drogon/drogon/lib/inc/drogon/IOThreadStorage.h @@ -56,7 +56,7 @@ namespace drogon { * @endcode */ template -class IOThreadStorage : public NonCopyable { +class IOThreadStorage : public trantor::NonCopyable { public: using ValueType = C; using InitCallback = std::function; diff --git a/web_backends/drogon/drogon/lib/inc/drogon/WebSocketClient.h b/web_backends/drogon/drogon/lib/inc/drogon/WebSocketClient.h index a5d93cb..eccd530 100644 --- a/web_backends/drogon/drogon/lib/inc/drogon/WebSocketClient.h +++ b/web_backends/drogon/drogon/lib/inc/drogon/WebSocketClient.h @@ -18,7 +18,7 @@ #include #include #include -#include "core/loops/event_loop.h" +#include #include #include #include @@ -66,7 +66,7 @@ public: const WebSocketRequestCallback &callback) = 0; /// Get the event loop of the client; - virtual EventLoop *getLoop() = 0; + virtual trantor::EventLoop *getLoop() = 0; /** * @brief Create a websocket client using the given ip and port to connect @@ -91,7 +91,7 @@ public: const std::string &ip, uint16_t port, bool useSSL = false, - EventLoop *loop = nullptr, + trantor::EventLoop *loop = nullptr, bool useOldTLS = false, bool validateCert = true); @@ -121,7 +121,7 @@ public: */ static WebSocketClientPtr newWebSocketClient( const std::string &hostString, - EventLoop *loop = nullptr, + trantor::EventLoop *loop = nullptr, bool useOldTLS = false, bool validateCert = true); diff --git a/web_backends/drogon/drogon/lib/inc/drogon/WebSocketConnection.h b/web_backends/drogon/drogon/lib/inc/drogon/WebSocketConnection.h index 5ef00a8..ebcbf38 100644 --- a/web_backends/drogon/drogon/lib/inc/drogon/WebSocketConnection.h +++ b/web_backends/drogon/drogon/lib/inc/drogon/WebSocketConnection.h @@ -15,7 +15,7 @@ #pragma once #include -#include "core/net/inet_address.h" +#include #include #include #include @@ -111,10 +111,10 @@ public: const WebSocketMessageType type = WebSocketMessageType::Text) = 0; /// Return the local IP address and port number of the connection - virtual const InetAddress &localAddr() const = 0; + virtual const trantor::InetAddress &localAddr() const = 0; /// Return the remote IP address and port number of the connection - virtual const InetAddress &peerAddr() const = 0; + virtual const trantor::InetAddress &peerAddr() const = 0; /// Return true if the connection is open virtual bool connected() const = 0; diff --git a/web_backends/drogon/drogon/lib/inc/drogon/drogon.h b/web_backends/drogon/drogon/lib/inc/drogon/drogon.h index e8a0d75..5fff366 100644 --- a/web_backends/drogon/drogon/lib/inc/drogon/drogon.h +++ b/web_backends/drogon/drogon/lib/inc/drogon/drogon.h @@ -14,10 +14,10 @@ #pragma once -#include "core/loops/event_loop.h" -#include "core/net/inet_address.h" -#include "core/math/date.h" -#include "core/log/logger.h" +#include +#include +#include +#include #include #include diff --git a/web_backends/drogon/drogon/lib/inc/drogon/drogon_test.h b/web_backends/drogon/drogon/lib/inc/drogon/drogon_test.h index 2c764aa..08df9d6 100644 --- a/web_backends/drogon/drogon/lib/inc/drogon/drogon_test.h +++ b/web_backends/drogon/drogon/lib/inc/drogon/drogon_test.h @@ -318,7 +318,7 @@ inline ThreadSafeStream printErr() { return ThreadSafeStream(std::cerr); } -class CaseBase : public NonCopyable { +class CaseBase : public trantor::NonCopyable { public: CaseBase() = default; CaseBase(const std::string &name) : diff --git a/web_backends/drogon/drogon/lib/inc/drogon/plugins/AccessLogger.h b/web_backends/drogon/drogon/lib/inc/drogon/plugins/AccessLogger.h index 6ba1090..38e3c5a 100644 --- a/web_backends/drogon/drogon/lib/inc/drogon/plugins/AccessLogger.h +++ b/web_backends/drogon/drogon/lib/inc/drogon/plugins/AccessLogger.h @@ -9,7 +9,7 @@ #include #include #include -#include "core/log/async_file_logger.h" +#include #include namespace drogon { @@ -84,89 +84,89 @@ public: void shutdown() override; private: - AsyncFileLogger asyncFileLogger_; + trantor::AsyncFileLogger asyncFileLogger_; int logIndex_{ 0 }; bool useLocalTime_{ true }; - using LogFunction = std::function; std::vector logFunctions_; - void logging(LogStream &stream, + void logging(trantor::LogStream &stream, const drogon::HttpRequestPtr &req, const drogon::HttpResponsePtr &resp); void createLogFunctions(std::string format); LogFunction newLogFunction(const std::string &placeholder); std::map logFunctionMap_; //$request_path - static void outputReqPath(LogStream &, + static void outputReqPath(trantor::LogStream &, const drogon::HttpRequestPtr &, const drogon::HttpResponsePtr &); //$request_query - static void outputReqQuery(LogStream &, + static void outputReqQuery(trantor::LogStream &, const drogon::HttpRequestPtr &, const drogon::HttpResponsePtr &); //$request_url - static void outputReqURL(LogStream &, + static void outputReqURL(trantor::LogStream &, const drogon::HttpRequestPtr &, const drogon::HttpResponsePtr &); //$date - void outputDate(LogStream &, + void outputDate(trantor::LogStream &, const drogon::HttpRequestPtr &, const drogon::HttpResponsePtr &) const; //$request_date - void outputReqDate(LogStream &, + void outputReqDate(trantor::LogStream &, const drogon::HttpRequestPtr &, const drogon::HttpResponsePtr &) const; //$remote_addr - static void outputRemoteAddr(LogStream &, + static void outputRemoteAddr(trantor::LogStream &, const drogon::HttpRequestPtr &, const drogon::HttpResponsePtr &); //$local_addr - static void outputLocalAddr(LogStream &, + static void outputLocalAddr(trantor::LogStream &, const drogon::HttpRequestPtr &, const drogon::HttpResponsePtr &); //$request_len $body_bytes_received - static void outputReqLength(LogStream &, + static void outputReqLength(trantor::LogStream &, const drogon::HttpRequestPtr &, const drogon::HttpResponsePtr &); //$response_len $body_bytes_sent - static void outputRespLength(LogStream &, + static void outputRespLength(trantor::LogStream &, const drogon::HttpRequestPtr &, const drogon::HttpResponsePtr &); //$method - static void outputMethod(LogStream &, + static void outputMethod(trantor::LogStream &, const drogon::HttpRequestPtr &, const drogon::HttpResponsePtr &); //$thread - static void outputThreadNumber(LogStream &, + static void outputThreadNumber(trantor::LogStream &, const drogon::HttpRequestPtr &, const drogon::HttpResponsePtr &); //$http_[header_name] - static void outputReqHeader(LogStream &stream, + static void outputReqHeader(trantor::LogStream &stream, const drogon::HttpRequestPtr &req, const std::string &headerName); //$cookie_[cookie_name] - static void outputReqCookie(LogStream &stream, + static void outputReqCookie(trantor::LogStream &stream, const drogon::HttpRequestPtr &req, const std::string &cookie); //$upstream_http_[header_name] - static void outputRespHeader(LogStream &stream, + static void outputRespHeader(trantor::LogStream &stream, const drogon::HttpResponsePtr &resp, const std::string &headerName); //$status - static void outputStatusString(LogStream &, + static void outputStatusString(trantor::LogStream &, const drogon::HttpRequestPtr &, const drogon::HttpResponsePtr &); //$status_code - static void outputStatusCode(LogStream &, + static void outputStatusCode(trantor::LogStream &, const drogon::HttpRequestPtr &, const drogon::HttpResponsePtr &); //$processing_time - static void outputProcessingTime(LogStream &, + static void outputProcessingTime(trantor::LogStream &, const drogon::HttpRequestPtr &, const drogon::HttpResponsePtr &); //$upstream_http_content-type $upstream_http_content_type - static void outputRespContentType(LogStream &, + static void outputRespContentType(trantor::LogStream &, const drogon::HttpRequestPtr &, const drogon::HttpResponsePtr &); }; diff --git a/web_backends/drogon/drogon/lib/inc/drogon/plugins/Plugin.h b/web_backends/drogon/drogon/lib/inc/drogon/plugins/Plugin.h index 2bbab01..50c43c9 100644 --- a/web_backends/drogon/drogon/lib/inc/drogon/plugins/Plugin.h +++ b/web_backends/drogon/drogon/lib/inc/drogon/plugins/Plugin.h @@ -14,7 +14,7 @@ #pragma once #include -#include "core/log/logger.h" +#include #include #include @@ -29,7 +29,7 @@ enum class PluginStatus { * @brief The abstract base class for plugins. * */ -class PluginBase : public NonCopyable { +class PluginBase : public trantor::NonCopyable { public: /// This method must be called by drogon. void initialize() { diff --git a/web_backends/drogon/drogon/lib/inc/drogon/utils/Utilities.h b/web_backends/drogon/drogon/lib/inc/drogon/utils/Utilities.h index df6c08a..22bebe8 100644 --- a/web_backends/drogon/drogon/lib/inc/drogon/utils/Utilities.h +++ b/web_backends/drogon/drogon/lib/inc/drogon/utils/Utilities.h @@ -16,8 +16,8 @@ #include -#include "core/math/date.h" -#include "core/utilities.h" +#include +#include #include #include #include @@ -60,7 +60,7 @@ std::vector hexToBinaryVector(const char *ptr, inline std::vector splitString(const std::string &str, const std::string &separator, bool acceptEmptyString = false) { - return Utilities::splitString(str, separator, acceptEmptyString); + return trantor::splitString(str, separator, acceptEmptyString); } std::set splitStringToSet( @@ -131,13 +131,13 @@ std::string brotliDecompress(const char *data, @endcode */ char *getHttpFullDate( - const Date &date = Date::now()); + const trantor::Date &date = trantor::Date::now()); -/// Get the Date object according to the http full date string +/// Get the trantor::Date object according to the http full date string /** - * Returns Date(std::numeric_limits::max()) upon failure. + * Returns trantor::Date(std::numeric_limits::max()) upon failure. */ -Date getHttpDate(const std::string &httpFullDateString); +trantor::Date getHttpDate(const std::string &httpFullDateString); /// Get a formatted string std::string formattedString(const char *format, ...); diff --git a/web_backends/drogon/drogon/lib/inc/drogon/utils/string_view.h b/web_backends/drogon/drogon/lib/inc/drogon/utils/string_view.h index 2f46786..159a958 100644 --- a/web_backends/drogon/drogon/lib/inc/drogon/utils/string_view.h +++ b/web_backends/drogon/drogon/lib/inc/drogon/utils/string_view.h @@ -20,7 +20,7 @@ #include #endif -#include "core/log/log_stream.h" +#include namespace drogon { #if __cplusplus >= 201703L || (defined _MSC_VER && _MSC_VER > 1900) @@ -29,11 +29,12 @@ using std::string_view; using boost::string_view; #endif } // namespace drogon - +namespace trantor { inline LogStream &operator<<(LogStream &ls, const drogon::string_view &v) { ls.append(v.data(), v.length()); return ls; } +} // namespace trantor #if __cplusplus < 201703L && !(defined _MSC_VER && _MSC_VER > 1900) namespace std { diff --git a/web_backends/drogon/drogon/lib/inc/http/Attribute.h b/web_backends/drogon/drogon/lib/inc/http/Attribute.h index 06b48f7..d9908f0 100644 --- a/web_backends/drogon/drogon/lib/inc/http/Attribute.h +++ b/web_backends/drogon/drogon/lib/inc/http/Attribute.h @@ -15,7 +15,7 @@ #pragma once #include -#include "core/log/logger.h" +#include #include #include diff --git a/web_backends/drogon/drogon/lib/inc/http/CacheFile.cc b/web_backends/drogon/drogon/lib/inc/http/CacheFile.cc index adb02de..ebb0516 100644 --- a/web_backends/drogon/drogon/lib/inc/http/CacheFile.cc +++ b/web_backends/drogon/drogon/lib/inc/http/CacheFile.cc @@ -13,7 +13,7 @@ */ #include "CacheFile.h" -#include "core/log/logger.h" +#include #ifdef _WIN32 #include #else diff --git a/web_backends/drogon/drogon/lib/inc/http/CacheFile.h b/web_backends/drogon/drogon/lib/inc/http/CacheFile.h index 09777e4..c97f58a 100644 --- a/web_backends/drogon/drogon/lib/inc/http/CacheFile.h +++ b/web_backends/drogon/drogon/lib/inc/http/CacheFile.h @@ -20,7 +20,7 @@ #include namespace drogon { -class CacheFile : public NonCopyable { +class CacheFile : public trantor::NonCopyable { public: explicit CacheFile(const std::string &path, bool autoDelete = true); ~CacheFile(); diff --git a/web_backends/drogon/drogon/lib/inc/http/CacheMap.h b/web_backends/drogon/drogon/lib/inc/http/CacheMap.h index 6188dad..cd7cef1 100644 --- a/web_backends/drogon/drogon/lib/inc/http/CacheMap.h +++ b/web_backends/drogon/drogon/lib/inc/http/CacheMap.h @@ -15,8 +15,8 @@ #pragma once #include -#include "core/loops/event_loop.h" -#include "core/log/logger.h" +#include +#include #include #include #include @@ -79,7 +79,7 @@ public: * The max delay of the CacheMap is about * tickInterval*(bucketsNumPerWheel^wheelsNum) seconds. */ - CacheMap(EventLoop *loop, + CacheMap(trantor::EventLoop *loop, float tickInterval = TICK_INTERVAL, size_t wheelsNum = WHEELS_NUM, size_t bucketsNumPerWheel = BUCKET_NUM_PER_WHEEL) : @@ -134,7 +134,7 @@ public: for (auto iter = wheels_.rbegin(); iter != wheels_.rend(); ++iter) { iter->clear(); } - //LOG_TRACE << "CacheMap destruct!"; + LOG_TRACE << "CacheMap destruct!"; } struct MapValue { MapValue(const T2 &value, @@ -327,9 +327,9 @@ public: /** * @brief Get the event loop object * - * @return EventLoop* + * @return trantor::EventLoop* */ - EventLoop *getLoop() { + trantor::EventLoop *getLoop() { return loop_; } @@ -377,8 +377,8 @@ private: std::mutex mtx_; std::mutex bucketMutex_; - TimerId timerId_; - EventLoop *loop_; + trantor::TimerId timerId_; + trantor::EventLoop *loop_; float tickInterval_; size_t wheelsNumber_; diff --git a/web_backends/drogon/drogon/lib/inc/http/Cookie.h b/web_backends/drogon/drogon/lib/inc/http/Cookie.h index 91df80c..4e82e4f 100644 --- a/web_backends/drogon/drogon/lib/inc/http/Cookie.h +++ b/web_backends/drogon/drogon/lib/inc/http/Cookie.h @@ -14,7 +14,7 @@ #pragma once -#include "core/math/date.h" +#include #include #include @@ -42,7 +42,7 @@ public: * * @param date The expiration date */ - void setExpiresDate(const Date &date) { + void setExpiresDate(const trantor::Date &date) { expiresDate_ = date; } @@ -114,14 +114,14 @@ public: /** * @brief Get the expiration date of the cookie */ - const Date &expiresDate() const { + const trantor::Date &expiresDate() const { return expiresDate_; } /** * @brief Get the expiration date of the cookie */ - const Date &getExpiresDate() const { + const trantor::Date &getExpiresDate() const { return expiresDate_; } @@ -212,7 +212,7 @@ public: } private: - Date expiresDate_{ (std::numeric_limits::max)() }; + trantor::Date expiresDate_{ (std::numeric_limits::max)() }; bool httpOnly_{ true }; bool secure_{ false }; std::string domain_; diff --git a/web_backends/drogon/drogon/lib/inc/http/HttpRequest.h b/web_backends/drogon/drogon/lib/inc/http/HttpRequest.h index 6538da4..b336ac5 100644 --- a/web_backends/drogon/drogon/lib/inc/http/HttpRequest.h +++ b/web_backends/drogon/drogon/lib/inc/http/HttpRequest.h @@ -21,8 +21,8 @@ #include #include -#include "core/net/inet_address.h" -#include "core/math/date.h" +#include +#include #include #include #include @@ -248,20 +248,20 @@ public: virtual const std::string &getParameter(const std::string &key) const = 0; /// Return the remote IP address and port - virtual const InetAddress &peerAddr() const = 0; - const InetAddress &getPeerAddr() const { + virtual const trantor::InetAddress &peerAddr() const = 0; + const trantor::InetAddress &getPeerAddr() const { return peerAddr(); } /// Return the local IP address and port - virtual const InetAddress &localAddr() const = 0; - const InetAddress &getLocalAddr() const { + virtual const trantor::InetAddress &localAddr() const = 0; + const trantor::InetAddress &getLocalAddr() const { return localAddr(); } /// Return the creation timestamp set by the framework. - virtual const Date &creationDate() const = 0; - const Date &getCreationDate() const { + virtual const trantor::Date &creationDate() const = 0; + const trantor::Date &getCreationDate() const { return creationDate(); } diff --git a/web_backends/drogon/drogon/lib/inc/http/HttpRequestImpl.cc b/web_backends/drogon/drogon/lib/inc/http/HttpRequestImpl.cc index fcadf45..43c9076 100644 --- a/web_backends/drogon/drogon/lib/inc/http/HttpRequestImpl.cc +++ b/web_backends/drogon/drogon/lib/inc/http/HttpRequestImpl.cc @@ -143,7 +143,7 @@ void HttpRequestImpl::parseParameters() const { } } -void HttpRequestImpl::appendToBuffer(MsgBuffer *output) const { +void HttpRequestImpl::appendToBuffer(trantor::MsgBuffer *output) const { switch (method_) { case Get: output->append("GET "); diff --git a/web_backends/drogon/drogon/lib/inc/http/HttpRequestImpl.h b/web_backends/drogon/drogon/lib/inc/http/HttpRequestImpl.h index e13075a..1e20909 100644 --- a/web_backends/drogon/drogon/lib/inc/http/HttpRequestImpl.h +++ b/web_backends/drogon/drogon/lib/inc/http/HttpRequestImpl.h @@ -20,10 +20,10 @@ #include #include #include -#include "core/loops/event_loop.h" -#include "core/net/inet_address.h" -#include "core/log/logger.h" -#include "core/containers/msg_buffer.h" +#include +#include +#include +#include #include #include #include @@ -35,8 +35,8 @@ class HttpRequestImpl : public HttpRequest { public: friend class HttpRequestParser; - explicit HttpRequestImpl(EventLoop *loop) : - creationDate_(Date::now()), loop_(loop) { + explicit HttpRequestImpl(trantor::EventLoop *loop) : + creationDate_(trantor::Date::now()), loop_(loop) { } void reset() { method_ = Invalid; @@ -62,7 +62,7 @@ public: keepAlive_ = true; jsonParsingErrorPtr_.reset(); } - EventLoop *getLoop() { + trantor::EventLoop *getLoop() { return loop_; } @@ -174,27 +174,27 @@ public: return query_; } - virtual const InetAddress &peerAddr() const override { + virtual const trantor::InetAddress &peerAddr() const override { return peer_; } - virtual const InetAddress &localAddr() const override { + virtual const trantor::InetAddress &localAddr() const override { return local_; } - virtual const Date &creationDate() const override { + virtual const trantor::Date &creationDate() const override { return creationDate_; } - void setCreationDate(const Date &date) { + void setCreationDate(const trantor::Date &date) { creationDate_ = date; } - void setPeerAddr(const InetAddress &peer) { + void setPeerAddr(const trantor::InetAddress &peer) { peer_ = peer; } - void setLocalAddr(const InetAddress &local) { + void setLocalAddr(const trantor::InetAddress &local) { local_ = local; } @@ -287,7 +287,7 @@ public: return passThrough_; } - void appendToBuffer(MsgBuffer *output) const; + void appendToBuffer(trantor::MsgBuffer *output) const; virtual const SessionPtr &session() const override { return sessionPtr_; @@ -419,9 +419,9 @@ private: mutable std::shared_ptr jsonPtr_; SessionPtr sessionPtr_; mutable AttributesPtr attributesPtr_; - InetAddress peer_; - InetAddress local_; - Date creationDate_; + trantor::InetAddress peer_; + trantor::InetAddress local_; + trantor::Date creationDate_; std::unique_ptr cacheFilePtr_; mutable std::unique_ptr jsonParsingErrorPtr_; std::unique_ptr expectPtr_; @@ -431,7 +431,7 @@ private: protected: std::string content_; - EventLoop *loop_; + trantor::EventLoop *loop_; mutable ContentType contentType_{ CT_TEXT_PLAIN }; mutable bool flagForParsingContentType_{ false }; std::string contentTypeString_; diff --git a/web_backends/drogon/drogon/lib/inc/http/HttpRequestParser.cc b/web_backends/drogon/drogon/lib/inc/http/HttpRequestParser.cc index 5b91f3a..8809039 100644 --- a/web_backends/drogon/drogon/lib/inc/http/HttpRequestParser.cc +++ b/web_backends/drogon/drogon/lib/inc/http/HttpRequestParser.cc @@ -18,14 +18,14 @@ #include "HttpResponseImpl.h" #include "HttpUtils.h" #include -#include "core/log/logger.h" -#include "core/containers/msg_buffer.h" +#include +#include #include - +using namespace trantor; using namespace drogon; -HttpRequestParser::HttpRequestParser(const TcpConnectionPtr &connPtr) : +HttpRequestParser::HttpRequestParser(const trantor::TcpConnectionPtr &connPtr) : status_(HttpRequestParseStatus::kExpectMethod), loop_(connPtr->getLoop()), conn_(connPtr) { @@ -99,7 +99,7 @@ void HttpRequestParser::reset() { auto req = std::move(requestsPool_.back()); requestsPool_.pop_back(); request_ = std::move(req); - request_->setCreationDate(Date::now()); + request_->setCreationDate(trantor::Date::now()); } } // Return false if any error diff --git a/web_backends/drogon/drogon/lib/inc/http/HttpRequestParser.h b/web_backends/drogon/drogon/lib/inc/http/HttpRequestParser.h index 3568d71..a682191 100644 --- a/web_backends/drogon/drogon/lib/inc/http/HttpRequestParser.h +++ b/web_backends/drogon/drogon/lib/inc/http/HttpRequestParser.h @@ -16,14 +16,14 @@ #include "../src/impl_forwards.h" #include -#include "core/net/tcp_connection.h" -#include "core/containers/msg_buffer.h" +#include +#include #include #include #include namespace drogon { -class HttpRequestParser : public NonCopyable, +class HttpRequestParser : public trantor::NonCopyable, public std::enable_shared_from_this { public: enum class HttpRequestParseStatus { @@ -37,10 +37,10 @@ public: kGotAll, }; - explicit HttpRequestParser(const TcpConnectionPtr &connPtr); + explicit HttpRequestParser(const trantor::TcpConnectionPtr &connPtr); // return false if any error - bool parseRequest(MsgBuffer *buf); + bool parseRequest(trantor::MsgBuffer *buf); bool gotAll() const { return status_ == HttpRequestParseStatus::kGotAll; @@ -88,7 +88,7 @@ public: size_t numberOfRequestsParsed() const { return requestsCounter_; } - MsgBuffer &getBuffer() { + trantor::MsgBuffer &getBuffer() { return sendBuffer_; } std::vector > &getResponseBuffer() { @@ -114,16 +114,16 @@ private: void shutdownConnection(HttpStatusCode code); bool processRequestLine(const char *begin, const char *end); HttpRequestParseStatus status_; - EventLoop *loop_; + trantor::EventLoop *loop_; HttpRequestImplPtr request_; bool firstRequest_{ true }; WebSocketConnectionImplPtr websockConnPtr_; std::deque > > requestPipelining_; size_t requestsCounter_{ 0 }; - std::weak_ptr conn_; + std::weak_ptr conn_; bool stopWorking_{ false }; - MsgBuffer sendBuffer_; + trantor::MsgBuffer sendBuffer_; std::unique_ptr > > responseBuffer_; std::unique_ptr > requestBuffer_; diff --git a/web_backends/drogon/drogon/lib/inc/http/HttpResponse.h b/web_backends/drogon/drogon/lib/inc/http/HttpResponse.h index 112fb41..c8bc146 100644 --- a/web_backends/drogon/drogon/lib/inc/http/HttpResponse.h +++ b/web_backends/drogon/drogon/lib/inc/http/HttpResponse.h @@ -101,8 +101,8 @@ public: } /// Get the creation timestamp of the response. - virtual const Date &creationDate() const = 0; - const Date &getCreationDate() const { + virtual const trantor::Date &creationDate() const = 0; + const trantor::Date &getCreationDate() const { return creationDate(); } diff --git a/web_backends/drogon/drogon/lib/inc/http/HttpResponseImpl.cc b/web_backends/drogon/drogon/lib/inc/http/HttpResponseImpl.cc index c1102e5..121c3da 100644 --- a/web_backends/drogon/drogon/lib/inc/http/HttpResponseImpl.cc +++ b/web_backends/drogon/drogon/lib/inc/http/HttpResponseImpl.cc @@ -18,14 +18,14 @@ #include #include #include -#include "core/log/logger.h" +#include #include #include #include #ifdef _WIN32 #define stat _stati64 #endif - +using namespace trantor; using namespace drogon; namespace drogon { @@ -98,7 +98,7 @@ void HttpResponseImpl::generateBodyFromJson() const { } HttpResponsePtr HttpResponse::newNotFoundResponse() { - auto loop = EventLoop::getEventLoopOfCurrentThread(); + auto loop = trantor::EventLoop::getEventLoopOfCurrentThread(); auto &resp = HttpAppFrameworkImpl::instance().getCustom404Page(); if (resp) { if (loop && loop->index() < app().getThreadNum()) { @@ -243,7 +243,7 @@ HttpResponsePtr HttpResponse::newFileResponse(const std::string &fullPath, const return resp; } -void HttpResponseImpl::makeHeaderString(MsgBuffer &buffer) { +void HttpResponseImpl::makeHeaderString(trantor::MsgBuffer &buffer) { buffer.ensureWritableBytes(128); int len{ 0 }; if (version_ == Version::kHttp11) { @@ -320,7 +320,7 @@ void HttpResponseImpl::makeHeaderString(MsgBuffer &buffer) { buffer.append("\r\n"); } } -void HttpResponseImpl::renderToBuffer(MsgBuffer &buffer) { +void HttpResponseImpl::renderToBuffer(trantor::MsgBuffer &buffer) { if (expriedTime_ >= 0) { auto strPtr = renderToBuffer(); buffer.append(strPtr->peek(), strPtr->readableBytes()); @@ -344,7 +344,7 @@ void HttpResponseImpl::renderToBuffer(MsgBuffer &buffer) { if (!passThrough_ && drogon::HttpAppFrameworkImpl::instance().sendDateHeader()) { buffer.append("date: "); - buffer.append(utils::getHttpFullDate(Date::date()), + buffer.append(utils::getHttpFullDate(trantor::Date::date()), httpFullDateStringLength); buffer.append("\r\n\r\n"); } else { @@ -353,12 +353,12 @@ void HttpResponseImpl::renderToBuffer(MsgBuffer &buffer) { if (bodyPtr_) buffer.append(bodyPtr_->data(), bodyPtr_->length()); } -std::shared_ptr HttpResponseImpl::renderToBuffer() { +std::shared_ptr HttpResponseImpl::renderToBuffer() { if (expriedTime_ >= 0) { if (!passThrough_ && drogon::HttpAppFrameworkImpl::instance().sendDateHeader()) { if (datePos_ != static_cast(-1)) { - auto now = Date::now(); + auto now = trantor::Date::now(); bool isDateChanged = ((now.microSecondsSinceEpoch() / MICRO_SECONDS_PRE_SEC) != httpStringDate_); @@ -369,7 +369,7 @@ std::shared_ptr HttpResponseImpl::renderToBuffer() { auto newDate = utils::getHttpFullDate(now); httpString_ = - std::make_shared(*httpString_); + std::make_shared(*httpString_); memcpy((void *)&(*httpString_)[datePos_], newDate, httpFullDateStringLength); @@ -383,7 +383,7 @@ std::shared_ptr HttpResponseImpl::renderToBuffer() { return httpString_; } } - auto httpString = std::make_shared(256); + auto httpString = std::make_shared(256); if (!fullHeaderString_) { makeHeaderString(*httpString); } else { @@ -402,7 +402,7 @@ std::shared_ptr HttpResponseImpl::renderToBuffer() { drogon::HttpAppFrameworkImpl::instance().sendDateHeader()) { httpString->append("date: "); auto datePos = httpString->readableBytes(); - httpString->append(utils::getHttpFullDate(Date::date()), + httpString->append(utils::getHttpFullDate(trantor::Date::date()), httpFullDateStringLength); httpString->append("\r\n\r\n"); datePos_ = datePos; @@ -420,9 +420,9 @@ std::shared_ptr HttpResponseImpl::renderToBuffer() { return httpString; } -std::shared_ptr HttpResponseImpl:: +std::shared_ptr HttpResponseImpl:: renderHeaderForHeadMethod() { - auto httpString = std::make_shared(256); + auto httpString = std::make_shared(256); if (!fullHeaderString_) { makeHeaderString(*httpString); } else { @@ -440,7 +440,7 @@ std::shared_ptr HttpResponseImpl:: if (!passThrough_ && drogon::HttpAppFrameworkImpl::instance().sendDateHeader()) { httpString->append("date: "); - httpString->append(utils::getHttpFullDate(Date::date()), + httpString->append(utils::getHttpFullDate(trantor::Date::date()), httpFullDateStringLength); httpString->append("\r\n\r\n"); } else { diff --git a/web_backends/drogon/drogon/lib/inc/http/HttpResponseImpl.h b/web_backends/drogon/drogon/lib/inc/http/HttpResponseImpl.h index 79fbc32..f4bedc9 100644 --- a/web_backends/drogon/drogon/lib/inc/http/HttpResponseImpl.h +++ b/web_backends/drogon/drogon/lib/inc/http/HttpResponseImpl.h @@ -19,9 +19,9 @@ #include #include -#include "core/net/inet_address.h" -#include "core/math/date.h" -#include "core/containers/msg_buffer.h" +#include +#include +#include #include #include #include @@ -34,12 +34,12 @@ class HttpResponseImpl : public HttpResponse { public: HttpResponseImpl() : - creationDate_(Date::now()) { + creationDate_(trantor::Date::now()) { } HttpResponseImpl(HttpStatusCode code, ContentType type) : statusCode_(code), statusMessage_(statusCodeToString(code)), - creationDate_(Date::now()), + creationDate_(trantor::Date::now()), contentType_(type), flagForParsingContentType_(true), contentTypeString_(webContentTypeToString(type)) { @@ -51,7 +51,7 @@ public: return statusCode_; } - const Date &creationDate() const override { + const trantor::Date &creationDate() const override { return creationDate_; } @@ -199,9 +199,9 @@ public: void redirect(const std::string &url) { headers_["location"] = url; } - std::shared_ptr renderToBuffer(); - void renderToBuffer(MsgBuffer &buffer); - std::shared_ptr renderHeaderForHeadMethod(); + std::shared_ptr renderToBuffer(); + void renderToBuffer(trantor::MsgBuffer &buffer); + std::shared_ptr renderHeaderForHeadMethod(); void clear() override; void setExpiredTime(ssize_t expiredTime) override { @@ -266,7 +266,7 @@ public: sendfileName_ = filename; } void makeHeaderString() { - fullHeaderString_ = std::make_shared(128); + fullHeaderString_ = std::make_shared(128); makeHeaderString(*fullHeaderString_); } @@ -295,7 +295,7 @@ public: ~HttpResponseImpl() override = default; protected: - void makeHeaderString(MsgBuffer &headerString); + void makeHeaderString(trantor::MsgBuffer &headerString); private: void setBody(const char *body, size_t len) override { @@ -327,7 +327,7 @@ private: HttpStatusCode statusCode_{ kUnknown }; string_view statusMessage_; - Date creationDate_; + trantor::Date creationDate_; Version version_{ Version::kHttp11 }; bool closeConnection_{ false }; mutable std::shared_ptr bodyPtr_; @@ -335,8 +335,8 @@ private: std::string sendfileName_; mutable std::shared_ptr jsonPtr_; - std::shared_ptr fullHeaderString_; - mutable std::shared_ptr httpString_; + std::shared_ptr fullHeaderString_; + mutable std::shared_ptr httpString_; mutable size_t datePos_{ static_cast(-1) }; mutable int64_t httpStringDate_{ -1 }; mutable bool flagForParsingJson_{ false }; diff --git a/web_backends/drogon/drogon/lib/inc/http/HttpResponseParser.cc b/web_backends/drogon/drogon/lib/inc/http/HttpResponseParser.cc index 568202f..75d6a83 100644 --- a/web_backends/drogon/drogon/lib/inc/http/HttpResponseParser.cc +++ b/web_backends/drogon/drogon/lib/inc/http/HttpResponseParser.cc @@ -14,10 +14,10 @@ #include "HttpResponseParser.h" #include "HttpResponseImpl.h" -#include "core/log/logger.h" -#include "core/containers/msg_buffer.h" +#include +#include #include - +using namespace trantor; using namespace drogon; void HttpResponseParser::reset() { @@ -28,7 +28,7 @@ void HttpResponseParser::reset() { currentChunkLength_ = 0; } -HttpResponseParser::HttpResponseParser(const TcpConnectionPtr &connPtr) : +HttpResponseParser::HttpResponseParser(const trantor::TcpConnectionPtr &connPtr) : status_(HttpResponseParseStatus::kExpectResponseLine), responsePtr_(new HttpResponseImpl), conn_(connPtr) { diff --git a/web_backends/drogon/drogon/lib/inc/http/HttpResponseParser.h b/web_backends/drogon/drogon/lib/inc/http/HttpResponseParser.h index 27c35dd..cde089c 100644 --- a/web_backends/drogon/drogon/lib/inc/http/HttpResponseParser.h +++ b/web_backends/drogon/drogon/lib/inc/http/HttpResponseParser.h @@ -15,14 +15,14 @@ #pragma once #include "../src/impl_forwards.h" -#include "core/net/tcp_connection.h" -#include "core/containers/msg_buffer.h" +#include +#include #include #include #include namespace drogon { -class HttpResponseParser : public NonCopyable { +class HttpResponseParser : public trantor::NonCopyable { public: enum class HttpResponseParseStatus { kExpectResponseLine, @@ -35,12 +35,12 @@ public: kGotAll, }; - explicit HttpResponseParser(const TcpConnectionPtr &connPtr); + explicit HttpResponseParser(const trantor::TcpConnectionPtr &connPtr); // default copy-ctor, dtor and assignment are fine // return false if any error - bool parseResponse(MsgBuffer *buf); + bool parseResponse(trantor::MsgBuffer *buf); bool parseResponseOnClose(); bool gotAll() const { @@ -65,7 +65,7 @@ private: bool parseResponseForHeadMethod_{ false }; size_t leftBodyLength_{ 0 }; size_t currentChunkLength_{ 0 }; - std::weak_ptr conn_; + std::weak_ptr conn_; }; } // namespace drogon diff --git a/web_backends/drogon/drogon/lib/inc/http/HttpUtils.cc b/web_backends/drogon/drogon/lib/inc/http/HttpUtils.cc index b6ad401..692938e 100644 --- a/web_backends/drogon/drogon/lib/inc/http/HttpUtils.cc +++ b/web_backends/drogon/drogon/lib/inc/http/HttpUtils.cc @@ -14,7 +14,7 @@ #include "HttpUtils.h" #include -#include "core/log/logger.h" +#include #include namespace drogon { diff --git a/web_backends/drogon/drogon/lib/inc/http/HttpUtils.h b/web_backends/drogon/drogon/lib/inc/http/HttpUtils.h index a0a4579..4e91e90 100644 --- a/web_backends/drogon/drogon/lib/inc/http/HttpUtils.h +++ b/web_backends/drogon/drogon/lib/inc/http/HttpUtils.h @@ -16,7 +16,7 @@ #include "HttpTypes.h" #include -#include "core/containers/msg_buffer.h" +#include #include namespace drogon { diff --git a/web_backends/drogon/drogon/lib/inc/http/Session.h b/web_backends/drogon/drogon/lib/inc/http/Session.h index 25376b3..ed4f1a8 100644 --- a/web_backends/drogon/drogon/lib/inc/http/Session.h +++ b/web_backends/drogon/drogon/lib/inc/http/Session.h @@ -16,7 +16,7 @@ #include #include -#include "core/log/logger.h" +#include #include #include #include diff --git a/web_backends/drogon/drogon/lib/inc/http/SessionManager.cc b/web_backends/drogon/drogon/lib/inc/http/SessionManager.cc index 233b65b..690bd12 100644 --- a/web_backends/drogon/drogon/lib/inc/http/SessionManager.cc +++ b/web_backends/drogon/drogon/lib/inc/http/SessionManager.cc @@ -17,7 +17,7 @@ using namespace drogon; -SessionManager::SessionManager(EventLoop *loop, size_t timeout) : +SessionManager::SessionManager(trantor::EventLoop *loop, size_t timeout) : loop_(loop), timeout_(timeout) { if (timeout_ > 0) { size_t wheelNum = 1; diff --git a/web_backends/drogon/drogon/lib/inc/http/SessionManager.h b/web_backends/drogon/drogon/lib/inc/http/SessionManager.h index 139a6a8..5d27e66 100644 --- a/web_backends/drogon/drogon/lib/inc/http/SessionManager.h +++ b/web_backends/drogon/drogon/lib/inc/http/SessionManager.h @@ -16,16 +16,16 @@ #include "CacheMap.h" #include "Session.h" -#include "core/loops/event_loop.h" +#include #include #include #include #include namespace drogon { -class SessionManager : public NonCopyable { +class SessionManager : public trantor::NonCopyable { public: - SessionManager(EventLoop *loop, size_t timeout); + SessionManager(trantor::EventLoop *loop, size_t timeout); ~SessionManager() { sessionMapPtr_.reset(); } @@ -34,7 +34,7 @@ public: private: std::unique_ptr > sessionMapPtr_; - EventLoop *loop_; + trantor::EventLoop *loop_; size_t timeout_; }; } // namespace drogon diff --git a/web_backends/drogon/drogon/lib/src/AccessLogger.cc b/web_backends/drogon/drogon/lib/src/AccessLogger.cc index d7275d4..855fbfa 100644 --- a/web_backends/drogon/drogon/lib/src/AccessLogger.cc +++ b/web_backends/drogon/drogon/lib/src/AccessLogger.cc @@ -35,13 +35,13 @@ void AccessLogger::initAndStart(const Json::Value &config) { logFunctionMap_ = { { "$request_path", outputReqPath }, { "$path", outputReqPath }, { "$date", - [this](LogStream &stream, + [this](trantor::LogStream &stream, const drogon::HttpRequestPtr &req, const drogon::HttpResponsePtr &resp) { outputDate(stream, req, resp); } }, { "$request_date", - [this](LogStream &stream, + [this](trantor::LogStream &stream, const drogon::HttpRequestPtr &req, const drogon::HttpResponsePtr &resp) { outputReqDate(stream, req, resp); @@ -85,7 +85,7 @@ void AccessLogger::initAndStart(const Json::Value &config) { asyncFileLogger_.setFileName(fileName, extension, logPath); asyncFileLogger_.startLogging(); logIndex_ = config.get("log_index", 0).asInt(); - Logger::setOutputFunction( + trantor::Logger::setOutputFunction( [&](const char *msg, const uint64_t len) { asyncFileLogger_.output(msg, len); }, @@ -106,7 +106,7 @@ void AccessLogger::initAndStart(const Json::Value &config) { void AccessLogger::shutdown() { } -void AccessLogger::logging(LogStream &stream, +void AccessLogger::logging(trantor::LogStream &stream, const drogon::HttpRequestPtr &req, const drogon::HttpResponsePtr &resp) { for (auto &func : logFunctions_) { @@ -128,7 +128,7 @@ void AccessLogger::createLogFunctions(std::string format) { if (std::regex_search(format, m, e)) { if (!rawString.empty()) { logFunctions_.emplace_back( - [rawString](LogStream &stream, + [rawString](trantor::LogStream &stream, const drogon::HttpRequestPtr &, const drogon::HttpResponsePtr &) { stream << rawString; @@ -150,14 +150,14 @@ void AccessLogger::createLogFunctions(std::string format) { if (!rawString.empty()) { logFunctions_.emplace_back( [rawString = - std::move(rawString)](LogStream &stream, + std::move(rawString)](trantor::LogStream &stream, const drogon::HttpRequestPtr &, const drogon::HttpResponsePtr &) { stream << rawString << "\n"; }); } else { logFunctions_.emplace_back( - [](LogStream &stream, + [](trantor::LogStream &stream, const drogon::HttpRequestPtr &, const drogon::HttpResponsePtr &) { stream << "\n"; }); } @@ -172,7 +172,7 @@ AccessLogger::LogFunction AccessLogger::newLogFunction( if (placeholder.find("$http_") == 0 && placeholder.size() > 6) { auto headerName = placeholder.substr(6); return [headerName = - std::move(headerName)](LogStream &stream, + std::move(headerName)](trantor::LogStream &stream, const drogon::HttpRequestPtr &req, const drogon::HttpResponsePtr &) { outputReqHeader(stream, req, headerName); @@ -181,7 +181,7 @@ AccessLogger::LogFunction AccessLogger::newLogFunction( if (placeholder.find("$cookie_") == 0 && placeholder.size() > 8) { auto cookieName = placeholder.substr(8); return [cookieName = - std::move(cookieName)](LogStream &stream, + std::move(cookieName)](trantor::LogStream &stream, const drogon::HttpRequestPtr &req, const drogon::HttpResponsePtr &) { outputReqCookie(stream, req, cookieName); @@ -190,36 +190,36 @@ AccessLogger::LogFunction AccessLogger::newLogFunction( if (placeholder.find("$upstream_http_") == 0 && placeholder.size() > 15) { auto headerName = placeholder.substr(15); return [headerName = std::move( - headerName)](LogStream &stream, + headerName)](trantor::LogStream &stream, const drogon::HttpRequestPtr &, const drogon::HttpResponsePtr &resp) { outputRespHeader(stream, resp, headerName); }; } - return [placeholder](LogStream &stream, + return [placeholder](trantor::LogStream &stream, const drogon::HttpRequestPtr &, const drogon::HttpResponsePtr &) { stream << placeholder; }; } -void AccessLogger::outputReqPath(LogStream &stream, +void AccessLogger::outputReqPath(trantor::LogStream &stream, const drogon::HttpRequestPtr &req, const drogon::HttpResponsePtr &) { stream << req->path(); } -void AccessLogger::outputDate(LogStream &stream, +void AccessLogger::outputDate(trantor::LogStream &stream, const drogon::HttpRequestPtr &, const drogon::HttpResponsePtr &) const { if (useLocalTime_) { - stream << Date::now().toFormattedStringLocal(true); + stream << trantor::Date::now().toFormattedStringLocal(true); } else { - stream << Date::now().toFormattedString(true); + stream << trantor::Date::now().toFormattedString(true); } } -void AccessLogger::outputReqDate(LogStream &stream, +void AccessLogger::outputReqDate(trantor::LogStream &stream, const drogon::HttpRequestPtr &req, const drogon::HttpResponsePtr &) const { if (useLocalTime_) { @@ -230,13 +230,13 @@ void AccessLogger::outputReqDate(LogStream &stream, } //$request_query -void AccessLogger::outputReqQuery(LogStream &stream, +void AccessLogger::outputReqQuery(trantor::LogStream &stream, const drogon::HttpRequestPtr &req, const drogon::HttpResponsePtr &) { stream << req->query(); } //$request_url -void AccessLogger::outputReqURL(LogStream &stream, +void AccessLogger::outputReqURL(trantor::LogStream &stream, const drogon::HttpRequestPtr &req, const drogon::HttpResponsePtr &) { auto &query = req->query(); @@ -247,36 +247,36 @@ void AccessLogger::outputReqURL(LogStream &stream, } } -void AccessLogger::outputRemoteAddr(LogStream &stream, +void AccessLogger::outputRemoteAddr(trantor::LogStream &stream, const drogon::HttpRequestPtr &req, const drogon::HttpResponsePtr &) { stream << req->peerAddr().toIpPort(); } -void AccessLogger::outputLocalAddr(LogStream &stream, +void AccessLogger::outputLocalAddr(trantor::LogStream &stream, const drogon::HttpRequestPtr &req, const drogon::HttpResponsePtr &) { stream << req->localAddr().toIpPort(); } -void AccessLogger::outputReqLength(LogStream &stream, +void AccessLogger::outputReqLength(trantor::LogStream &stream, const drogon::HttpRequestPtr &req, const drogon::HttpResponsePtr &) { stream << req->body().length(); } -void AccessLogger::outputRespLength(LogStream &stream, +void AccessLogger::outputRespLength(trantor::LogStream &stream, const drogon::HttpRequestPtr &, const drogon::HttpResponsePtr &resp) { stream << resp->body().length(); } -void AccessLogger::outputMethod(LogStream &stream, +void AccessLogger::outputMethod(trantor::LogStream &stream, const drogon::HttpRequestPtr &req, const drogon::HttpResponsePtr &) { stream << req->methodString(); } -void AccessLogger::outputThreadNumber(LogStream &stream, +void AccessLogger::outputThreadNumber(trantor::LogStream &stream, const drogon::HttpRequestPtr &, const drogon::HttpResponsePtr &) { #ifdef __linux__ @@ -310,45 +310,45 @@ void AccessLogger::outputThreadNumber(LogStream &stream, } //$http_[header_name] -void AccessLogger::outputReqHeader(LogStream &stream, +void AccessLogger::outputReqHeader(trantor::LogStream &stream, const drogon::HttpRequestPtr &req, const std::string &headerName) { stream << headerName << ": " << req->getHeader(headerName); } //$cookie_[cookie_name] -void AccessLogger::outputReqCookie(LogStream &stream, +void AccessLogger::outputReqCookie(trantor::LogStream &stream, const drogon::HttpRequestPtr &req, const std::string &cookie) { stream << "(cookie)" << cookie << "=" << req->getCookie(cookie); } //$upstream_http_[header_name] -void AccessLogger::outputRespHeader(LogStream &stream, +void AccessLogger::outputRespHeader(trantor::LogStream &stream, const drogon::HttpResponsePtr &resp, const std::string &headerName) { stream << headerName << ": " << resp->getHeader(headerName); } //$status -void AccessLogger::outputStatusString(LogStream &stream, +void AccessLogger::outputStatusString(trantor::LogStream &stream, const drogon::HttpRequestPtr &, const drogon::HttpResponsePtr &resp) { int code = resp->getStatusCode(); stream << code << " " << statusCodeToString(code); } //$status_code -void AccessLogger::outputStatusCode(LogStream &stream, +void AccessLogger::outputStatusCode(trantor::LogStream &stream, const drogon::HttpRequestPtr &, const drogon::HttpResponsePtr &resp) { stream << resp->getStatusCode(); } //$processing_time -void AccessLogger::outputProcessingTime(LogStream &stream, +void AccessLogger::outputProcessingTime(trantor::LogStream &stream, const drogon::HttpRequestPtr &req, const drogon::HttpResponsePtr &) { auto start = req->creationDate(); - auto end = Date::now(); + auto end = trantor::Date::now(); auto duration = end.microSecondsSinceEpoch() - start.microSecondsSinceEpoch(); auto seconds = static_cast(duration) / 1000000.0; @@ -356,7 +356,7 @@ void AccessLogger::outputProcessingTime(LogStream &stream, } //$upstream_http_content-type $upstream_http_content_type -void AccessLogger::outputRespContentType(LogStream &stream, +void AccessLogger::outputRespContentType(trantor::LogStream &stream, const drogon::HttpRequestPtr &, const drogon::HttpResponsePtr &resp) { auto typeStr = webContentTypeToString(resp->contentType()); diff --git a/web_backends/drogon/drogon/lib/src/HttpAppFrameworkImpl.cc b/web_backends/drogon/drogon/lib/src/HttpAppFrameworkImpl.cc index d86b9d4..4a24cc8 100644 --- a/web_backends/drogon/drogon/lib/src/HttpAppFrameworkImpl.cc +++ b/web_backends/drogon/drogon/lib/src/HttpAppFrameworkImpl.cc @@ -33,7 +33,7 @@ #include #include -#include "core/log/async_file_logger.h" +#include #include #include @@ -365,8 +365,8 @@ HttpAppFramework &HttpAppFrameworkImpl::setLogPath( return *this; } HttpAppFramework &HttpAppFrameworkImpl::setLogLevel( - Logger::LogLevel level) { - Logger::setLogLevel(level); + trantor::Logger::LogLevel level) { + trantor::Logger::setLogLevel(level); return *this; } HttpAppFramework &HttpAppFrameworkImpl::setSSLConfigCommands( @@ -386,7 +386,7 @@ void HttpAppFrameworkImpl::run() { getLoop()->moveToCurrentThread(); } LOG_TRACE << "Start to run..."; - AsyncFileLogger asyncFileLogger; + trantor::AsyncFileLogger asyncFileLogger; // Create dirs for cache files for (int i = 0; i < 256; ++i) { char dirName[4]; @@ -443,7 +443,7 @@ void HttpAppFrameworkImpl::run() { asyncFileLogger.setFileName(baseName, ".log", logPath_); asyncFileLogger.startLogging(); - Logger::setOutputFunction( + trantor::Logger::setOutputFunction( [&](const char *msg, const uint64_t len) { asyncFileLogger.output(msg, len); }, @@ -518,7 +518,7 @@ void HttpAppFrameworkImpl::run() { getLoop()->loop(); } -void HttpAppFrameworkImpl::onConnection(const TcpConnectionPtr &conn) { +void HttpAppFrameworkImpl::onConnection(const trantor::TcpConnectionPtr &conn) { static std::mutex mtx; LOG_TRACE << "connect!!!" << maxConnectionNum_ << " num=" << connectionNum_.load(); @@ -737,13 +737,13 @@ void HttpAppFrameworkImpl::onAsyncRequest( }*/ } -EventLoop *HttpAppFrameworkImpl::getLoop() const { - //static EventLoop loop; +trantor::EventLoop *HttpAppFrameworkImpl::getLoop() const { + //static trantor::EventLoop loop; //return &loop;] return nullptr; } -EventLoop *HttpAppFrameworkImpl::getIOLoop(size_t id) const { +trantor::EventLoop *HttpAppFrameworkImpl::getIOLoop(size_t id) const { assert(listenerManagerPtr_); return listenerManagerPtr_->getIOLoop(id); } @@ -781,7 +781,7 @@ void HttpAppFrameworkImpl::forward( clientPtr = iter->second; } else { clientPtr = std::make_shared( - EventLoop::getEventLoopOfCurrentThread() ? EventLoop::getEventLoopOfCurrentThread() : getLoop(), + trantor::EventLoop::getEventLoopOfCurrentThread() ? trantor::EventLoop::getEventLoopOfCurrentThread() : getLoop(), hostString); clientsMap[hostString] = clientPtr; } @@ -815,7 +815,7 @@ const HttpResponsePtr &HttpAppFrameworkImpl::getCustom404Page() { if (!custom404_) { return custom404_; } - auto loop = EventLoop::getEventLoopOfCurrentThread(); + auto loop = trantor::EventLoop::getEventLoopOfCurrentThread(); if (loop && loop->index() < app().getThreadNum()) { // If the current thread is an IO thread static IOThreadStorage thread404Pages; @@ -869,7 +869,7 @@ const std::function return customErrorHandler_; } -std::vector HttpAppFrameworkImpl::getListeners() const { +std::vector HttpAppFrameworkImpl::getListeners() const { return listenerManagerPtr_->getListeners(); } HttpAppFramework &HttpAppFrameworkImpl::setDefaultHandler( diff --git a/web_backends/drogon/drogon/lib/src/HttpAppFrameworkImpl.h b/web_backends/drogon/drogon/lib/src/HttpAppFrameworkImpl.h index b53189e..1fce1ad 100644 --- a/web_backends/drogon/drogon/lib/src/HttpAppFrameworkImpl.h +++ b/web_backends/drogon/drogon/lib/src/HttpAppFrameworkImpl.h @@ -114,8 +114,8 @@ public: } HttpAppFramework ®isterNewConnectionAdvice( - const std::function &advice) + const std::function &advice) override { newConnectionAdvices_.emplace_back(advice); return *this; @@ -222,8 +222,8 @@ public: const std::string &getUploadPath() const override { return uploadPath_; } - const std::shared_ptr &getResolver() const override { - static auto resolver = Resolver::newResolver(getLoop()); + const std::shared_ptr &getResolver() const override { + static auto resolver = trantor::Resolver::newResolver(getLoop()); return resolver; } HttpAppFramework &setUploadPath(const std::string &uploadPath) override; @@ -255,7 +255,7 @@ public: HttpAppFramework &setLogPath(const std::string &logPath, const std::string &logfileBaseName, size_t logfileSize) override; - HttpAppFramework &setLogLevel(Logger::LogLevel level) override; + HttpAppFramework &setLogLevel(trantor::Logger::LogLevel level) override; HttpAppFramework &enableSendfile(bool sendFile) override { useSendfile_ = sendFile; return *this; @@ -365,9 +365,9 @@ public: const noexcept override { return floatPrecisionInJson_; } - EventLoop *getLoop() const override; + trantor::EventLoop *getLoop() const override; - EventLoop *getIOLoop(size_t id) const override; + trantor::EventLoop *getIOLoop(size_t id) const override; void quit() override; @@ -396,7 +396,7 @@ public: return serverHeader_; } - std::vector getListeners() const override; + std::vector getListeners() const override; inline static HttpAppFrameworkImpl &instance() { static HttpAppFrameworkImpl instance; return instance; @@ -417,7 +417,7 @@ public: } size_t getCurrentThreadIndex() const override { - auto *loop = EventLoop::getEventLoopOfCurrentThread(); + auto *loop = trantor::EventLoop::getEventLoopOfCurrentThread(); if (loop) { return loop->index(); } @@ -466,7 +466,7 @@ private: const HttpRequestImplPtr &req, std::function &&callback, const WebSocketConnectionImplPtr &wsConnPtr); - void onConnection(const TcpConnectionPtr &conn); + void onConnection(const trantor::TcpConnectionPtr &conn); void findSessionForRequest(const HttpRequestImplPtr &req); @@ -539,8 +539,8 @@ private: bool enableDateHeader_{ true }; bool reusePort_{ false }; std::vector > beginningAdvices_; - std::vector > + std::vector > newConnectionAdvices_; std::vector > responseCreationAdvices_; diff --git a/web_backends/drogon/drogon/lib/src/HttpClientImpl.cc b/web_backends/drogon/drogon/lib/src/HttpClientImpl.cc index ce90f9d..14fb675 100644 --- a/web_backends/drogon/drogon/lib/src/HttpClientImpl.cc +++ b/web_backends/drogon/drogon/lib/src/HttpClientImpl.cc @@ -21,16 +21,16 @@ #include #include - +using namespace trantor; using namespace drogon; using namespace std::placeholders; - +namespace trantor { const static size_t kDefaultDNSTimeout{ 600 }; - +} void HttpClientImpl::createTcpClient() { LOG_TRACE << "New TcpClient," << serverAddr_.toIpPort(); tcpClientPtr_ = - std::make_shared(loop_, serverAddr_, "httpClient"); + std::make_shared(loop_, serverAddr_, "httpClient"); #ifdef OPENSSL_FOUND if (useSSL_) { @@ -43,7 +43,7 @@ void HttpClientImpl::createTcpClient() { std::weak_ptr weakPtr = thisPtr; tcpClientPtr_->setConnectionCallback( - [weakPtr](const TcpConnectionPtr &connPtr) { + [weakPtr](const trantor::TcpConnectionPtr &connPtr) { auto thisPtr = weakPtr.lock(); if (!thisPtr) return; @@ -89,8 +89,8 @@ void HttpClientImpl::createTcpClient() { thisPtr->onError(ReqResult::BadServerAddress); }); tcpClientPtr_->setMessageCallback( - [weakPtr](const TcpConnectionPtr &connPtr, - MsgBuffer *msg) { + [weakPtr](const trantor::TcpConnectionPtr &connPtr, + trantor::MsgBuffer *msg) { auto thisPtr = weakPtr.lock(); if (thisPtr) { thisPtr->onRecvMessage(connPtr, msg); @@ -100,9 +100,9 @@ void HttpClientImpl::createTcpClient() { auto thisPtr = weakPtr.lock(); if (!thisPtr) return; - if (err == SSLError::kSSLHandshakeError) + if (err == trantor::SSLError::kSSLHandshakeError) thisPtr->onError(ReqResult::HandshakeError); - else if (err == SSLError::kSSLInvalidCertificate) + else if (err == trantor::SSLError::kSSLInvalidCertificate) thisPtr->onError(ReqResult::InvalidCertificate); else { LOG_FATAL << "Invalid value for SSLError"; @@ -112,8 +112,8 @@ void HttpClientImpl::createTcpClient() { tcpClientPtr_->connect(); } -HttpClientImpl::HttpClientImpl(EventLoop *loop, - const InetAddress &addr, +HttpClientImpl::HttpClientImpl(trantor::EventLoop *loop, + const trantor::InetAddress &addr, bool useSSL, bool useOldTLS, bool validateCert) : @@ -124,7 +124,7 @@ HttpClientImpl::HttpClientImpl(EventLoop *loop, useOldTLS_(useOldTLS) { } -HttpClientImpl::HttpClientImpl(EventLoop *loop, +HttpClientImpl::HttpClientImpl(trantor::EventLoop *loop, const std::string &hostString, bool useOldTLS, bool validateCert) : @@ -285,7 +285,7 @@ void HttpClientImpl::sendRequestInLoop(const drogon::HttpRequestPtr &req, } for (auto &cookie : validCookies_) { if ((cookie.expiresDate().microSecondsSinceEpoch() == 0 || - cookie.expiresDate() > Date::now()) && + cookie.expiresDate() > trantor::Date::now()) && (cookie.path().empty() || req->path().find(cookie.path()) == 0)) { req->addCookie(cookie.key(), cookie.value()); } @@ -316,13 +316,13 @@ void HttpClientImpl::sendRequestInLoop(const drogon::HttpRequestPtr &req, dns_ = true; if (!resolverPtr_) { resolverPtr_ = - Resolver::newResolver(loop_, + trantor::Resolver::newResolver(loop_, kDefaultDNSTimeout); } resolverPtr_->resolve( domain_, [thisPtr = shared_from_this(), - hasIpv6Address](const InetAddress &addr) { + hasIpv6Address](const trantor::InetAddress &addr) { thisPtr->loop_->runInLoop([thisPtr, addr, hasIpv6Address]() { @@ -394,9 +394,9 @@ void HttpClientImpl::sendRequestInLoop(const drogon::HttpRequestPtr &req, } } -void HttpClientImpl::sendReq(const TcpConnectionPtr &connPtr, +void HttpClientImpl::sendReq(const trantor::TcpConnectionPtr &connPtr, const HttpRequestPtr &req) { - MsgBuffer buffer; + trantor::MsgBuffer buffer; assert(req); auto implPtr = static_cast(req.get()); implPtr->appendToBuffer(&buffer); @@ -409,7 +409,7 @@ void HttpClientImpl::sendReq(const TcpConnectionPtr &connPtr, void HttpClientImpl::handleResponse( const HttpResponseImplPtr &resp, std::pair &&reqAndCb, - const TcpConnectionPtr &connPtr) { + const trantor::TcpConnectionPtr &connPtr) { assert(!pipeliningCallbacks_.empty()); auto &type = resp->getHeaderBy("content-type"); auto &coding = resp->getHeaderBy("content-encoding"); @@ -452,8 +452,8 @@ void HttpClientImpl::handleResponse( } } } -void HttpClientImpl::onRecvMessage(const TcpConnectionPtr &connPtr, - MsgBuffer *msg) { +void HttpClientImpl::onRecvMessage(const trantor::TcpConnectionPtr &connPtr, + trantor::MsgBuffer *msg) { auto responseParser = connPtr->getContext(); // LOG_TRACE << "###:" << msg->readableBytes(); @@ -488,20 +488,20 @@ void HttpClientImpl::onRecvMessage(const TcpConnectionPtr &connPtr, HttpClientPtr HttpClient::newHttpClient(const std::string &ip, uint16_t port, bool useSSL, - EventLoop *loop, + trantor::EventLoop *loop, bool useOldTLS, bool validateCert) { bool isIpv6 = ip.find(':') == std::string::npos ? false : true; return std::make_shared( loop == nullptr ? HttpAppFrameworkImpl::instance().getLoop() : loop, - InetAddress(ip, port, isIpv6), + trantor::InetAddress(ip, port, isIpv6), useSSL, useOldTLS, validateCert); } HttpClientPtr HttpClient::newHttpClient(const std::string &hostString, - EventLoop *loop, + trantor::EventLoop *loop, bool useOldTLS, bool validateCert) { return std::make_shared( diff --git a/web_backends/drogon/drogon/lib/src/HttpClientImpl.h b/web_backends/drogon/drogon/lib/src/HttpClientImpl.h index ff5e588..0b647cb 100644 --- a/web_backends/drogon/drogon/lib/src/HttpClientImpl.h +++ b/web_backends/drogon/drogon/lib/src/HttpClientImpl.h @@ -17,9 +17,9 @@ #include "impl_forwards.h" #include #include -#include "core/loops/event_loop.h" -#include "core/net/resolver.h" -#include "core/net/tcp_client.h" +#include +#include +#include #include #include #include @@ -29,12 +29,12 @@ namespace drogon { class HttpClientImpl final : public HttpClient, public std::enable_shared_from_this { public: - HttpClientImpl(EventLoop *loop, - const InetAddress &addr, + HttpClientImpl(trantor::EventLoop *loop, + const trantor::InetAddress &addr, bool useSSL = false, bool useOldTLS = false, bool validateCert = true); - HttpClientImpl(EventLoop *loop, + HttpClientImpl(trantor::EventLoop *loop, const std::string &hostString, bool useOldTLS = false, bool validateCert = true); @@ -44,7 +44,7 @@ public: void sendRequest(const HttpRequestPtr &req, HttpReqCallback &&callback, double timeout = 0) override; - EventLoop *getLoop() override { + trantor::EventLoop *getLoop() override { return loop_; } void setPipeliningDepth(size_t depth) override { @@ -75,12 +75,12 @@ public: } private: - std::shared_ptr tcpClientPtr_; - EventLoop *loop_; - InetAddress serverAddr_; + std::shared_ptr tcpClientPtr_; + trantor::EventLoop *loop_; + trantor::InetAddress serverAddr_; bool useSSL_; bool validateCert_; - void sendReq(const TcpConnectionPtr &connPtr, + void sendReq(const trantor::TcpConnectionPtr &connPtr, const HttpRequestPtr &req); void sendRequestInLoop(const HttpRequestPtr &req, HttpReqCallback &&callback); @@ -90,11 +90,11 @@ private: void handleCookies(const HttpResponseImplPtr &resp); void handleResponse(const HttpResponseImplPtr &resp, std::pair &&reqAndCb, - const TcpConnectionPtr &connPtr); + const trantor::TcpConnectionPtr &connPtr); void createTcpClient(); std::queue > pipeliningCallbacks_; std::list > requestsBuffer_; - void onRecvMessage(const TcpConnectionPtr &, MsgBuffer *); + void onRecvMessage(const trantor::TcpConnectionPtr &, trantor::MsgBuffer *); void onError(ReqResult result); std::string domain_; size_t pipeliningDepth_{ 0 }; @@ -103,7 +103,7 @@ private: size_t bytesSent_{ 0 }; size_t bytesReceived_{ 0 }; bool dns_{ false }; - std::shared_ptr resolverPtr_; + std::shared_ptr resolverPtr_; bool useOldTLS_{ false }; std::string userAgent_{ "DrogonClient" }; }; diff --git a/web_backends/drogon/drogon/lib/src/HttpServer.cc b/web_backends/drogon/drogon/lib/src/HttpServer.cc index 2fa3de3..07ad1c1 100644 --- a/web_backends/drogon/drogon/lib/src/HttpServer.cc +++ b/web_backends/drogon/drogon/lib/src/HttpServer.cc @@ -21,7 +21,7 @@ #include #include #include -#include "core/log/logger.h" +#include #include #if COZ_PROFILING @@ -35,7 +35,7 @@ using namespace std::placeholders; using namespace drogon; - +using namespace trantor; namespace drogon { static HttpResponsePtr getCompressedResponse(const HttpRequestImplPtr &req, const HttpResponsePtr &response, @@ -127,7 +127,7 @@ static void defaultWebSockAsyncCallback( callback(resp); } -static void defaultConnectionCallback(const TcpConnectionPtr &) { +static void defaultConnectionCallback(const trantor::TcpConnectionPtr &) { return; } } // namespace drogon @@ -218,7 +218,7 @@ void HttpServer::onMessage(const TcpConnectionPtr &conn, MsgBuffer *buf) { requestParser->requestImpl()->setPeerAddr(conn->peerAddr()); requestParser->requestImpl()->setLocalAddr(conn->localAddr()); requestParser->requestImpl()->setCreationDate( - Date::date()); + trantor::Date::date()); requestParser->requestImpl()->setSecure( conn->isSSLConnection()); if (requestParser->firstReq() && @@ -457,7 +457,7 @@ void HttpServer::sendResponse(const TcpConnectionPtr &conn, void HttpServer::sendResponses( const TcpConnectionPtr &conn, const std::vector > &responses, - MsgBuffer &buffer) { + trantor::MsgBuffer &buffer) { conn->getLoop()->assertInLoopThread(); if (responses.empty()) return; diff --git a/web_backends/drogon/drogon/lib/src/HttpServer.h b/web_backends/drogon/drogon/lib/src/HttpServer.h index 106e5f7..c15b5f5 100644 --- a/web_backends/drogon/drogon/lib/src/HttpServer.h +++ b/web_backends/drogon/drogon/lib/src/HttpServer.h @@ -15,18 +15,18 @@ #pragma once #include "impl_forwards.h" -#include "core/net/tcp_server.h" -#include "core/net/callbacks.h" +#include +#include #include #include #include #include namespace drogon { -class HttpServer : NonCopyable { +class HttpServer : trantor::NonCopyable { public: - HttpServer(EventLoop *loop, - const InetAddress &listenAddr, + HttpServer(trantor::EventLoop *loop, + const trantor::InetAddress &listenAddr, const std::string &name, const std::vector< std::function > @@ -37,7 +37,7 @@ public: ~HttpServer(); - EventLoop *getLoop() const { + trantor::EventLoop *getLoop() const { return server_.getLoop(); } @@ -48,11 +48,11 @@ public: void setNewWebsocketCallback(const WebSocketNewAsyncCallback &cb) { newWebsocketCallback_ = cb; } - void setConnectionCallback(const ConnectionCallback &cb) { + void setConnectionCallback(const trantor::ConnectionCallback &cb) { connectionCallback_ = cb; } void setIoLoopThreadPool( - const std::shared_ptr &pool) { + const std::shared_ptr &pool) { server_.setIoLoopThreadPool(pool); } void setIoLoopNum(int numThreads) { @@ -61,10 +61,10 @@ public: void kickoffIdleConnections(size_t timeout) { server_.kickoffIdleConnections(timeout); } - EventLoop *getLoop() { + trantor::EventLoop *getLoop() { return server_.getLoop(); } - std::vector getIoLoops() { + std::vector getIoLoops() { return server_.getIoLoops(); } void start(); @@ -78,27 +78,27 @@ public: server_.enableSSL(certPath, keyPath, useOldTLS, sslConfCmds); } - const InetAddress &address() const { + const trantor::InetAddress &address() const { return server_.address(); } private: - void onConnection(const TcpConnectionPtr &conn); - void onMessage(const TcpConnectionPtr &, MsgBuffer *); - void onRequests(const TcpConnectionPtr &, + void onConnection(const trantor::TcpConnectionPtr &conn); + void onMessage(const trantor::TcpConnectionPtr &, trantor::MsgBuffer *); + void onRequests(const trantor::TcpConnectionPtr &, const std::vector &, const std::shared_ptr &); - void sendResponse(const TcpConnectionPtr &, + void sendResponse(const trantor::TcpConnectionPtr &, const HttpResponsePtr &, bool isHeadMethod); void sendResponses( - const TcpConnectionPtr &conn, + const trantor::TcpConnectionPtr &conn, const std::vector > &responses, - MsgBuffer &buffer); - TcpServer server_; + trantor::MsgBuffer &buffer); + trantor::TcpServer server_; HttpAsyncCallback httpAsyncCallback_; WebSocketNewAsyncCallback newWebsocketCallback_; - ConnectionCallback connectionCallback_; + trantor::ConnectionCallback connectionCallback_; const std::vector > &syncAdvices_; const std::vector< diff --git a/web_backends/drogon/drogon/lib/src/ListenerManager.cc b/web_backends/drogon/drogon/lib/src/ListenerManager.cc index 74adaaf..b58ae2e 100644 --- a/web_backends/drogon/drogon/lib/src/ListenerManager.cc +++ b/web_backends/drogon/drogon/lib/src/ListenerManager.cc @@ -19,7 +19,7 @@ #include #include #include -#include "core/log/logger.h" +#include #ifndef _WIN32 #include #include @@ -28,7 +28,7 @@ namespace drogon { #ifndef _WIN32 -class DrogonFileLocker : public NonCopyable { +class DrogonFileLocker : public trantor::NonCopyable { public: DrogonFileLocker() { fd_ = open("/tmp/drogon.lock", O_TRUNC | O_CREAT, 0666); @@ -45,7 +45,7 @@ private: #endif } // namespace drogon - +using namespace trantor; using namespace drogon; void ListenerManager::addListener( @@ -65,7 +65,7 @@ void ListenerManager::addListener( ip, port, useSSL, certFile, keyFile, useOldTLS, sslConfCmds); } -std::vector ListenerManager::createListeners(EventLoop *event_loop, +std::vector ListenerManager::createListeners(trantor::EventLoop *event_loop, const HttpAsyncCallback &httpCallback, const WebSocketNewAsyncCallback &webSocketCallback, const ConnectionCallback &connectionCallback, @@ -224,7 +224,7 @@ void ListenerManager::startListening() { } } -EventLoop *ListenerManager::getIOLoop(size_t id) const { +trantor::EventLoop *ListenerManager::getIOLoop(size_t id) const { auto const n = listeningloopThreads_.size(); if (0 == n) { LOG_WARN << "Please call getIOLoop() after drogon::app().run()"; @@ -275,8 +275,8 @@ void ListenerManager::stopListening() { #endif } -std::vector ListenerManager::getListeners() const { - std::vector listeners; +std::vector ListenerManager::getListeners() const { + std::vector listeners; for (auto &server : servers_) { listeners.emplace_back(server->address()); } diff --git a/web_backends/drogon/drogon/lib/src/ListenerManager.h b/web_backends/drogon/drogon/lib/src/ListenerManager.h index b03fa84..aca6865 100644 --- a/web_backends/drogon/drogon/lib/src/ListenerManager.h +++ b/web_backends/drogon/drogon/lib/src/ListenerManager.h @@ -15,17 +15,17 @@ #pragma once #include "impl_forwards.h" -#include "core/loops/event_loop_thread_pool.h" -#include "core/net/callbacks.h" +#include +#include #include #include #include #include - +namespace trantor { class InetAddress; - +} namespace drogon { -class ListenerManager : public NonCopyable { +class ListenerManager : public trantor::NonCopyable { public: void addListener(const std::string &ip, uint16_t port, @@ -35,10 +35,10 @@ public: bool useOldTLS = false, const std::vector > &sslConfCmds = {}); - std::vector createListeners(EventLoop *event_loop, + std::vector createListeners(trantor::EventLoop *event_loop, const HttpAsyncCallback &httpCallback, const WebSocketNewAsyncCallback &webSocketCallback, - const ConnectionCallback &connectionCallback, + const trantor::ConnectionCallback &connectionCallback, size_t connectionTimeout, const std::string &globalCertFile, const std::string &globalKeyFile, @@ -51,12 +51,12 @@ public: const HttpResponsePtr &)> > &preSendingAdvices); void startListening(); - std::vector getListeners() const; + std::vector getListeners() const; ~ListenerManager() = default; - EventLoop *getIOLoop(size_t id) const; + trantor::EventLoop *getIOLoop(size_t id) const; void stopListening(); - std::vector ioLoops_; + std::vector ioLoops_; private: struct ListenerInfo { @@ -86,9 +86,9 @@ private: }; std::vector listeners_; std::vector > servers_; - std::vector > + std::vector > listeningloopThreads_; - std::shared_ptr ioLoopThreadPoolPtr_; + std::shared_ptr ioLoopThreadPoolPtr_; }; } // namespace drogon diff --git a/web_backends/drogon/drogon/lib/src/PluginsManager.cc b/web_backends/drogon/drogon/lib/src/PluginsManager.cc index 785dfa0..c33259f 100644 --- a/web_backends/drogon/drogon/lib/src/PluginsManager.cc +++ b/web_backends/drogon/drogon/lib/src/PluginsManager.cc @@ -13,7 +13,7 @@ */ #include "PluginsManager.h" -#include "core/log/logger.h" +#include using namespace drogon; diff --git a/web_backends/drogon/drogon/lib/src/PluginsManager.h b/web_backends/drogon/drogon/lib/src/PluginsManager.h index be5a137..e49aa50 100644 --- a/web_backends/drogon/drogon/lib/src/PluginsManager.h +++ b/web_backends/drogon/drogon/lib/src/PluginsManager.h @@ -19,7 +19,7 @@ namespace drogon { using PluginBasePtr = std::unique_ptr; -class PluginsManager : NonCopyable { +class PluginsManager : trantor::NonCopyable { public: void initializeAllPlugins( const Json::Value &configs, diff --git a/web_backends/drogon/drogon/lib/src/SharedLibManager.cc b/web_backends/drogon/drogon/lib/src/SharedLibManager.cc index 2da4e96..bd978f9 100644 --- a/web_backends/drogon/drogon/lib/src/SharedLibManager.cc +++ b/web_backends/drogon/drogon/lib/src/SharedLibManager.cc @@ -17,7 +17,7 @@ #include #include -#include "core/log/logger.h" +#include #include #include static void forEachFileIn( diff --git a/web_backends/drogon/drogon/lib/src/SharedLibManager.h b/web_backends/drogon/drogon/lib/src/SharedLibManager.h index f339f7b..14c808d 100644 --- a/web_backends/drogon/drogon/lib/src/SharedLibManager.h +++ b/web_backends/drogon/drogon/lib/src/SharedLibManager.h @@ -15,7 +15,7 @@ #pragma once #include -#include "core/loops/event_loop_thread.h" +#include #include #include #include @@ -38,7 +38,7 @@ #endif namespace drogon { -class SharedLibManager : public NonCopyable { +class SharedLibManager : public trantor::NonCopyable { public: SharedLibManager(const std::vector &libPaths, const std::string &outputPath); @@ -57,7 +57,7 @@ private: void *loadLib(const std::string &soFile, void *oldHld); bool shouldCompileLib(const std::string &soFile, const struct stat &sourceStat); - TimerId timeId_; - EventLoopThread workingThread_; + trantor::TimerId timeId_; + trantor::EventLoopThread workingThread_; }; } // namespace drogon diff --git a/web_backends/drogon/drogon/lib/src/StaticFileRouter.cc b/web_backends/drogon/drogon/lib/src/StaticFileRouter.cc index d962dd8..6749ae4 100644 --- a/web_backends/drogon/drogon/lib/src/StaticFileRouter.cc +++ b/web_backends/drogon/drogon/lib/src/StaticFileRouter.cc @@ -31,7 +31,7 @@ using namespace drogon; -void StaticFileRouter::init(const std::vector &ioloops) { +void StaticFileRouter::init(const std::vector &ioloops) { // Max timeout up to about 70 days; staticFilesCacheMap_ = decltype(staticFilesCacheMap_)( new IOThreadStorage > >); diff --git a/web_backends/drogon/drogon/lib/src/StaticFileRouter.h b/web_backends/drogon/drogon/lib/src/StaticFileRouter.h index bc9e477..92f68e0 100644 --- a/web_backends/drogon/drogon/lib/src/StaticFileRouter.h +++ b/web_backends/drogon/drogon/lib/src/StaticFileRouter.h @@ -40,7 +40,7 @@ public: void setBrStatic(bool useBrStatic) { brStaticFlag_ = useBrStatic; } - void init(const std::vector &ioloops); + void init(const std::vector &ioloops); void sendStaticFileResponse( const std::string &filePath, diff --git a/web_backends/drogon/drogon/lib/src/TaskTimeoutFlag.cc b/web_backends/drogon/drogon/lib/src/TaskTimeoutFlag.cc index 232ff5d..a51e2ec 100644 --- a/web_backends/drogon/drogon/lib/src/TaskTimeoutFlag.cc +++ b/web_backends/drogon/drogon/lib/src/TaskTimeoutFlag.cc @@ -15,7 +15,7 @@ #include "TaskTimeoutFlag.h" using namespace drogon; -TaskTimeoutFlag::TaskTimeoutFlag(EventLoop *loop, +TaskTimeoutFlag::TaskTimeoutFlag(trantor::EventLoop *loop, const std::chrono::duration &timeout, std::function timeoutCallback) : loop_(loop), timeout_(timeout), timeoutFunc_(timeoutCallback) { diff --git a/web_backends/drogon/drogon/lib/src/TaskTimeoutFlag.h b/web_backends/drogon/drogon/lib/src/TaskTimeoutFlag.h index c4cbf13..2388e56 100644 --- a/web_backends/drogon/drogon/lib/src/TaskTimeoutFlag.h +++ b/web_backends/drogon/drogon/lib/src/TaskTimeoutFlag.h @@ -11,7 +11,7 @@ * Drogon * */ -#include "core/loops/event_loop.h" +#include #include #include #include @@ -19,10 +19,10 @@ #include namespace drogon { -class TaskTimeoutFlag : public NonCopyable, +class TaskTimeoutFlag : public trantor::NonCopyable, public std::enable_shared_from_this { public: - TaskTimeoutFlag(EventLoop *loop, + TaskTimeoutFlag(trantor::EventLoop *loop, const std::chrono::duration &timeout, std::function timeoutCallback); bool done(); @@ -30,7 +30,7 @@ public: private: std::atomic isDone_{ false }; - EventLoop *loop_; + trantor::EventLoop *loop_; std::chrono::duration timeout_; std::function timeoutFunc_; }; diff --git a/web_backends/drogon/drogon/lib/src/Utilities.cc b/web_backends/drogon/drogon/lib/src/Utilities.cc index 1727120..b5302b9 100644 --- a/web_backends/drogon/drogon/lib/src/Utilities.cc +++ b/web_backends/drogon/drogon/lib/src/Utilities.cc @@ -14,7 +14,7 @@ #include -#include "core/log/logger.h" +#include #ifdef OPENSSL_FOUND #include #include @@ -838,7 +838,7 @@ std::string gzipDecompress(const char *data, const size_t ndata) { } } -char *getHttpFullDate(const Date &date) { +char *getHttpFullDate(const trantor::Date &date) { static thread_local int64_t lastSecond = 0; static thread_local char lastTimeString[128] = { 0 }; auto nowSecond = date.microSecondsSinceEpoch() / MICRO_SECONDS_PRE_SEC; @@ -851,7 +851,7 @@ char *getHttpFullDate(const Date &date) { sizeof(lastTimeString)); return lastTimeString; } -Date getHttpDate(const std::string &httpFullDateString) { +trantor::Date getHttpDate(const std::string &httpFullDateString) { static const std::array formats = { // RFC822 (default) "%a, %d %b %Y %H:%M:%S", @@ -866,11 +866,11 @@ Date getHttpDate(const std::string &httpFullDateString) { for (const char *format : formats) { if (strptime(httpFullDateString.c_str(), format, &tmptm) != NULL) { auto epoch = timegm(&tmptm); - return Date(epoch * MICRO_SECONDS_PRE_SEC); + return trantor::Date(epoch * MICRO_SECONDS_PRE_SEC); } } LOG_WARN << "invalid datetime format: '" << httpFullDateString << "'"; - return Date((std::numeric_limits::max)()); + return trantor::Date((std::numeric_limits::max)()); } std::string formattedString(const char *format, ...) { std::string strBuffer(128, 0); diff --git a/web_backends/drogon/drogon/lib/src/WebSocketClientImpl.cc b/web_backends/drogon/drogon/lib/src/WebSocketClientImpl.cc index 3723ef5..8060577 100644 --- a/web_backends/drogon/drogon/lib/src/WebSocketClientImpl.cc +++ b/web_backends/drogon/drogon/lib/src/WebSocketClientImpl.cc @@ -21,7 +21,7 @@ #include "WebSocketConnectionImpl.h" #include -#include "core/net/inet_address.h" +#include #ifdef OPENSSL_FOUND #include #else @@ -29,7 +29,7 @@ #endif using namespace drogon; - +using namespace trantor; WebSocketClientImpl::~WebSocketClientImpl() { } @@ -39,7 +39,7 @@ WebSocketConnectionPtr WebSocketClientImpl::getConnection() { void WebSocketClientImpl::createTcpClient() { LOG_TRACE << "New TcpClient," << serverAddr_.toIpPort(); tcpClientPtr_ = - std::make_shared(loop_, serverAddr_, "httpClient"); + std::make_shared(loop_, serverAddr_, "httpClient"); if (useSSL_) { tcpClientPtr_->enableSSL(useOldTLS_, validateCert_, domain_); } @@ -47,7 +47,7 @@ void WebSocketClientImpl::createTcpClient() { std::weak_ptr weakPtr = thisPtr; tcpClientPtr_->setConnectionCallback( - [weakPtr](const TcpConnectionPtr &connPtr) { + [weakPtr](const trantor::TcpConnectionPtr &connPtr) { auto thisPtr = weakPtr.lock(); if (!thisPtr) return; @@ -74,8 +74,8 @@ void WebSocketClientImpl::createTcpClient() { thisPtr->loop_->runAfter(1.0, [thisPtr]() { thisPtr->reconnect(); }); }); tcpClientPtr_->setMessageCallback( - [weakPtr](const TcpConnectionPtr &connPtr, - MsgBuffer *msg) { + [weakPtr](const trantor::TcpConnectionPtr &connPtr, + trantor::MsgBuffer *msg) { auto thisPtr = weakPtr.lock(); if (thisPtr) { thisPtr->onRecvMessage(connPtr, msg); @@ -124,12 +124,12 @@ void WebSocketClientImpl::connectToServerInLoop() { if (serverAddr_.ipNetEndian() == 0 && !hasIpv6Address && !domain_.empty() && serverAddr_.portNetEndian() != 0) { if (!resolver_) { - resolver_ = Resolver::newResolver(loop_); + resolver_ = trantor::Resolver::newResolver(loop_); } resolver_->resolve( domain_, [thisPtr = shared_from_this(), - hasIpv6Address](const InetAddress &addr) { + hasIpv6Address](const trantor::InetAddress &addr) { thisPtr->loop_->runInLoop([thisPtr, addr, hasIpv6Address]() { auto port = thisPtr->serverAddr_.portNetEndian(); thisPtr->serverAddr_ = addr; @@ -163,15 +163,15 @@ void WebSocketClientImpl::connectToServerInLoop() { } void WebSocketClientImpl::onRecvWsMessage( - const TcpConnectionPtr &connPtr, - MsgBuffer *msgBuffer) { + const trantor::TcpConnectionPtr &connPtr, + trantor::MsgBuffer *msgBuffer) { assert(websockConnPtr_); websockConnPtr_->onNewMessage(connPtr, msgBuffer); } void WebSocketClientImpl::onRecvMessage( - const TcpConnectionPtr &connPtr, - MsgBuffer *msgBuffer) { + const trantor::TcpConnectionPtr &connPtr, + trantor::MsgBuffer *msgBuffer) { if (upgraded_) { onRecvWsMessage(connPtr, msgBuffer); return; @@ -244,8 +244,8 @@ void WebSocketClientImpl::reconnect() { connectToServerInLoop(); } -WebSocketClientImpl::WebSocketClientImpl(EventLoop *loop, - const InetAddress &addr, +WebSocketClientImpl::WebSocketClientImpl(trantor::EventLoop *loop, + const trantor::InetAddress &addr, bool useSSL, bool useOldTLS, bool validateCert) : @@ -256,7 +256,7 @@ WebSocketClientImpl::WebSocketClientImpl(EventLoop *loop, validateCert_(validateCert) { } -WebSocketClientImpl::WebSocketClientImpl(EventLoop *loop, +WebSocketClientImpl::WebSocketClientImpl(trantor::EventLoop *loop, const std::string &hostString, bool useOldTLS, bool validateCert) : @@ -325,8 +325,8 @@ WebSocketClientImpl::WebSocketClientImpl(EventLoop *loop, LOG_TRACE << "userSSL=" << useSSL_ << " domain=" << domain_; } -void WebSocketClientImpl::sendReq(const TcpConnectionPtr &connPtr) { - MsgBuffer buffer; +void WebSocketClientImpl::sendReq(const trantor::TcpConnectionPtr &connPtr) { + trantor::MsgBuffer buffer; assert(upgradeRequest_); auto implPtr = static_cast(upgradeRequest_.get()); implPtr->appendToBuffer(&buffer); @@ -356,13 +356,13 @@ void WebSocketClientImpl::connectToServer( WebSocketClientPtr WebSocketClient::newWebSocketClient(const std::string &ip, uint16_t port, bool useSSL, - EventLoop *loop, + trantor::EventLoop *loop, bool useOldTLS, bool validateCert) { bool isIpv6 = ip.find(':') == std::string::npos ? false : true; return std::make_shared( loop == nullptr ? HttpAppFrameworkImpl::instance().getLoop() : loop, - InetAddress(ip, port, isIpv6), + trantor::InetAddress(ip, port, isIpv6), useSSL, useOldTLS, validateCert); @@ -370,7 +370,7 @@ WebSocketClientPtr WebSocketClient::newWebSocketClient(const std::string &ip, WebSocketClientPtr WebSocketClient::newWebSocketClient( const std::string &hostString, - EventLoop *loop, + trantor::EventLoop *loop, bool useOldTLS, bool validateCert) { return std::make_shared( diff --git a/web_backends/drogon/drogon/lib/src/WebSocketClientImpl.h b/web_backends/drogon/drogon/lib/src/WebSocketClientImpl.h index 664d632..b6f0bd7 100644 --- a/web_backends/drogon/drogon/lib/src/WebSocketClientImpl.h +++ b/web_backends/drogon/drogon/lib/src/WebSocketClientImpl.h @@ -16,8 +16,8 @@ #include "impl_forwards.h" #include -#include "core/loops/event_loop.h" -#include "core/net/tcp_client.h" +#include +#include #include #include @@ -47,17 +47,17 @@ public: void connectToServer(const HttpRequestPtr &request, const WebSocketRequestCallback &callback) override; - EventLoop *getLoop() override { + trantor::EventLoop *getLoop() override { return loop_; } - WebSocketClientImpl(EventLoop *loop, - const InetAddress &addr, + WebSocketClientImpl(trantor::EventLoop *loop, + const trantor::InetAddress &addr, bool useSSL = false, bool useOldTLS = false, bool validateCert = true); - WebSocketClientImpl(EventLoop *loop, + WebSocketClientImpl(trantor::EventLoop *loop, const std::string &hostString, bool useOldTLS = false, bool validateCert = true); @@ -65,9 +65,9 @@ public: ~WebSocketClientImpl() override; private: - std::shared_ptr tcpClientPtr_; - EventLoop *loop_; - InetAddress serverAddr_; + std::shared_ptr tcpClientPtr_; + trantor::EventLoop *loop_; + trantor::InetAddress serverAddr_; std::string domain_; bool useSSL_{ false }; bool useOldTLS_{ false }; @@ -89,13 +89,13 @@ private: WebSocketConnectionImplPtr websockConnPtr_; void connectToServerInLoop(); - void sendReq(const TcpConnectionPtr &connPtr); - void onRecvMessage(const TcpConnectionPtr &, MsgBuffer *); - void onRecvWsMessage(const TcpConnectionPtr &, - MsgBuffer *); + void sendReq(const trantor::TcpConnectionPtr &connPtr); + void onRecvMessage(const trantor::TcpConnectionPtr &, trantor::MsgBuffer *); + void onRecvWsMessage(const trantor::TcpConnectionPtr &, + trantor::MsgBuffer *); void reconnect(); void createTcpClient(); - std::shared_ptr resolver_; + std::shared_ptr resolver_; }; } // namespace drogon diff --git a/web_backends/drogon/drogon/lib/src/WebSocketConnectionImpl.cc b/web_backends/drogon/drogon/lib/src/WebSocketConnectionImpl.cc index abafe7c..2195f9d 100644 --- a/web_backends/drogon/drogon/lib/src/WebSocketConnectionImpl.cc +++ b/web_backends/drogon/drogon/lib/src/WebSocketConnectionImpl.cc @@ -18,7 +18,7 @@ using namespace drogon; WebSocketConnectionImpl::WebSocketConnectionImpl( - const TcpConnectionPtr &conn, + const trantor::TcpConnectionPtr &conn, bool isServer) : tcpConnectionPtr_(conn), localAddr_(conn->localAddr()), @@ -133,10 +133,10 @@ void WebSocketConnectionImpl::send(const std::string &msg, const WebSocketMessageType type) { send(msg.data(), msg.length(), type); } -const InetAddress &WebSocketConnectionImpl::localAddr() const { +const trantor::InetAddress &WebSocketConnectionImpl::localAddr() const { return localAddr_; } -const InetAddress &WebSocketConnectionImpl::peerAddr() const { +const trantor::InetAddress &WebSocketConnectionImpl::peerAddr() const { return peerAddr_; } @@ -189,7 +189,7 @@ void WebSocketConnectionImpl::disablePing() { } } -bool WebSocketMessageParser::parse(MsgBuffer *buffer) { +bool WebSocketMessageParser::parse(trantor::MsgBuffer *buffer) { // According to the rfc6455 gotAll_ = false; if (buffer->readableBytes() >= 2) { @@ -305,8 +305,8 @@ bool WebSocketMessageParser::parse(MsgBuffer *buffer) { } void WebSocketConnectionImpl::onNewMessage( - const TcpConnectionPtr &connPtr, - MsgBuffer *buffer) { + const trantor::TcpConnectionPtr &connPtr, + trantor::MsgBuffer *buffer) { while (buffer->readableBytes() > 0) { auto success = parser_.parse(buffer); if (success) { @@ -338,7 +338,7 @@ void WebSocketConnectionImpl::onNewMessage( } void WebSocketConnectionImpl::disablePingInLoop() { - if (pingTimerId_ != InvalidTimerId) { + if (pingTimerId_ != trantor::InvalidTimerId) { tcpConnectionPtr_->getLoop()->invalidateTimer(pingTimerId_); } } diff --git a/web_backends/drogon/drogon/lib/src/WebSocketConnectionImpl.h b/web_backends/drogon/drogon/lib/src/WebSocketConnectionImpl.h index 460b36d..eb42062 100644 --- a/web_backends/drogon/drogon/lib/src/WebSocketConnectionImpl.h +++ b/web_backends/drogon/drogon/lib/src/WebSocketConnectionImpl.h @@ -16,7 +16,7 @@ #include "impl_forwards.h" #include -#include "core/net/tcp_connection.h" +#include #include namespace drogon { @@ -25,7 +25,7 @@ using WebSocketConnectionImplPtr = std::shared_ptr; class WebSocketMessageParser { public: - bool parse(MsgBuffer *buffer); + bool parse(trantor::MsgBuffer *buffer); bool gotAll(std::string &message, WebSocketMessageType &type) { assert(message.empty()); if (!gotAll_) @@ -44,9 +44,9 @@ private: class WebSocketConnectionImpl final : public WebSocketConnection, public std::enable_shared_from_this, - public NonCopyable { + public trantor::NonCopyable { public: - explicit WebSocketConnectionImpl(const TcpConnectionPtr &conn, + explicit WebSocketConnectionImpl(const trantor::TcpConnectionPtr &conn, bool isServer = true); ~WebSocketConnectionImpl() override; @@ -58,8 +58,8 @@ public: const std::string &msg, const WebSocketMessageType type = WebSocketMessageType::Text) override; - const InetAddress &localAddr() const override; - const InetAddress &peerAddr() const override; + const trantor::InetAddress &localAddr() const override; + const trantor::InetAddress &peerAddr() const override; bool connected() const override; bool disconnected() const override; @@ -85,22 +85,22 @@ public: closeCallback_ = callback; } - void onNewMessage(const TcpConnectionPtr &connPtr, - MsgBuffer *buffer); + void onNewMessage(const trantor::TcpConnectionPtr &connPtr, + trantor::MsgBuffer *buffer); void onClose() { - if (pingTimerId_ != InvalidTimerId) + if (pingTimerId_ != trantor::InvalidTimerId) tcpConnectionPtr_->getLoop()->invalidateTimer(pingTimerId_); closeCallback_(shared_from_this()); } private: - TcpConnectionPtr tcpConnectionPtr_; - InetAddress localAddr_; - InetAddress peerAddr_; + trantor::TcpConnectionPtr tcpConnectionPtr_; + trantor::InetAddress localAddr_; + trantor::InetAddress peerAddr_; bool isServer_{ true }; WebSocketMessageParser parser_; - TimerId pingTimerId_{ InvalidTimerId }; + trantor::TimerId pingTimerId_{ trantor::InvalidTimerId }; std::vector masks_; std::atomic usingMask_; diff --git a/web_backends/drogon/drogon/lib/src/WebsocketControllersRouter.h b/web_backends/drogon/drogon/lib/src/WebsocketControllersRouter.h index 88a4279..4e4293d 100644 --- a/web_backends/drogon/drogon/lib/src/WebsocketControllersRouter.h +++ b/web_backends/drogon/drogon/lib/src/WebsocketControllersRouter.h @@ -28,7 +28,7 @@ namespace drogon { class HttpAppFrameworkImpl; -class WebsocketControllersRouter : public NonCopyable { +class WebsocketControllersRouter : public trantor::NonCopyable { public: WebsocketControllersRouter( const std::vector; class Resolver; - +} // namespace trantor namespace drogon { using HttpAsyncCallback = diff --git a/web_backends/drogon/drogon/lib/tests/integration_test/client/main.cc b/web_backends/drogon/drogon/lib/tests/integration_test/client/main.cc index e01d837..c78e3d1 100644 --- a/web_backends/drogon/drogon/lib/tests/integration_test/client/main.cc +++ b/web_backends/drogon/drogon/lib/tests/integration_test/client/main.cc @@ -18,8 +18,8 @@ #include #include #include -#include "core/loops/event_loop_thread.h" -#include "core/net/tcp_client.h" +#include +#include #include #include @@ -889,7 +889,7 @@ DROGON_TEST(HttpsTest) { } int main(int argc, char **argv) { - Logger::setLogLevel(Logger::LogLevel::kDebug); + trantor::Logger::setLogLevel(trantor::Logger::LogLevel::kDebug); loadFileLengths(); std::promise p1; diff --git a/web_backends/drogon/drogon/lib/tests/integration_test/server/PipeliningTest.cc b/web_backends/drogon/drogon/lib/tests/integration_test/server/PipeliningTest.cc index dd82e18..647fe19 100644 --- a/web_backends/drogon/drogon/lib/tests/integration_test/server/PipeliningTest.cc +++ b/web_backends/drogon/drogon/lib/tests/integration_test/server/PipeliningTest.cc @@ -1,5 +1,5 @@ #include "PipeliningTest.h" -#include "core/loops/event_loop.h" +#include #include void PipeliningTest::asyncHandleHttpRequest( @@ -27,7 +27,7 @@ void PipeliningTest::asyncHandleHttpRequest( }); return; } - EventLoop::getEventLoopOfCurrentThread()->runAfter( + trantor::EventLoop::getEventLoopOfCurrentThread()->runAfter( delay, [c, callback]() { auto resp = HttpResponse::newHttpResponse(); auto str = utils::formattedString("

the %dth response

", c); diff --git a/web_backends/drogon/drogon/lib/tests/integration_test/server/TimeFilter.cc b/web_backends/drogon/drogon/lib/tests/integration_test/server/TimeFilter.cc index 7055ee8..b6d7074 100644 --- a/web_backends/drogon/drogon/lib/tests/integration_test/server/TimeFilter.cc +++ b/web_backends/drogon/drogon/lib/tests/integration_test/server/TimeFilter.cc @@ -7,18 +7,18 @@ void TimeFilter::doFilter(const HttpRequestPtr &req, FilterCallback &&cb, FilterChainCallback &&ccb) { - Date now = Date::date(); + trantor::Date now = trantor::Date::date(); if (!req->session()) { // no session support by framework,pls enable session auto resp = HttpResponse::newNotFoundResponse(); cb(resp); return; } - auto lastDate = req->session()->getOptional(VDate); + auto lastDate = req->session()->getOptional(VDate); if (lastDate) { LOG_TRACE << "last:" << lastDate->toFormattedString(false); - req->session()->modify(VDate, - [now](Date &vdate) { + req->session()->modify(VDate, + [now](trantor::Date &vdate) { vdate = now; }); LOG_TRACE << "update visitDate"; diff --git a/web_backends/drogon/drogon/lib/tests/integration_test/server/a-directory/page.html b/web_backends/drogon/drogon/lib/tests/integration_test/server/a-directory/page.html index 1e1919d..e1b1fc5 100644 --- a/web_backends/drogon/drogon/lib/tests/integration_test/server/a-directory/page.html +++ b/web_backends/drogon/drogon/lib/tests/integration_test/server/a-directory/page.html @@ -1,11 +1,11 @@

Build Status - Codacy Badge - Total alerts - Language grade: C/C++ - Join the chat at https://gitter.im/drogon-web/community - Docker image

+Codacy Badge +Total alerts +Language grade: C/C++ +Join the chat at https://gitter.im/drogon-web/community +Docker image

Overview (from an implicit page)

Drogon is a C++14/17-based HTTP application framework. Drogon can be used to easily build various types of web application server programs using C++. Drogon is the name of a dragon in the American TV series “Game of Thrones” that I really like.

@@ -13,28 +13,28 @@

Drogon’s main application platform is Linux. It also supports Mac OS and FreeBSD. Currently, it does not support windows. Its main features are as follows:

    -
  • Use a non-blocking I/O network lib based on epoll (kqueue under MacOS/FreeBSD) to provide high-concurrency, high-performance network IO, please visit the benchmarks page for more details;
  • -
  • Provide a completely asynchronous programming mode;
  • -
  • Support Http1.0/1.1 (server side and client side);
  • -
  • Based on template, a simple reflection mechanism is implemented to completely decouple the main program framework, controllers and views.
  • -
  • Support cookies and built-in sessions;
  • -
  • Support back-end rendering, the controller generates the data to the view to generate the Html page, the view is described by a “JSP-like” CSP file, the C++ code is embedded into the Html page by the CSP tag, and the drogon command-line tool automatically generates the C++ code file for compilation;
  • -
  • Support view page dynamic loading (dynamic compilation and loading at runtime);
  • -
  • Provide a convenient and flexible routing solution from the path to the controller handler;
  • -
  • Support filter chains to facilitate the execution of unified logic (such as login verification, Http Method constraint verification, etc.) before controllers;
  • -
  • Support https (based on OpenSSL);
  • -
  • Support WebSocket (server side and client side);
  • -
  • Support JSON format request and response, very friendly to the Restful API application development;
  • -
  • Support file download and upload;
  • -
  • Support gzip compression transmission;
  • -
  • Support pipelining;
  • -
  • Provide a lightweight command line tool, drogon_ctl, to simplify the creation of various classes in Drogon and the generation of view code;
  • -
  • Support non-blocking I/O based asynchronously reading and writing database (PostgreSQL and MySQL(MariaDB) database);
  • -
  • Support asynchronously reading and writing sqlite3 database based on thread pool;
  • -
  • Support ARM Architecture;
  • -
  • Provide a convenient lightweight ORM implementation that supports for regular object-to-database bidirectional mapping;
  • -
  • Support plugins which can be installed by the configuration file at load time;
  • -
  • Support AOP with build-in joinpoints.
  • +
  • Use a non-blocking I/O network lib based on epoll (kqueue under MacOS/FreeBSD) to provide high-concurrency, high-performance network IO, please visit the benchmarks page for more details;
  • +
  • Provide a completely asynchronous programming mode;
  • +
  • Support Http1.0/1.1 (server side and client side);
  • +
  • Based on template, a simple reflection mechanism is implemented to completely decouple the main program framework, controllers and views.
  • +
  • Support cookies and built-in sessions;
  • +
  • Support back-end rendering, the controller generates the data to the view to generate the Html page, the view is described by a “JSP-like” CSP file, the C++ code is embedded into the Html page by the CSP tag, and the drogon command-line tool automatically generates the C++ code file for compilation;
  • +
  • Support view page dynamic loading (dynamic compilation and loading at runtime);
  • +
  • Provide a convenient and flexible routing solution from the path to the controller handler;
  • +
  • Support filter chains to facilitate the execution of unified logic (such as login verification, Http Method constraint verification, etc.) before controllers;
  • +
  • Support https (based on OpenSSL);
  • +
  • Support WebSocket (server side and client side);
  • +
  • Support JSON format request and response, very friendly to the Restful API application development;
  • +
  • Support file download and upload;
  • +
  • Support gzip compression transmission;
  • +
  • Support pipelining;
  • +
  • Provide a lightweight command line tool, drogon_ctl, to simplify the creation of various classes in Drogon and the generation of view code;
  • +
  • Support non-blocking I/O based asynchronously reading and writing database (PostgreSQL and MySQL(MariaDB) database);
  • +
  • Support asynchronously reading and writing sqlite3 database based on thread pool;
  • +
  • Support ARM Architecture;
  • +
  • Provide a convenient lightweight ORM implementation that supports for regular object-to-database bidirectional mapping;
  • +
  • Support plugins which can be installed by the configuration file at load time;
  • +
  • Support AOP with build-in joinpoints.

A very simple example

@@ -44,146 +44,144 @@

Below is the main program of a typical drogon application:

c++ - #include <drogon/drogon.h> - using namespace drogon; - int main() - { - app().setLogPath("./"); - app().setLogLevel(Logger::kWarn); - app().addListener("0.0.0.0", 80); - app().setThreadNum(16); - app().enableRunAsDaemon(); - app().run(); - } -

+#include <drogon/drogon.h> +using namespace drogon; +int main() +{ + app().setLogPath("./"); + app().setLogLevel(trantor::Logger::kWarn); + app().addListener("0.0.0.0", 80); + app().setThreadNum(16); + app().enableRunAsDaemon(); + app().run(); +} +

It can be further simplified by using configuration file as follows:

c++ - #include <drogon/drogon.h> - using namespace drogon; - int main() - { - app().loadConfigFile("./config.json"); - app().run(); - } -

+#include <drogon/drogon.h> +using namespace drogon; +int main() +{ + app().loadConfigFile("./config.json"); + app().run(); +} +

Drogon provides some interfaces for adding controller logic directly in the main() function, for example, user can register a handler like this in Drogon:

c++ - app.registerHandler("/test?username={1}", - [](const HttpRequestPtr& req, - const std::function<void (const HttpResponsePtr &)> & callback, - const std::string &name) - { - Json::Value json; - json["result"]="ok"; - json["message"]=std::string("hello,")+name; - auto resp=HttpResponse::newHttpJsonResponse(json); - callback(resp); - }, - {Get,"LoginFilter"}); -

+app.registerHandler("/test?username={1}", + [](const HttpRequestPtr& req, + const std::function<void (const HttpResponsePtr &)> & callback, + const std::string &name) + { + Json::Value json; + json["result"]="ok"; + json["message"]=std::string("hello,")+name; + auto resp=HttpResponse::newHttpJsonResponse(json); + callback(resp); + }, + {Get,"LoginFilter"}); +

While such interfaces look intuitive, they are not suitable for complex business logic scenarios. Assuming there are tens or even hundreds of handlers that need to be registered in the framework, isn’t it a better practice to implement them separately in their respective classes? So unless your logic is very simple, we don’t recommend using above interfaces. Instead, we can create an HttpSimpleController as follows:

```c++ - /// The TestCtrl.h file - #pragma once - #include <drogon/HttpSimpleController.h> - using namespace drogon; - class TestCtrl:public drogon::HttpSimpleController - { - public: - virtual void asyncHandleHttpRequest(const HttpRequestPtr& req,const std::function<void (const HttpResponsePtr &)> & callback)override; - PATH_LIST_BEGIN - PATH_ADD("/test",Get); - PATH_LIST_END - }; -

+/// The TestCtrl.h file +#pragma once +#include <drogon/HttpSimpleController.h> +using namespace drogon; +class TestCtrl:public drogon::HttpSimpleController +{ +public: + virtual void asyncHandleHttpRequest(const HttpRequestPtr& req,const std::function<void (const HttpResponsePtr &)> & callback)override; + PATH_LIST_BEGIN + PATH_ADD("/test",Get); + PATH_LIST_END +};

/// The TestCtrl.cc file - #include “TestCtrl.h” - void TestCtrl::asyncHandleHttpRequest(const HttpRequestPtr& req, - const std::function<void (const HttpResponsePtr &)> & callback) - { +#include “TestCtrl.h” +void TestCtrl::asyncHandleHttpRequest(const HttpRequestPtr& req, + const std::function<void (const HttpResponsePtr &)> & callback) +{ //write your application logic here auto resp = HttpResponse::newHttpResponse(); resp->setBody(“<p>Hello, world!</p>”); resp->setExpiredTime(0); callback(resp); - } - ```

+} +```

Most of the above programs can be automatically generated by the command line tool drogon_ctl provided by drogon (The cammand is drogon_ctl create controller TestCtrl). All the user needs to do is add their own business logic. In the example, the controller returns a Hello, world! string when the client accesses the http://ip/test URL.

For JSON format response, we create the controller as follows:

```c++ - /// The header file - #pragma once - #include <drogon/HttpSimpleController.h> - using namespace drogon; - class JsonCtrl : public drogon::HttpSimpleController - { - public: - virtual void asyncHandleHttpRequest(const HttpRequestPtr &req, const std::function<void(const HttpResponsePtr &)> &callback) override; - PATH_LIST_BEGIN - //list path definitions here; - PATH_ADD("/json", Get); - PATH_LIST_END - }; -

+/// The header file +#pragma once +#include <drogon/HttpSimpleController.h> +using namespace drogon; +class JsonCtrl : public drogon::HttpSimpleController +{ + public: + virtual void asyncHandleHttpRequest(const HttpRequestPtr &req, const std::function<void(const HttpResponsePtr &)> &callback) override; + PATH_LIST_BEGIN + //list path definitions here; + PATH_ADD("/json", Get); + PATH_LIST_END +};

/// The source file - #include “JsonCtrl.h” - void JsonCtrl::asyncHandleHttpRequest(const HttpRequestPtr &req, - const std::function<void(const HttpResponsePtr &)> &callback) - { +#include “JsonCtrl.h” +void JsonCtrl::asyncHandleHttpRequest(const HttpRequestPtr &req, + const std::function<void(const HttpResponsePtr &)> &callback) +{ Json::Value ret; ret[“message”] = “Hello, World!”; auto resp = HttpResponse::newHttpJsonResponse(ret); callback(resp); - } - ```

+} +```

Let’s go a step further and create a demo RESTful API with the HttpController class, as shown below (Omit the source file):

c++ - /// The header file - #pragma once - #include <drogon/HttpController.h> - using namespace drogon; - namespace api - { - namespace v1 - { - class User : public drogon::HttpController<User> - { - public: - METHOD_LIST_BEGIN - //use METHOD_ADD to add your custom processing function here; - METHOD_ADD(User::getInfo, "/{1}", Get); //path is /api/v1/User/{arg1} - METHOD_ADD(User::getDetailInfo, "/{1}/detailinfo", Get); //path is /api/v1/User/{arg1}/detailinfo - METHOD_ADD(User::newUser, "/{1}", Post); //path is /api/v1/User/{arg1} - METHOD_LIST_END - //your declaration of processing function maybe like this: - void getInfo(const HttpRequestPtr &req, const std::function<void(const HttpResponsePtr &)> &callback, int userId) const; - void getDetailInfo(const HttpRequestPtr &req, const std::function<void(const HttpResponsePtr &)> &callback, int userId) const; - void newUser(const HttpRequestPtr &req, const std::function<void(const HttpResponsePtr &)> &callback, std::string &&userName); - public: - User() - { +/// The header file +#pragma once +#include <drogon/HttpController.h> +using namespace drogon; +namespace api +{ +namespace v1 +{ +class User : public drogon::HttpController<User> +{ + public: + METHOD_LIST_BEGIN + //use METHOD_ADD to add your custom processing function here; + METHOD_ADD(User::getInfo, "/{1}", Get); //path is /api/v1/User/{arg1} + METHOD_ADD(User::getDetailInfo, "/{1}/detailinfo", Get); //path is /api/v1/User/{arg1}/detailinfo + METHOD_ADD(User::newUser, "/{1}", Post); //path is /api/v1/User/{arg1} + METHOD_LIST_END + //your declaration of processing function maybe like this: + void getInfo(const HttpRequestPtr &req, const std::function<void(const HttpResponsePtr &)> &callback, int userId) const; + void getDetailInfo(const HttpRequestPtr &req, const std::function<void(const HttpResponsePtr &)> &callback, int userId) const; + void newUser(const HttpRequestPtr &req, const std::function<void(const HttpResponsePtr &)> &callback, std::string &&userName); + public: + User() + { LOG_DEBUG << "User constructor!"; - } - }; - } // namespace v1 - } // namespace api -

+ } +}; +} // namespace v1 +} // namespace api +

As you can see, users can use the HttpController to map paths and parameters at the same time. This is a very convenient way to create a RESTful API application.

In addition, you can also find that all handler interfaces are in asynchronous mode, where the response is returned by a callback object. This design is for performance reasons because in asynchronous mode the drogon application can handle a large number of concurrent requests with a small number of threads.

-

After compiling all of the above source files, we get a very simple web application. This is a good start. for more information, please visit the wiki site

\ No newline at end of file +

After compiling all of the above source files, we get a very simple web application. This is a good start. for more information, please visit the wiki site

diff --git a/web_backends/drogon/drogon/lib/tests/integration_test/server/api_v1_CoroTest.cc b/web_backends/drogon/drogon/lib/tests/integration_test/server/api_v1_CoroTest.cc index fa78999..352e1ca 100644 --- a/web_backends/drogon/drogon/lib/tests/integration_test/server/api_v1_CoroTest.cc +++ b/web_backends/drogon/drogon/lib/tests/integration_test/server/api_v1_CoroTest.cc @@ -5,7 +5,7 @@ Task<> CoroTest::get(HttpRequestPtr req, std::function callback) { // Force co_await to test awaiting works co_await drogon::sleepCoro( - EventLoop::getEventLoopOfCurrentThread(), + trantor::EventLoop::getEventLoopOfCurrentThread(), std::chrono::milliseconds(100)); auto resp = HttpResponse::newHttpResponse(); diff --git a/web_backends/drogon/drogon/lib/tests/integration_test/server/index.html b/web_backends/drogon/drogon/lib/tests/integration_test/server/index.html index 5d019ee..c9bb37d 100644 --- a/web_backends/drogon/drogon/lib/tests/integration_test/server/index.html +++ b/web_backends/drogon/drogon/lib/tests/integration_test/server/index.html @@ -1,11 +1,11 @@

Build Status - Codacy Badge - Total alerts - Language grade: C/C++ - Join the chat at https://gitter.im/drogon-web/community - Docker image

+Codacy Badge +Total alerts +Language grade: C/C++ +Join the chat at https://gitter.im/drogon-web/community +Docker image

Overview

Drogon is a C++14/17-based HTTP application framework. Drogon can be used to easily build various types of web application server programs using C++. Drogon is the name of a dragon in the American TV series “Game of Thrones” that I really like.

@@ -13,28 +13,28 @@

Drogon’s main application platform is Linux. It also supports Mac OS and FreeBSD. Currently, it does not support windows. Its main features are as follows:

    -
  • Use a non-blocking I/O network lib based on epoll (kqueue under MacOS/FreeBSD) to provide high-concurrency, high-performance network IO, please visit the benchmarks page for more details;
  • -
  • Provide a completely asynchronous programming mode;
  • -
  • Support Http1.0/1.1 (server side and client side);
  • -
  • Based on template, a simple reflection mechanism is implemented to completely decouple the main program framework, controllers and views.
  • -
  • Support cookies and built-in sessions;
  • -
  • Support back-end rendering, the controller generates the data to the view to generate the Html page, the view is described by a “JSP-like” CSP file, the C++ code is embedded into the Html page by the CSP tag, and the drogon command-line tool automatically generates the C++ code file for compilation;
  • -
  • Support view page dynamic loading (dynamic compilation and loading at runtime);
  • -
  • Provide a convenient and flexible routing solution from the path to the controller handler;
  • -
  • Support filter chains to facilitate the execution of unified logic (such as login verification, Http Method constraint verification, etc.) before controllers;
  • -
  • Support https (based on OpenSSL);
  • -
  • Support WebSocket (server side and client side);
  • -
  • Support JSON format request and response, very friendly to the Restful API application development;
  • -
  • Support file download and upload;
  • -
  • Support gzip compression transmission;
  • -
  • Support pipelining;
  • -
  • Provide a lightweight command line tool, drogon_ctl, to simplify the creation of various classes in Drogon and the generation of view code;
  • -
  • Support non-blocking I/O based asynchronously reading and writing database (PostgreSQL and MySQL(MariaDB) database);
  • -
  • Support asynchronously reading and writing sqlite3 database based on thread pool;
  • -
  • Support ARM Architecture;
  • -
  • Provide a convenient lightweight ORM implementation that supports for regular object-to-database bidirectional mapping;
  • -
  • Support plugins which can be installed by the configuration file at load time;
  • -
  • Support AOP with build-in joinpoints.
  • +
  • Use a non-blocking I/O network lib based on epoll (kqueue under MacOS/FreeBSD) to provide high-concurrency, high-performance network IO, please visit the benchmarks page for more details;
  • +
  • Provide a completely asynchronous programming mode;
  • +
  • Support Http1.0/1.1 (server side and client side);
  • +
  • Based on template, a simple reflection mechanism is implemented to completely decouple the main program framework, controllers and views.
  • +
  • Support cookies and built-in sessions;
  • +
  • Support back-end rendering, the controller generates the data to the view to generate the Html page, the view is described by a “JSP-like” CSP file, the C++ code is embedded into the Html page by the CSP tag, and the drogon command-line tool automatically generates the C++ code file for compilation;
  • +
  • Support view page dynamic loading (dynamic compilation and loading at runtime);
  • +
  • Provide a convenient and flexible routing solution from the path to the controller handler;
  • +
  • Support filter chains to facilitate the execution of unified logic (such as login verification, Http Method constraint verification, etc.) before controllers;
  • +
  • Support https (based on OpenSSL);
  • +
  • Support WebSocket (server side and client side);
  • +
  • Support JSON format request and response, very friendly to the Restful API application development;
  • +
  • Support file download and upload;
  • +
  • Support gzip compression transmission;
  • +
  • Support pipelining;
  • +
  • Provide a lightweight command line tool, drogon_ctl, to simplify the creation of various classes in Drogon and the generation of view code;
  • +
  • Support non-blocking I/O based asynchronously reading and writing database (PostgreSQL and MySQL(MariaDB) database);
  • +
  • Support asynchronously reading and writing sqlite3 database based on thread pool;
  • +
  • Support ARM Architecture;
  • +
  • Provide a convenient lightweight ORM implementation that supports for regular object-to-database bidirectional mapping;
  • +
  • Support plugins which can be installed by the configuration file at load time;
  • +
  • Support AOP with build-in joinpoints.

A very simple example

@@ -44,146 +44,144 @@

Below is the main program of a typical drogon application:

c++ - #include <drogon/drogon.h> - using namespace drogon; - int main() - { - app().setLogPath("./"); - app().setLogLevel(Logger::kWarn); - app().addListener("0.0.0.0", 80); - app().setThreadNum(16); - app().enableRunAsDaemon(); - app().run(); - } -

+#include <drogon/drogon.h> +using namespace drogon; +int main() +{ + app().setLogPath("./"); + app().setLogLevel(trantor::Logger::kWarn); + app().addListener("0.0.0.0", 80); + app().setThreadNum(16); + app().enableRunAsDaemon(); + app().run(); +} +

It can be further simplified by using configuration file as follows:

c++ - #include <drogon/drogon.h> - using namespace drogon; - int main() - { - app().loadConfigFile("./config.json"); - app().run(); - } -

+#include <drogon/drogon.h> +using namespace drogon; +int main() +{ + app().loadConfigFile("./config.json"); + app().run(); +} +

Drogon provides some interfaces for adding controller logic directly in the main() function, for example, user can register a handler like this in Drogon:

c++ - app.registerHandler("/test?username={1}", - [](const HttpRequestPtr& req, - const std::function<void (const HttpResponsePtr &)> & callback, - const std::string &name) - { - Json::Value json; - json["result"]="ok"; - json["message"]=std::string("hello,")+name; - auto resp=HttpResponse::newHttpJsonResponse(json); - callback(resp); - }, - {Get,"LoginFilter"}); -

+app.registerHandler("/test?username={1}", + [](const HttpRequestPtr& req, + const std::function<void (const HttpResponsePtr &)> & callback, + const std::string &name) + { + Json::Value json; + json["result"]="ok"; + json["message"]=std::string("hello,")+name; + auto resp=HttpResponse::newHttpJsonResponse(json); + callback(resp); + }, + {Get,"LoginFilter"}); +

While such interfaces look intuitive, they are not suitable for complex business logic scenarios. Assuming there are tens or even hundreds of handlers that need to be registered in the framework, isn’t it a better practice to implement them separately in their respective classes? So unless your logic is very simple, we don’t recommend using above interfaces. Instead, we can create an HttpSimpleController as follows:

```c++ - /// The TestCtrl.h file - #pragma once - #include <drogon/HttpSimpleController.h> - using namespace drogon; - class TestCtrl:public drogon::HttpSimpleController - { - public: - virtual void asyncHandleHttpRequest(const HttpRequestPtr& req,const std::function<void (const HttpResponsePtr &)> & callback)override; - PATH_LIST_BEGIN - PATH_ADD("/test",Get); - PATH_LIST_END - }; -

+/// The TestCtrl.h file +#pragma once +#include <drogon/HttpSimpleController.h> +using namespace drogon; +class TestCtrl:public drogon::HttpSimpleController +{ +public: + virtual void asyncHandleHttpRequest(const HttpRequestPtr& req,const std::function<void (const HttpResponsePtr &)> & callback)override; + PATH_LIST_BEGIN + PATH_ADD("/test",Get); + PATH_LIST_END +};

/// The TestCtrl.cc file - #include “TestCtrl.h” - void TestCtrl::asyncHandleHttpRequest(const HttpRequestPtr& req, - const std::function<void (const HttpResponsePtr &)> & callback) - { +#include “TestCtrl.h” +void TestCtrl::asyncHandleHttpRequest(const HttpRequestPtr& req, + const std::function<void (const HttpResponsePtr &)> & callback) +{ //write your application logic here auto resp = HttpResponse::newHttpResponse(); resp->setBody(“<p>Hello, world!</p>”); resp->setExpiredTime(0); callback(resp); - } - ```

+} +```

Most of the above programs can be automatically generated by the command line tool drogon_ctl provided by drogon (The cammand is drogon_ctl create controller TestCtrl). All the user needs to do is add their own business logic. In the example, the controller returns a Hello, world! string when the client accesses the http://ip/test URL.

For JSON format response, we create the controller as follows:

```c++ - /// The header file - #pragma once - #include <drogon/HttpSimpleController.h> - using namespace drogon; - class JsonCtrl : public drogon::HttpSimpleController - { - public: - virtual void asyncHandleHttpRequest(const HttpRequestPtr &req, const std::function<void(const HttpResponsePtr &)> &callback) override; - PATH_LIST_BEGIN - //list path definitions here; - PATH_ADD("/json", Get); - PATH_LIST_END - }; -

+/// The header file +#pragma once +#include <drogon/HttpSimpleController.h> +using namespace drogon; +class JsonCtrl : public drogon::HttpSimpleController +{ + public: + virtual void asyncHandleHttpRequest(const HttpRequestPtr &req, const std::function<void(const HttpResponsePtr &)> &callback) override; + PATH_LIST_BEGIN + //list path definitions here; + PATH_ADD("/json", Get); + PATH_LIST_END +};

/// The source file - #include “JsonCtrl.h” - void JsonCtrl::asyncHandleHttpRequest(const HttpRequestPtr &req, - const std::function<void(const HttpResponsePtr &)> &callback) - { +#include “JsonCtrl.h” +void JsonCtrl::asyncHandleHttpRequest(const HttpRequestPtr &req, + const std::function<void(const HttpResponsePtr &)> &callback) +{ Json::Value ret; ret[“message”] = “Hello, World!”; auto resp = HttpResponse::newHttpJsonResponse(ret); callback(resp); - } - ```

+} +```

Let’s go a step further and create a demo RESTful API with the HttpController class, as shown below (Omit the source file):

c++ - /// The header file - #pragma once - #include <drogon/HttpController.h> - using namespace drogon; - namespace api - { - namespace v1 - { - class User : public drogon::HttpController<User> - { - public: - METHOD_LIST_BEGIN - //use METHOD_ADD to add your custom processing function here; - METHOD_ADD(User::getInfo, "/{1}", Get); //path is /api/v1/User/{arg1} - METHOD_ADD(User::getDetailInfo, "/{1}/detailinfo", Get); //path is /api/v1/User/{arg1}/detailinfo - METHOD_ADD(User::newUser, "/{1}", Post); //path is /api/v1/User/{arg1} - METHOD_LIST_END - //your declaration of processing function maybe like this: - void getInfo(const HttpRequestPtr &req, const std::function<void(const HttpResponsePtr &)> &callback, int userId) const; - void getDetailInfo(const HttpRequestPtr &req, const std::function<void(const HttpResponsePtr &)> &callback, int userId) const; - void newUser(const HttpRequestPtr &req, const std::function<void(const HttpResponsePtr &)> &callback, std::string &&userName); - public: - User() - { +/// The header file +#pragma once +#include <drogon/HttpController.h> +using namespace drogon; +namespace api +{ +namespace v1 +{ +class User : public drogon::HttpController<User> +{ + public: + METHOD_LIST_BEGIN + //use METHOD_ADD to add your custom processing function here; + METHOD_ADD(User::getInfo, "/{1}", Get); //path is /api/v1/User/{arg1} + METHOD_ADD(User::getDetailInfo, "/{1}/detailinfo", Get); //path is /api/v1/User/{arg1}/detailinfo + METHOD_ADD(User::newUser, "/{1}", Post); //path is /api/v1/User/{arg1} + METHOD_LIST_END + //your declaration of processing function maybe like this: + void getInfo(const HttpRequestPtr &req, const std::function<void(const HttpResponsePtr &)> &callback, int userId) const; + void getDetailInfo(const HttpRequestPtr &req, const std::function<void(const HttpResponsePtr &)> &callback, int userId) const; + void newUser(const HttpRequestPtr &req, const std::function<void(const HttpResponsePtr &)> &callback, std::string &&userName); + public: + User() + { LOG_DEBUG << "User constructor!"; - } - }; - } // namespace v1 - } // namespace api -

+ } +}; +} // namespace v1 +} // namespace api +

As you can see, users can use the HttpController to map paths and parameters at the same time. This is a very convenient way to create a RESTful API application.

In addition, you can also find that all handler interfaces are in asynchronous mode, where the response is returned by a callback object. This design is for performance reasons because in asynchronous mode the drogon application can handle a large number of concurrent requests with a small number of threads.

-

After compiling all of the above source files, we get a very simple web application. This is a good start. for more information, please visit the wiki site

\ No newline at end of file +

After compiling all of the above source files, we get a very simple web application. This is a good start. for more information, please visit the wiki site

diff --git a/web_backends/drogon/drogon/lib/tests/integration_test/server/main.cc b/web_backends/drogon/drogon/lib/tests/integration_test/server/main.cc index 9a7dfc4..dc0e728 100644 --- a/web_backends/drogon/drogon/lib/tests/integration_test/server/main.cc +++ b/web_backends/drogon/drogon/lib/tests/integration_test/server/main.cc @@ -240,8 +240,8 @@ int main() { // AOP example app().registerBeginningAdvice( []() { LOG_DEBUG << "Event loop is running!"; }); - app().registerNewConnectionAdvice([](const InetAddress &peer, - const InetAddress &local) { + app().registerNewConnectionAdvice([](const trantor::InetAddress &peer, + const trantor::InetAddress &local) { LOG_DEBUG << "New connection: " << peer.toIpPort() << "-->" << local.toIpPort(); return true; @@ -336,7 +336,7 @@ int main() { }); std::cout << "Date: " << std::string{ drogon::utils::getHttpFullDate( - Date::now()) } + trantor::Date::now()) } << std::endl; app().run(); } diff --git a/web_backends/drogon/drogon/lib/tests/unittests/CacheMapTest.cc b/web_backends/drogon/drogon/lib/tests/unittests/CacheMapTest.cc index 05d321b..ddea631 100644 --- a/web_backends/drogon/drogon/lib/tests/unittests/CacheMapTest.cc +++ b/web_backends/drogon/drogon/lib/tests/unittests/CacheMapTest.cc @@ -1,7 +1,7 @@ #include #include #include -#include "core/loops/event_loop_thread.h" +#include #include @@ -9,7 +9,7 @@ using namespace drogon; using namespace std::chrono_literals; DROGON_TEST(CacheMapTest) { - EventLoopThread loopThread; + trantor::EventLoopThread loopThread; loopThread.run(); drogon::CacheMap cache(loopThread.getLoop(), 0.1, diff --git a/web_backends/drogon/drogon/lib/tests/unittests/CookieTest.cc b/web_backends/drogon/drogon/lib/tests/unittests/CookieTest.cc index b4308c0..31f75fc 100644 --- a/web_backends/drogon/drogon/lib/tests/unittests/CookieTest.cc +++ b/web_backends/drogon/drogon/lib/tests/unittests/CookieTest.cc @@ -11,7 +11,7 @@ DROGON_TEST(CookieTest) { drogon::Cookie cookie3("test", "3"); cookie3.setDomain("drogon.org"); - cookie3.setExpiresDate(Date(1621561557000000L)); + cookie3.setExpiresDate(trantor::Date(1621561557000000L)); CHECK(cookie3.cookieString() == "Set-Cookie: test=3; Expires=Fri, 21 May 2021 01:45:57 GMT; " "Domain=drogon.org; HttpOnly\r\n"); diff --git a/web_backends/drogon/drogon/lib/tests/unittests/MsgBufferTest.cc b/web_backends/drogon/drogon/lib/tests/unittests/MsgBufferTest.cc index 1b3977b..2b38fc5 100644 --- a/web_backends/drogon/drogon/lib/tests/unittests/MsgBufferTest.cc +++ b/web_backends/drogon/drogon/lib/tests/unittests/MsgBufferTest.cc @@ -1,9 +1,9 @@ #include -#include "core/containers/msg_buffer.h" +#include #include #include - +using namespace trantor; DROGON_TEST(MsgBufferTest) { SUBSECTION(readableTest) { MsgBuffer buffer; diff --git a/web_backends/drogon/drogon/lib/tests/unittests/main.cc b/web_backends/drogon/drogon/lib/tests/unittests/main.cc index 48a75a5..ad4ea66 100644 --- a/web_backends/drogon/drogon/lib/tests/unittests/main.cc +++ b/web_backends/drogon/drogon/lib/tests/unittests/main.cc @@ -3,7 +3,7 @@ #include using namespace drogon; - +using namespace trantor; DROGON_TEST(TestFrameworkSelfTest) { CHECK(TEST_CTX->name() == "TestFrameworkSelfTest"); diff --git a/web_backends/drogon/drogon_web_server.cpp b/web_backends/drogon/drogon_web_server.cpp index 0359603..4b40a19 100644 --- a/web_backends/drogon/drogon_web_server.cpp +++ b/web_backends/drogon/drogon_web_server.cpp @@ -12,8 +12,8 @@ #include #include -#include "core/log/async_file_logger.h" -#include "core/net/tcp_connection.h" +#include +#include #include #include @@ -59,7 +59,7 @@ void DrogonWebServer::run() { LOG_TRACE << "Start to run..."; - AsyncFileLogger asyncFileLogger; + trantor::AsyncFileLogger asyncFileLogger; // Create dirs for cache files for (int i = 0; i < 256; ++i) { @@ -127,7 +127,7 @@ void DrogonWebServer::run() { asyncFileLogger.setFileName(baseName, ".log", _log_path); asyncFileLogger.startLogging(); - Logger::setOutputFunction( + trantor::Logger::setOutputFunction( [&](const char *msg, const uint64_t len) { asyncFileLogger.output(msg, len); }, @@ -192,11 +192,11 @@ void DrogonWebServer::run() { }); }*/ - // httpCtrlsRouterPtr_->init(ioLoops); - // httpSimpleCtrlsRouterPtr_->init(ioLoops); + //httpCtrlsRouterPtr_->init(ioLoops); + //httpSimpleCtrlsRouterPtr_->init(ioLoops); - // staticFileRouterPtr_->init(ioLoops); - // websockCtrlsRouterPtr_->init(); + //staticFileRouterPtr_->init(ioLoops); + //websockCtrlsRouterPtr_->init(); get_loop()->queueInLoop([this]() { // Let listener event loops run when everything is ready. @@ -209,14 +209,6 @@ void DrogonWebServer::run() { _beginning_advices.clear(); }); - if (_update_interval > 0) { - get_loop()->runEvery(_update_interval, [this]() { - this->update(); - }); - } - - // - get_loop()->loop(); } @@ -232,7 +224,7 @@ void DrogonWebServer::disable_session() { _use_session = false; } -// todo think about it +//todo think about it const std::string &DrogonWebServer::get_document_root() const { return _root_path; } @@ -248,8 +240,8 @@ const std::string &DrogonWebServer::get_upload_path() const { return _upload_path; } -const std::shared_ptr &DrogonWebServer::get_resolver() const { - static std::shared_ptr resolver = Resolver::newResolver(get_loop()); +const std::shared_ptr &DrogonWebServer::get_resolver() const { + static std::shared_ptr resolver = trantor::Resolver::newResolver(get_loop()); return resolver; } @@ -257,8 +249,8 @@ void DrogonWebServer::set_upload_path(const std::string &uploadPath) { _upload_path = uploadPath; } void DrogonWebServer::set_file_types(const std::vector &types) { - // staticFileRouterPtr_->setFileTypes(types); - // return *this; + //staticFileRouterPtr_->setFileTypes(types); + //return *this; } void DrogonWebServer::set_max_connection_num(size_t maxConnections) { @@ -294,8 +286,8 @@ void DrogonWebServer::set_log_path(const std::string &logPath, const std::string _logfile_base_name = logfileBaseName; _logfile_size = logfileSize; } -void DrogonWebServer::set_log_level(Logger::LogLevel level) { - Logger::setLogLevel(level); +void DrogonWebServer::set_log_level(trantor::Logger::LogLevel level) { + trantor::Logger::setLogLevel(level); } void DrogonWebServer::enable_sendfile(bool sendFile) { @@ -319,11 +311,11 @@ bool DrogonWebServer::is_brotli_enabled() const { } void DrogonWebServer::set_static_files_cache_time(int cacheTime) { - // staticFileRouterPtr_->setStaticFilesCacheTime(cacheTime); + //staticFileRouterPtr_->setStaticFilesCacheTime(cacheTime); } int DrogonWebServer::static_files_cache_time() const { - // return staticFileRouterPtr_->staticFilesCacheTime(); + //return staticFileRouterPtr_->staticFilesCacheTime(); return 0; } @@ -338,10 +330,10 @@ void DrogonWebServer::set_pipelining_requests_number(const size_t number) { } void DrogonWebServer::set_gzip_static(bool useGzipStatic) { - // staticFileRouterPtr_->setGzipStatic(useGzipStatic); + //staticFileRouterPtr_->setGzipStatic(useGzipStatic); } void DrogonWebServer::set_br_static(bool useGzipStatic) { - // staticFileRouterPtr_->setBrStatic(useGzipStatic); + //staticFileRouterPtr_->setBrStatic(useGzipStatic); } void DrogonWebServer::set_client_max_body_size(size_t maxSize) { @@ -362,18 +354,18 @@ const std::string &DrogonWebServer::get_home_page() const { } void DrogonWebServer::set_implicit_page_enable(bool useImplicitPage) { - // staticFileRouterPtr_->setImplicitPageEnable(useImplicitPage); + //staticFileRouterPtr_->setImplicitPageEnable(useImplicitPage); } bool DrogonWebServer::is_implicit_page_enabled() const { - // return staticFileRouterPtr_->isImplicitPageEnabled(); + //return staticFileRouterPtr_->isImplicitPageEnabled(); return false; } void DrogonWebServer::set_implicit_page(const std::string &implicitPageFile) { - // staticFileRouterPtr_->setImplicitPage(implicitPageFile); + //staticFileRouterPtr_->setImplicitPage(implicitPageFile); } const std::string &DrogonWebServer::get_implicit_page() const { - // return staticFileRouterPtr_->getImplicitPage(); + //return staticFileRouterPtr_->getImplicitPage(); static std::string s = ""; return s; } @@ -413,10 +405,10 @@ const std::pair &DrogonWebServer::get_float_precision return _float_precision_in_json; } -EventLoop *DrogonWebServer::get_loop() const { +trantor::EventLoop *DrogonWebServer::get_loop() const { return _loop; } -EventLoop *DrogonWebServer::get_io_loop(size_t id) const { +trantor::EventLoop *DrogonWebServer::get_io_loop(size_t id) const { assert(_listener_manager); return _listener_manager->getIOLoop(id); @@ -446,7 +438,7 @@ const std::string &DrogonWebServer::get_server_header_string() const { return _server_header; } -std::vector DrogonWebServer::get_listeners() const { +std::vector DrogonWebServer::get_listeners() const { return _listener_manager->getListeners(); } @@ -462,7 +454,7 @@ bool DrogonWebServer::support_ssl() const { } size_t DrogonWebServer::get_current_thread_index() const { - EventLoop *loop = EventLoop::getEventLoopOfCurrentThread(); + trantor::EventLoop *loop = trantor::EventLoop::getEventLoopOfCurrentThread(); if (loop) { return loop->index(); @@ -524,17 +516,17 @@ void DrogonWebServer::on_async_request(const HttpRequestImplPtr &req, std::funct } */ - // void HttpSimpleControllersRouter::route(const HttpRequestImplPtr &req,std::function &&callback) + //void HttpSimpleControllersRouter::route(const HttpRequestImplPtr &req,std::function &&callback) - // auto resp = HttpResponse::newHttpResponse(); - // resp->setBody("

Hello, world!

"); - // resp->setExpiredTime(0); - // callback(resp); + //auto resp = HttpResponse::newHttpResponse(); + //resp->setBody("

Hello, world!

"); + //resp->setExpiredTime(0); + //callback(resp); DRequest *request = DRequest::get(); request->server = this; request->request = std::shared_ptr(req); - request->callback = callback; // std::move(callback); + request->callback = callback; //std::move(callback); request->setup_url_stack(); @@ -573,7 +565,7 @@ void DrogonWebServer::on_new_websock_request(const HttpRequestImplPtr &req, std: }); }*/ } -void DrogonWebServer::on_connection(const TcpConnectionPtr &conn) { +void DrogonWebServer::on_connection(const trantor::TcpConnectionPtr &conn) { static std::mutex mtx; LOG_TRACE << "connect!!!" << _max_connection_num << " num=" << _connection_num.load(); @@ -644,13 +636,13 @@ void DrogonWebServer::find_session_for_request(const HttpRequestImplPtr &req) { } } -// to request -// void forward(const HttpRequestPtr &req, std::function &&callback,const std::string &hostString,double timeout); -// void forward(const HttpRequestImplPtr &req,std::function &&callback,const std::string &hostString,double timeout = 0); +//to request +//void forward(const HttpRequestPtr &req, std::function &&callback,const std::string &hostString,double timeout); +//void forward(const HttpRequestImplPtr &req,std::function &&callback,const std::string &hostString,double timeout = 0); -DrogonWebServer::DrogonWebServer() : +DrogonWebServer::DrogonWebServer() : _listener_manager(new ListenerManager()), WebServer() { - // staticFileRouterPtr_(new StaticFileRouter{}), + //staticFileRouterPtr_(new StaticFileRouter{}), /* httpCtrlsRouterPtr_(new HttpControllersRouter(*staticFileRouterPtr_, postRoutingAdvices_, @@ -665,14 +657,14 @@ DrogonWebServer::DrogonWebServer() : preHandlingAdvices_, preHandlingObservers_, postHandlingAdvices_)),*/ - // websockCtrlsRouterPtr_( + //websockCtrlsRouterPtr_( // new WebsocketControllersRouter(postRoutingAdvices_, // postRoutingObservers_)), - // listenerManagerPtr_(new ListenerManager), - // pluginsManagerPtr_(new PluginsManager), - // uploadPath_(rootPath_ + "uploads") { + //listenerManagerPtr_(new ListenerManager), + //pluginsManagerPtr_(new PluginsManager), + //uploadPath_(rootPath_ + "uploads") { - _loop = new EventLoop(); + _loop = new trantor::EventLoop(); //_listener_manager = new ListenerManager(); _upload_path = _root_path + "uploads"; diff --git a/web_backends/drogon/drogon_web_server.h b/web_backends/drogon/drogon_web_server.h index ae5ccb4..92edeb5 100644 --- a/web_backends/drogon/drogon_web_server.h +++ b/web_backends/drogon/drogon_web_server.h @@ -12,9 +12,9 @@ #include #include -#include "core/net/inet_address.h" -#include "core/net/resolver.h" -#include "core/log/logger.h" +#include +#include +#include #include "http/HttpRequestImpl.h" #include "http/HttpResponse.h" @@ -56,7 +56,7 @@ public: const std::string &get_upload_path() const; - const std::shared_ptr &get_resolver() const; + const std::shared_ptr &get_resolver() const; void set_upload_path(const std::string &uploadPath); void set_file_types(const std::vector &types); @@ -65,7 +65,7 @@ public: void set_max_connection_num_per_ip(size_t maxConnectionsPerIP); void set_log_path(const std::string &logPath, const std::string &logfileBaseName, size_t logfileSize); - void set_log_level(Logger::LogLevel level); + void set_log_level(trantor::Logger::LogLevel level); void enable_sendfile(bool sendFile); void enable_gzip(bool useGzip); bool is_gzip_enabled() const; @@ -110,8 +110,8 @@ public: const std::pair &get_float_precision_in_json() const; - EventLoop *get_loop() const; - EventLoop *get_io_loop(size_t id) const; + trantor::EventLoop *get_loop() const; + trantor::EventLoop *get_io_loop(size_t id) const; void set_server_header_field(const std::string &server); @@ -123,7 +123,7 @@ public: const std::string &get_server_header_string() const; - std::vector get_listeners() const; + std::vector get_listeners() const; bool use_sendfile() const; @@ -137,7 +137,7 @@ public: void on_async_request(const HttpRequestImplPtr &req, std::function &&callback); void on_new_websock_request(const HttpRequestImplPtr &req, std::function &&callback, const WebSocketConnectionImplPtr &wsConnPtr); - void on_connection(const TcpConnectionPtr &conn); + void on_connection(const trantor::TcpConnectionPtr &conn); void find_session_for_request(const HttpRequestImplPtr &req); @@ -197,10 +197,10 @@ protected: bool _enable_date_header{ true }; bool _reuse_port{ false }; - EventLoop *_loop; + trantor::EventLoop *_loop; std::vector > _beginning_advices; - std::vector > _new_connection_advices; + std::vector > _new_connection_advices; std::vector > _sync_advices; std::vector > _pre_sending_advices; }; diff --git a/web_backends/drogon/trantor/net/Channel.cc b/web_backends/drogon/trantor/net/Channel.cc new file mode 100644 index 0000000..f68c22d --- /dev/null +++ b/web_backends/drogon/trantor/net/Channel.cc @@ -0,0 +1,97 @@ +/** + * + * Channel.cc + * An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#include "Channel.h" +#include +#ifdef _WIN32 +#include "Wepoll.h" +#define POLLIN EPOLLIN +#define POLLPRI EPOLLPRI +#define POLLOUT EPOLLOUT +#define POLLHUP EPOLLHUP +#define POLLNVAL 0 +#define POLLERR EPOLLERR +#else +#include +#endif +#include +namespace trantor { +const int Channel::kNoneEvent = 0; + +const int Channel::kReadEvent = POLLIN | POLLPRI; +const int Channel::kWriteEvent = POLLOUT; + +Channel::Channel(EventLoop *loop, int fd) : + loop_(loop), fd_(fd), events_(0), revents_(0), index_(-1), tied_(false) { +} + +void Channel::remove() { + assert(events_ == kNoneEvent); + addedToLoop_ = false; + loop_->removeChannel(this); +} + +void Channel::update() { + loop_->updateChannel(this); +} + +void Channel::handleEvent() { + // LOG_TRACE<<"revents_="< guard = tie_.lock(); + if (guard) { + handleEventSafely(); + } + } else { + handleEventSafely(); + } +} +void Channel::handleEventSafely() { + if (eventCallback_) { + eventCallback_(); + return; + } + if ((revents_ & POLLHUP) && !(revents_ & POLLIN)) { + // LOG_TRACE<<"handle close"; + if (closeCallback_) + closeCallback_(); + } + if (revents_ & (POLLNVAL | POLLERR)) { + // LOG_TRACE<<"handle error"; + if (errorCallback_) + errorCallback_(); + } +#ifdef __linux__ + if (revents_ & (POLLIN | POLLPRI | POLLRDHUP)) +#else + if (revents_ & (POLLIN | POLLPRI)) +#endif + { + // LOG_TRACE<<"handle read"; + if (readCallback_) + readCallback_(); + } +#ifdef _WIN32 + if ((revents_ & POLLOUT) && !(revents_ & POLLHUP)) +#else + if (revents_ & POLLOUT) +#endif + { + // LOG_TRACE<<"handle write"; + if (writeCallback_) + writeCallback_(); + } +} + +} // namespace trantor diff --git a/web_backends/drogon/trantor/net/Channel.h b/web_backends/drogon/trantor/net/Channel.h new file mode 100644 index 0000000..7060ee5 --- /dev/null +++ b/web_backends/drogon/trantor/net/Channel.h @@ -0,0 +1,314 @@ +/** + * + * @file Channel.h + * @author An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +namespace trantor +{ +class EventLoop; +/** + * @brief This class is used to implement reactor pattern. A Channel object + * manages a socket fd. Users use a Channel object to receive write or read + * events on the socket it manages. + * + */ +class TRANTOR_EXPORT Channel : NonCopyable +{ + public: + using EventCallback = std::function; + /** + * @brief Construct a new Channel instance. + * + * @param loop The event loop in which the channel works. + * @param fd The socket fd. + */ + Channel(EventLoop *loop, int fd); + + /** + * @brief Set the read callback. + * + * @param cb The callback is called when read event occurs on the socket. + * @note One should call the enableReading() method to ensure that the + * callback would be called when some data is received on the socket. + */ + void setReadCallback(const EventCallback &cb) + { + readCallback_ = cb; + }; + void setReadCallback(EventCallback &&cb) + { + readCallback_ = std::move(cb); + } + + /** + * @brief Set the write callback. + * + * @param cb The callback is called when write event occurs on the socket. + * @note One should call the enableWriting() method to ensure that the + * callback would be called when the socket can be written. + */ + void setWriteCallback(const EventCallback &cb) + { + writeCallback_ = cb; + }; + void setWriteCallback(EventCallback &&cb) + { + writeCallback_ = std::move(cb); + } + + /** + * @brief Set the close callback. + * + * @param cb The callback is called when the socket is closed. + */ + void setCloseCallback(const EventCallback &cb) + { + closeCallback_ = cb; + } + void setCloseCallback(EventCallback &&cb) + { + closeCallback_ = std::move(cb); + } + + /** + * @brief Set the error callback. + * + * @param cb The callback is called when an error occurs on the socket. + */ + void setErrorCallback(const EventCallback &cb) + { + errorCallback_ = cb; + } + void setErrorCallback(EventCallback &&cb) + { + errorCallback_ = std::move(cb); + } + + /** + * @brief Set the event callback. + * + * @param cb The callback is called when any event occurs on the socket. + * @note If the event callback is set to the channel, any other callback + * wouldn't be called again. + */ + void setEventCallback(const EventCallback &cb) + { + eventCallback_ = cb; + } + void setEventCallback(EventCallback &&cb) + { + eventCallback_ = std::move(cb); + } + + /** + * @brief Return the fd of the socket. + * + * @return int + */ + int fd() const + { + return fd_; + } + + /** + * @brief Return the events enabled on the socket. + * + * @return int + */ + int events() const + { + return events_; + } + + /** + * @brief Return the events that occurred on the socket. + * + * @return int + */ + int revents() const + { + return revents_; + } + + /** + * @brief Check whether there is no event enabled on the socket. + * + * @return true + * @return false + */ + bool isNoneEvent() const + { + return events_ == kNoneEvent; + }; + + /** + * @brief Disable all events on the socket. + * + */ + void disableAll() + { + events_ = kNoneEvent; + update(); + } + + /** + * @brief Remove the socket from the poller in the event loop. + * + */ + void remove(); + + /** + * @brief Return the event loop. + * + * @return EventLoop* + */ + EventLoop *ownerLoop() + { + return loop_; + }; + + /** + * @brief Enable the read event on the socket. + * + */ + void enableReading() + { + events_ |= kReadEvent; + update(); + } + + /** + * @brief Disable the read event on the socket. + * + */ + void disableReading() + { + events_ &= ~kReadEvent; + update(); + } + + /** + * @brief Enable the write event on the socket. + * + */ + void enableWriting() + { + events_ |= kWriteEvent; + update(); + } + + /** + * @brief Disable the write event on the socket. + * + */ + void disableWriting() + { + events_ &= ~kWriteEvent; + update(); + } + + /** + * @brief Check whether the write event is enabled on the socket. + * + * @return true + * @return false + */ + bool isWriting() const + { + return events_ & kWriteEvent; + } + + /** + * @brief Check whether the read event is enabled on the socket. + * + * @return true + * @return false + */ + bool isReading() const + { + return events_ & kReadEvent; + } + + /** + * @brief Set and update the events enabled. + * + * @param events + */ + void updateEvents(int events) + { + events_ = events; + update(); + } + + /** + * @brief This method is used to ensure that the callback owner is valid + * when a callback is called. + * + * @param obj The callback owner. Usually, the owner is also the owner of + * the channel. + * @note The 'obj' is kept in a weak_ptr object, so this method does not + * cause a circular reference problem. + */ + void tie(const std::shared_ptr &obj) + { + tie_ = obj; + tied_ = true; + } + + static const int kNoneEvent; + static const int kReadEvent; + static const int kWriteEvent; + + private: + friend class EventLoop; + friend class EpollPoller; + friend class KQueue; + void update(); + void handleEvent(); + void handleEventSafely(); + int setRevents(int revt) + { + // LOG_TRACE<<"revents="< tie_; + bool tied_; +}; +} // namespace trantor diff --git a/core/loops/event_loop.cpp b/web_backends/drogon/trantor/net/EventLoop.cc similarity index 80% rename from core/loops/event_loop.cpp rename to web_backends/drogon/trantor/net/EventLoop.cc index 8dd2b8d..b78def7 100644 --- a/core/loops/event_loop.cpp +++ b/web_backends/drogon/trantor/net/EventLoop.cc @@ -1,41 +1,26 @@ - -// This file is originally from Moduo -> Trantor - EventLoop.cc - -// Copyright (c) 2016-2021, Tao An. All rights reserved. -// Copyright (c) 2010, Shuo Chen. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: +// Copyright 2010, Shuo Chen. All rights reserved. +// http://code.google.com/p/muduo/ // -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. +// Use of this source code is governed by a BSD-style license +// that can be found in the License file. + +// Author: Shuo Chen (chenshuo at chenshuo dot com) + +// Taken from Muduo and modified +// Copyright 2016, Tao An. All rights reserved. +// https://github.com/an-tao/trantor // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// Use of this source code is governed by a BSD-style license +// that can be found in the License file. -#include "event_loop.h" -#include "core/log/logger.h" +// Author: Tao An -#include "core/net/channel.h" -#include "core/polling/poller.h" +#include +#include -#include "timer_queue.h" +#include "Channel.h" +#include "Poller.h" +#include "TimerQueue.h" #include #include @@ -57,6 +42,7 @@ using ssize_t = long long; #include #include +namespace trantor { #ifdef __linux__ int createEventfd() { int evtfd = ::eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); @@ -333,3 +319,5 @@ void EventLoop::runOnQuit(Func &&cb) { void EventLoop::runOnQuit(const Func &cb) { funcsOnQuit_.enqueue(cb); } + +} // namespace trantor diff --git a/web_backends/drogon/trantor/net/EventLoop.h b/web_backends/drogon/trantor/net/EventLoop.h new file mode 100644 index 0000000..d28f6b8 --- /dev/null +++ b/web_backends/drogon/trantor/net/EventLoop.h @@ -0,0 +1,321 @@ +// Copyright 2010, Shuo Chen. All rights reserved. +// http://code.google.com/p/muduo/ +// +// Use of this source code is governed by a BSD-style license +// that can be found in the License file. + +// Author: Shuo Chen (chenshuo at chenshuo dot com) + +// Taken from Muduo and modified +// Copyright 2016, Tao An. All rights reserved. +// https://github.com/an-tao/trantor +// +// Use of this source code is governed by a BSD-style license +// that can be found in the License file. + +// Author: Tao An + +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace trantor +{ +class Poller; +class TimerQueue; +class Channel; +using ChannelList = std::vector; +using Func = std::function; +using TimerId = uint64_t; +enum +{ + InvalidTimerId = 0 +}; + +/** + * @brief As the name implies, this class represents an event loop that runs in + * a perticular thread. The event loop can handle network I/O events and timers + * in asynchronous mode. + * @note An event loop object always belongs to a separate thread, and there is + * one event loop object at most in a thread. We can call an event loop object + * the event loop of the thread it belongs to, or call that thread the thread of + * the event loop. + */ +class TRANTOR_EXPORT EventLoop : NonCopyable +{ + public: + EventLoop(); + ~EventLoop(); + + /** + * @brief Run the event loop. This method will be blocked until the event + * loop exits. + * + */ + void loop(); + + /** + * @brief Let the event loop quit. + * + */ + void quit(); + + /** + * @brief Assertion that the current thread is the thread to which the event + * loop belongs. If the assertion fails, the program aborts. + */ + void assertInLoopThread() + { + if (!isInLoopThread()) + { + abortNotInLoopThread(); + } + }; +#ifdef __linux__ + /** + * @brief Make the timer queue works after calling the fork() function. + * + */ + void resetTimerQueue(); +#endif + /** + * @brief Make the event loop works after calling the fork() function. + * + */ + void resetAfterFork(); + + /** + * @brief Return true if the current thread is the thread to which the event + * loop belongs. + * + * @return true + * @return false + */ + bool isInLoopThread() const + { + return threadId_ == std::this_thread::get_id(); + }; + + /** + * @brief Get the event loop of the current thread. Return nullptr if there + * is no event loop in the current thread. + * + * @return EventLoop* + */ + static EventLoop *getEventLoopOfCurrentThread(); + + /** + * @brief Run the function f in the thread of the event loop. + * + * @param f + * @note If the current thread is the thread of the event loop, the function + * f is executed directly before the method exiting. + */ + void runInLoop(const Func &f); + void runInLoop(Func &&f); + + /** + * @brief Run the function f in the thread of the event loop. + * + * @param f + * @note The difference between this method and the runInLoop() method is + * that the function f is executed after the method exiting no matter if the + * current thread is the thread of the event loop. + */ + void queueInLoop(const Func &f); + void queueInLoop(Func &&f); + + /** + * @brief Run a function at a time point. + * + * @param time The time to run the function. + * @param cb The function to run. + * @return TimerId The ID of the timer. + */ + TimerId runAt(const Date &time, const Func &cb); + TimerId runAt(const Date &time, Func &&cb); + + /** + * @brief Run a function after a period of time. + * + * @param delay Represent the period of time in seconds. + * @param cb The function to run. + * @return TimerId The ID of the timer. + */ + TimerId runAfter(double delay, const Func &cb); + TimerId runAfter(double delay, Func &&cb); + + /** + * @brief Run a function after a period of time. + * @note Users could use chrono literals to represent a time duration + * For example: + * @code + runAfter(5s, task); + runAfter(10min, task); + @endcode + */ + TimerId runAfter(const std::chrono::duration &delay, const Func &cb) + { + return runAfter(delay.count(), cb); + } + TimerId runAfter(const std::chrono::duration &delay, Func &&cb) + { + return runAfter(delay.count(), std::move(cb)); + } + + /** + * @brief Repeatedly run a function every period of time. + * + * @param interval The duration in seconds. + * @param cb The function to run. + * @return TimerId The ID of the timer. + */ + TimerId runEvery(double interval, const Func &cb); + TimerId runEvery(double interval, Func &&cb); + + /** + * @brief Repeatedly run a function every period of time. + * Users could use chrono literals to represent a time duration + * For example: + * @code + runEvery(5s, task); + runEvery(10min, task); + runEvery(0.1h, task); + @endcode + */ + TimerId runEvery(const std::chrono::duration &interval, + const Func &cb) + { + return runEvery(interval.count(), cb); + } + TimerId runEvery(const std::chrono::duration &interval, Func &&cb) + { + return runEvery(interval.count(), std::move(cb)); + } + + /** + * @brief Invalidate the timer identified by the given ID. + * + * @param id The ID of the timer. + */ + void invalidateTimer(TimerId id); + + /** + * @brief Move the EventLoop to the current thread, this method must be + * called before the loop is running. + * + */ + void moveToCurrentThread(); + + /** + * @brief Update channel status. This method is usually used internally. + * + * @param chl + */ + void updateChannel(Channel *chl); + + /** + * @brief Remove a channel from the event loop. This method is usually used + * internally. + * + * @param chl + */ + void removeChannel(Channel *chl); + + /** + * @brief Return the index of the event loop. + * + * @return size_t + */ + size_t index() + { + return index_; + } + + /** + * @brief Set the index of the event loop. + * + * @param index + */ + void setIndex(size_t index) + { + index_ = index; + } + + /** + * @brief Return true if the event loop is running. + * + * @return true + * @return false + */ + bool isRunning() + { + return looping_ && (!quit_); + } + + /** + * @brief Check if the event loop is calling a function. + * + * @return true + * @return false + */ + bool isCallingFunctions() + { + return callingFuncs_; + } + + /** + * @brief Run functions when the event loop quits + * + * @param cb the function to run + * @note the function runs on the thread that quits the EventLoop + */ + void runOnQuit(Func &&cb); + void runOnQuit(const Func &cb); + + private: + void abortNotInLoopThread(); + void wakeup(); + void wakeupRead(); + bool looping_; + std::thread::id threadId_; + bool quit_; + std::unique_ptr poller_; + + ChannelList activeChannels_; + Channel *currentActiveChannel_; + + bool eventHandling_; + MpscQueue funcs_; + std::unique_ptr timerQueue_; + MpscQueue funcsOnQuit_; + bool callingFuncs_{false}; +#ifdef __linux__ + int wakeupFd_; + std::unique_ptr wakeupChannelPtr_; +#elif defined _WIN32 +#else + int wakeupFd_[2]; + std::unique_ptr wakeupChannelPtr_; +#endif + + void doRunInLoopFuncs(); +#ifdef _WIN32 + size_t index_{size_t(-1)}; +#else + size_t index_{std::numeric_limits::max()}; +#endif + EventLoop **threadLocalLoopPtr_; +}; + +} // namespace trantor diff --git a/web_backends/drogon/trantor/net/EventLoopThread.cc b/web_backends/drogon/trantor/net/EventLoopThread.cc new file mode 100644 index 0000000..121c3ad --- /dev/null +++ b/web_backends/drogon/trantor/net/EventLoopThread.cc @@ -0,0 +1,65 @@ +/** + * + * @file EventLoopThread.cc + * @author An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#include +#include +#ifdef __linux__ +#include +#endif + +using namespace trantor; +EventLoopThread::EventLoopThread(const std::string &threadName) : + loop_(nullptr), + loopThreadName_(threadName), + thread_([this]() { loopFuncs(); }) { + auto f = promiseForLoopPointer_.get_future(); + loop_ = f.get(); +} +EventLoopThread::~EventLoopThread() { + run(); + if (loop_) { + loop_->quit(); + } + if (thread_.joinable()) { + thread_.join(); + } +} +// void EventLoopThread::stop() { +// if(loop_) +// loop_->quit(); +//} +void EventLoopThread::wait() { + thread_.join(); +} +void EventLoopThread::loopFuncs() { +#ifdef __linux__ + ::prctl(PR_SET_NAME, loopThreadName_.c_str()); +#endif + EventLoop loop; + loop.queueInLoop([this]() { promiseForLoop_.set_value(1); }); + promiseForLoopPointer_.set_value(&loop); + auto f = promiseForRun_.get_future(); + (void)f.get(); + loop.loop(); + // LOG_DEBUG << "loop out"; + loop_ = NULL; +} +void EventLoopThread::run() { + std::call_once(once_, [this]() { + auto f = promiseForLoop_.get_future(); + promiseForRun_.set_value(1); + // Make sure the event loop loops before returning. + (void)f.get(); + }); +} diff --git a/web_backends/drogon/trantor/net/EventLoopThread.h b/web_backends/drogon/trantor/net/EventLoopThread.h new file mode 100644 index 0000000..4d9caa1 --- /dev/null +++ b/web_backends/drogon/trantor/net/EventLoopThread.h @@ -0,0 +1,72 @@ +/** + * + * @file EventLoopThread.h + * @author An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace trantor +{ +/** + * @brief This class represents an event loop thread. + * + */ +class TRANTOR_EXPORT EventLoopThread : NonCopyable +{ + public: + explicit EventLoopThread(const std::string &threadName = "EventLoopThread"); + ~EventLoopThread(); + + /** + * @brief Wait for the event loop to exit. + * @note This method blocks the current thread until the event loop exits. + */ + void wait(); + + /** + * @brief Get the pointer of the event loop of the thread. + * + * @return EventLoop* + */ + EventLoop *getLoop() const + { + return loop_; + } + + /** + * @brief Run the event loop of the thread. This method doesn't block the + * current thread. + * + */ + void run(); + + private: + EventLoop *loop_; + std::string loopThreadName_; + void loopFuncs(); + std::promise promiseForLoopPointer_; + std::promise promiseForRun_; + std::promise promiseForLoop_; + std::once_flag once_; + std::thread thread_; +}; + +} // namespace trantor diff --git a/web_backends/drogon/trantor/net/EventLoopThreadPool.cc b/web_backends/drogon/trantor/net/EventLoopThreadPool.cc new file mode 100644 index 0000000..1505abe --- /dev/null +++ b/web_backends/drogon/trantor/net/EventLoopThreadPool.cc @@ -0,0 +1,61 @@ +/** + * + * EventLoopThreadPool.cc + * An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#include +using namespace trantor; +EventLoopThreadPool::EventLoopThreadPool(size_t threadNum, + const std::string &name) : + loopIndex_(0) { + for (size_t i = 0; i < threadNum; ++i) { + loopThreadVector_.emplace_back(std::make_shared(name)); + } +} +void EventLoopThreadPool::start() { + for (unsigned int i = 0; i < loopThreadVector_.size(); ++i) { + loopThreadVector_[i]->run(); + } +} +// void EventLoopThreadPool::stop(){ +// for(unsigned int i=0;iwait(); + } +} +EventLoop *EventLoopThreadPool::getNextLoop() { + if (loopThreadVector_.size() > 0) { + EventLoop *loop = loopThreadVector_[loopIndex_]->getLoop(); + ++loopIndex_; + if (loopIndex_ >= loopThreadVector_.size()) + loopIndex_ = 0; + return loop; + } + return nullptr; +} +EventLoop *EventLoopThreadPool::getLoop(size_t id) { + if (id < loopThreadVector_.size()) + return loopThreadVector_[id]->getLoop(); + return nullptr; +} +std::vector EventLoopThreadPool::getLoops() const { + std::vector ret; + for (auto &loopThread : loopThreadVector_) { + ret.push_back(loopThread->getLoop()); + } + return ret; +} \ No newline at end of file diff --git a/web_backends/drogon/trantor/net/EventLoopThreadPool.h b/web_backends/drogon/trantor/net/EventLoopThreadPool.h new file mode 100644 index 0000000..6332169 --- /dev/null +++ b/web_backends/drogon/trantor/net/EventLoopThreadPool.h @@ -0,0 +1,92 @@ +/** + * + * @file EventLoopThreadPool.h + * @author An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#pragma once + +#include +#include +#include +#include + +namespace trantor +{ +/** + * @brief This class represents a pool of EventLoopThread objects + * + */ +class TRANTOR_EXPORT EventLoopThreadPool : NonCopyable +{ + public: + EventLoopThreadPool() = delete; + + /** + * @brief Construct a new event loop thread pool instance. + * + * @param threadNum The number of threads + * @param name The name of the EventLoopThreadPool object. + */ + EventLoopThreadPool(size_t threadNum, + const std::string &name = "EventLoopThreadPool"); + + /** + * @brief Run all event loops in the pool. + * @note This function doesn't block the current thread. + */ + void start(); + + /** + * @brief Wait for all event loops in the pool to quit. + * + * @note This function blocks the current thread. + */ + void wait(); + + /** + * @brief Return the number of the event loop. + * + * @return size_t + */ + size_t size() + { + return loopThreadVector_.size(); + } + + /** + * @brief Get the next event loop in the pool. + * + * @return EventLoop* + */ + EventLoop *getNextLoop(); + + /** + * @brief Get the event loop in the `id` position in the pool. + * + * @param id The id of the first event loop is zero. If the id >= the number + * of event loops, nullptr is returned. + * @return EventLoop* + */ + EventLoop *getLoop(size_t id); + + /** + * @brief Get all event loops in the pool. + * + * @return std::vector + */ + std::vector getLoops() const; + + private: + std::vector> loopThreadVector_; + size_t loopIndex_; +}; +} // namespace trantor diff --git a/core/net/inet_address.cpp b/web_backends/drogon/trantor/net/InetAddress.cc similarity index 75% rename from core/net/inet_address.cpp rename to web_backends/drogon/trantor/net/InetAddress.cc index ba3b9d9..f1dfe68 100644 --- a/core/net/inet_address.cpp +++ b/web_backends/drogon/trantor/net/InetAddress.cc @@ -1,35 +1,15 @@ - -// This file is originally from Moduo -> Trantor - InetAddress.cc - -// Copyright (c) 2016-2021, Tao An. All rights reserved. // Copyright 2010, Shuo Chen. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: +// http://code.google.com/p/muduo/ // -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// Use of this source code is governed by a BSD-style license +// that can be found in the License file. -#include "inet_address.h" +// Author: Shuo Chen (chenshuo at chenshuo dot com) + +#include + +#include +//#include #ifdef _WIN32 struct in6_addr_uint { @@ -43,7 +23,6 @@ struct in6_addr_uint { #include #include #include // memset -#include #endif // INADDR_ANY use (type)value casting. @@ -71,6 +50,7 @@ static const in_addr_t kInaddrLoopback = INADDR_LOOPBACK; // uint32_t sin6_scope_id; /* IPv6 scope-id */ // }; +using namespace trantor; /* #ifdef __linux__ @@ -98,7 +78,8 @@ InetAddress::InetAddress(uint16_t port, bool loopbackOnly, bool ipv6) : isUnspecified_ = false; } -InetAddress::InetAddress(const std::string &ip, uint16_t port, bool ipv6) : isIpV6_(ipv6) { +InetAddress::InetAddress(const std::string &ip, uint16_t port, bool ipv6) : + isIpV6_(ipv6) { if (ipv6) { memset(&addr6_, 0, sizeof(addr6_)); addr6_.sin6_family = AF_INET6; diff --git a/web_backends/drogon/trantor/net/InetAddress.h b/web_backends/drogon/trantor/net/InetAddress.h new file mode 100644 index 0000000..1750bb5 --- /dev/null +++ b/web_backends/drogon/trantor/net/InetAddress.h @@ -0,0 +1,226 @@ +// Copyright 2010, Shuo Chen. All rights reserved. +// http://code.google.com/p/muduo/ +// +// Use of this source code is governed by a BSD-style license +// that can be found in the License file. + +// Author: Shuo Chen (chenshuo at chenshuo dot com) +// +// This is a public header file, it must only include public header files. + +// Taken from Muduo and modified +// Copyright 2016, Tao An. All rights reserved. +// https://github.com/an-tao/trantor +// +// Use of this source code is governed by a BSD-style license +// that can be found in the License file. + +// Author: Tao An + +#ifndef MUDUO_NET_INETADDRESS_H +#define MUDUO_NET_INETADDRESS_H + +#include +#include + +#ifdef _WIN32 +#include +using sa_family_t = unsigned short; +using in_addr_t = uint32_t; +using uint16_t = unsigned short; +#else +#include +#include +#include +#endif +#include +#include +#include +namespace trantor +{ +/** + * @brief Wrapper of sockaddr_in. This is an POD interface class. + * + */ +class TRANTOR_EXPORT InetAddress +{ + public: + /** + * @brief Constructs an endpoint with given port number. Mostly used in + * TcpServer listening. + * + * @param port + * @param loopbackOnly + * @param ipv6 + */ + InetAddress(uint16_t port = 0, + bool loopbackOnly = false, + bool ipv6 = false); + + /** + * @brief Constructs an endpoint with given ip and port. + * + * @param ip A IPv4 or IPv6 address. + * @param port + * @param ipv6 + */ + InetAddress(const std::string &ip, uint16_t port, bool ipv6 = false); + + /** + * @brief Constructs an endpoint with given struct `sockaddr_in`. Mostly + * used when accepting new connections + * + * @param addr + */ + explicit InetAddress(const struct sockaddr_in &addr) + : addr_(addr), isUnspecified_(false) + { + } + + /** + * @brief Constructs an IPv6 endpoint with given struct `sockaddr_in6`. + * Mostly used when accepting new connections + * + * @param addr + */ + explicit InetAddress(const struct sockaddr_in6 &addr) + : addr6_(addr), isIpV6_(true), isUnspecified_(false) + { + } + + /** + * @brief Return the sin_family of the endpoint. + * + * @return sa_family_t + */ + sa_family_t family() const + { + return addr_.sin_family; + } + + /** + * @brief Return the IP string of the endpoint. + * + * @return std::string + */ + std::string toIp() const; + + /** + * @brief Return the IP and port string of the endpoint. + * + * @return std::string + */ + std::string toIpPort() const; + + /** + * @brief Return the port number of the endpoint. + * + * @return uint16_t + */ + uint16_t toPort() const; + + /** + * @brief Check if the endpoint is IPv4 or IPv6. + * + * @return true + * @return false + */ + bool isIpV6() const + { + return isIpV6_; + } + + /** + * @brief Return true if the endpoint is an intranet endpoint. + * + * @return true + * @return false + */ + bool isIntranetIp() const; + + /** + * @brief Return true if the endpoint is a loopback endpoint. + * + * @return true + * @return false + */ + bool isLoopbackIp() const; + + /** + * @brief Get the pointer to the sockaddr struct. + * + * @return const struct sockaddr* + */ + const struct sockaddr *getSockAddr() const + { + return static_cast((void *)(&addr6_)); + } + + /** + * @brief Set the sockaddr_in6 struct in the endpoint. + * + * @param addr6 + */ + void setSockAddrInet6(const struct sockaddr_in6 &addr6) + { + addr6_ = addr6; + isIpV6_ = (addr6_.sin6_family == AF_INET6); + isUnspecified_ = false; + } + + /** + * @brief Return the integer value of the IP(v4) in net endian byte order. + * + * @return uint32_t + */ + uint32_t ipNetEndian() const; + + /** + * @brief Return the pointer to the integer value of the IP(v6) in net + * endian byte order. + * + * @return const uint32_t* + */ + const uint32_t *ip6NetEndian() const; + + /** + * @brief Return the port number in net endian byte order. + * + * @return uint16_t + */ + uint16_t portNetEndian() const + { + return addr_.sin_port; + } + + /** + * @brief Set the port number in net endian byte order. + * + * @param port + */ + void setPortNetEndian(uint16_t port) + { + addr_.sin_port = port; + } + + /** + * @brief Return true if the address is not initalized. + */ + inline bool isUnspecified() const + { + return isUnspecified_; + } + + private: + union + { + struct sockaddr_in addr_; + struct sockaddr_in6 addr6_; + }; + bool isIpV6_{false}; + bool isUnspecified_{true}; +}; + +} // namespace trantor + +#endif // MUDUO_NET_INETADDRESS_H diff --git a/web_backends/drogon/trantor/net/Resolver.h b/web_backends/drogon/trantor/net/Resolver.h new file mode 100644 index 0000000..478887b --- /dev/null +++ b/web_backends/drogon/trantor/net/Resolver.h @@ -0,0 +1,57 @@ +// Copyright 2016, Tao An. All rights reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the License file. + +// Author: Tao An + +#pragma once +#include +#include +#include +#include + +namespace trantor +{ +/** + * @brief This class represents an asynchronous DNS resolver. + * @note Although the c-ares library is not essential, it is recommended to + * install it for higher performance + */ +class TRANTOR_EXPORT Resolver +{ + public: + using Callback = std::function; + + /** + * @brief Create a new DNS resolver. + * + * @param loop The event loop in which the DNS resolver runs. + * @param timeout The timeout in seconds for DNS. + * @return std::shared_ptr + */ + static std::shared_ptr newResolver(EventLoop* loop = nullptr, + size_t timeout = 60); + + /** + * @brief Resolve an address asynchronously. + * + * @param hostname + * @param callback + */ + virtual void resolve(const std::string& hostname, + const Callback& callback) = 0; + + virtual ~Resolver() + { + } + + /** + * @brief Check whether the c-ares library is used. + * + * @return true + * @return false + */ + static bool isCAresUsed(); +}; +} // namespace trantor \ No newline at end of file diff --git a/core/net/tcp_client.cpp b/web_backends/drogon/trantor/net/TcpClient.cc similarity index 56% rename from core/net/tcp_client.cpp rename to web_backends/drogon/trantor/net/TcpClient.cc index 2cf0a2e..5942ce5 100644 --- a/core/net/tcp_client.cpp +++ b/web_backends/drogon/trantor/net/TcpClient.cc @@ -1,50 +1,32 @@ - -// This file is originally from Moduo -> Trantor - TcpClient.h - -// Copyright (c) 2016-2021, Tao An. All rights reserved. // Copyright 2010, Shuo Chen. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: +// http://code.google.com/p/muduo/ // -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. +// Use of this source code is governed by a BSD-style license +// that can be found in the License file. + +// Author: Shuo Chen (chenshuo at chenshuo dot com) // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include "core/net/tcp_client.h" +// Taken from muduo and modified by an tao -#include "connector.h" -#include "core/log/logger.h" -#include "core/loops/event_loop.h" -#include "core/net/connections/tcp_connection_impl.h" +#include + +#include "Connector.h" +#include "inner/TcpConnectionImpl.h" +#include +#include #include #include -#include "core/net/socket.h" +#include "Socket.h" #include // snprintf +using namespace trantor; using namespace std::placeholders; +namespace trantor { // void removeConnector(const ConnectorPtr &) // { // // connector-> @@ -54,7 +36,9 @@ TcpClient::IgnoreSigPipe TcpClient::initObj; #endif static void defaultConnectionCallback(const TcpConnectionPtr &conn) { - LOG_TRACE << conn->localAddr().toIpPort() << " -> " << conn->peerAddr().toIpPort() << " is " << (conn->connected() ? "UP" : "DOWN"); + LOG_TRACE << conn->localAddr().toIpPort() << " -> " + << conn->peerAddr().toIpPort() << " is " + << (conn->connected() ? "UP" : "DOWN"); // do not call conn->forceClose(), because some users want to register // message callback only. } @@ -63,7 +47,11 @@ static void defaultMessageCallback(const TcpConnectionPtr &, MsgBuffer *buf) { buf->retrieveAll(); } -TcpClient::TcpClient(EventLoop *loop, const InetAddress &serverAddr, const std::string &nameArg) : +} // namespace trantor + +TcpClient::TcpClient(EventLoop *loop, + const InetAddress &serverAddr, + const std::string &nameArg) : loop_(loop), connector_(new Connector(loop, serverAddr, false)), name_(nameArg), @@ -71,27 +59,23 @@ TcpClient::TcpClient(EventLoop *loop, const InetAddress &serverAddr, const std:: messageCallback_(defaultMessageCallback), retry_(false), connect_(true) { - - connector_->setNewConnectionCallback(std::bind(&TcpClient::newConnection, this, _1)); - + connector_->setNewConnectionCallback( + std::bind(&TcpClient::newConnection, this, _1)); connector_->setErrorCallback([this]() { if (connectionErrorCallback_) { connectionErrorCallback_(); } }); - LOG_TRACE << "TcpClient::TcpClient[" << name_ << "] - connector "; } TcpClient::~TcpClient() { LOG_TRACE << "TcpClient::~TcpClient[" << name_ << "] - connector "; - TcpConnectionImplPtr conn; { std::lock_guard lock(mutex_); conn = std::dynamic_pointer_cast(connection_); } - if (conn) { assert(loop_ == conn->getLoop()); // TODO: not 100% safe, if we are in different thread @@ -99,11 +83,11 @@ TcpClient::~TcpClient() { loop_->runInLoop([conn, loop]() { conn->setCloseCallback([loop](const TcpConnectionPtr &connPtr) { loop->queueInLoop([connPtr]() { - static_cast(connPtr.get())->connectDestroyed(); + static_cast(connPtr.get()) + ->connectDestroyed(); }); }); }); - conn->forceClose(); } else { /// TODO need test in this condition @@ -142,34 +126,39 @@ void TcpClient::newConnection(int sockfd) { // TODO poll with zero timeout to double confirm the new connection // TODO use make_shared if necessary std::shared_ptr conn; - if (sslCtxPtr_) { #ifdef USE_OPENSSL - conn = std::make_shared(loop_, sockfd, localAddr, peerAddr, sslCtxPtr_, false, validateCert_, SSLHostName_); + conn = std::make_shared(loop_, + sockfd, + localAddr, + peerAddr, + sslCtxPtr_, + false, + validateCert_, + SSLHostName_); #else LOG_FATAL << "OpenSSL is not found in your system!"; abort(); #endif } else { - conn = std::make_shared(loop_, sockfd, localAddr, peerAddr); + conn = std::make_shared(loop_, + sockfd, + localAddr, + peerAddr); } - conn->setConnectionCallback(connectionCallback_); conn->setRecvMsgCallback(messageCallback_); conn->setWriteCompleteCallback(writeCompleteCallback_); conn->setCloseCallback(std::bind(&TcpClient::removeConnection, this, _1)); - { std::lock_guard lock(mutex_); connection_ = conn; } - conn->setSSLErrorCallback([this](SSLError err) { if (sslErrorCallback_) { sslErrorCallback_(err); } }); - conn->connectEstablished(); } @@ -183,23 +172,30 @@ void TcpClient::removeConnection(const TcpConnectionPtr &conn) { connection_.reset(); } - loop_->queueInLoop(std::bind(&TcpConnectionImpl::connectDestroyed, std::dynamic_pointer_cast(conn))); - + loop_->queueInLoop( + std::bind(&TcpConnectionImpl::connectDestroyed, + std::dynamic_pointer_cast(conn))); if (retry_ && connect_) { - LOG_TRACE << "TcpClient::connect[" << name_ << "] - Reconnecting to " << connector_->serverAddress().toIpPort(); + LOG_TRACE << "TcpClient::connect[" << name_ << "] - Reconnecting to " + << connector_->serverAddress().toIpPort(); connector_->restart(); } } -void TcpClient::enableSSL(bool useOldTLS, bool validateCert, std::string hostname, const std::vector > &sslConfCmds) { +void TcpClient::enableSSL( + bool useOldTLS, + bool validateCert, + std::string hostname, + const std::vector > &sslConfCmds) { #ifdef USE_OPENSSL /* Create a new OpenSSL context */ sslCtxPtr_ = newSSLContext(useOldTLS, validateCert, sslConfCmds); - validateCert_ = validateCert; - if (!hostname.empty()) { - std::transform(hostname.begin(), hostname.end(), hostname.begin(), tolower); + std::transform(hostname.begin(), + hostname.end(), + hostname.begin(), + tolower); SSLHostName_ = std::move(hostname); } diff --git a/web_backends/drogon/trantor/net/TcpClient.h b/web_backends/drogon/trantor/net/TcpClient.h new file mode 100644 index 0000000..045ad06 --- /dev/null +++ b/web_backends/drogon/trantor/net/TcpClient.h @@ -0,0 +1,247 @@ +// taken from muduo +// Copyright 2010, Shuo Chen. All rights reserved. +// http://code.google.com/p/muduo/ +// +// Use of this source code is governed by a BSD-style license +// that can be found in the License file. + +// Author: Shuo Chen (chenshuo at chenshuo dot com) +// +// This is a public header file, it must only include public header files. + +// Copyright 2016, Tao An. All rights reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the License file. + +// Author: Tao An + +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +namespace trantor +{ +class Connector; +using ConnectorPtr = std::shared_ptr; +class SSLContext; +/** + * @brief This class represents a TCP client. + * + */ +class TRANTOR_EXPORT TcpClient : NonCopyable +{ + public: + /** + * @brief Construct a new TCP client instance. + * + * @param loop The event loop in which the client runs. + * @param serverAddr The address of the server. + * @param nameArg The name of the client. + */ + TcpClient(EventLoop *loop, + const InetAddress &serverAddr, + const std::string &nameArg); + ~TcpClient(); + + /** + * @brief Connect to the server. + * + */ + void connect(); + + /** + * @brief Disconnect from the server. + * + */ + void disconnect(); + + /** + * @brief Stop connecting to the server. + * + */ + void stop(); + + /** + * @brief Get the TCP connection to the server. + * + * @return TcpConnectionPtr + */ + TcpConnectionPtr connection() const + { + std::lock_guard lock(mutex_); + return connection_; + } + + /** + * @brief Get the event loop. + * + * @return EventLoop* + */ + EventLoop *getLoop() const + { + return loop_; + } + + /** + * @brief Check whether the client re-connect to the server. + * + * @return true + * @return false + */ + bool retry() const + { + return retry_; + } + + /** + * @brief Enable retrying. + * + */ + void enableRetry() + { + retry_ = true; + } + + /** + * @brief Get the name of the client. + * + * @return const std::string& + */ + const std::string &name() const + { + return name_; + } + + /** + * @brief Set the connection callback. + * + * @param cb The callback is called when the connection to the server is + * established or closed. + */ + void setConnectionCallback(const ConnectionCallback &cb) + { + connectionCallback_ = cb; + } + void setConnectionCallback(ConnectionCallback &&cb) + { + connectionCallback_ = std::move(cb); + } + + /** + * @brief Set the connection error callback. + * + * @param cb The callback is called when an error occurs during connecting + * to the server. + */ + void setConnectionErrorCallback(const ConnectionErrorCallback &cb) + { + connectionErrorCallback_ = cb; + } + + /** + * @brief Set the message callback. + * + * @param cb The callback is called when some data is received from the + * server. + */ + void setMessageCallback(const RecvMessageCallback &cb) + { + messageCallback_ = cb; + } + void setMessageCallback(RecvMessageCallback &&cb) + { + messageCallback_ = std::move(cb); + } + /// Set write complete callback. + /// Not thread safe. + + /** + * @brief Set the write complete callback. + * + * @param cb The callback is called when data to send is written to the + * socket. + */ + void setWriteCompleteCallback(const WriteCompleteCallback &cb) + { + writeCompleteCallback_ = cb; + } + void setWriteCompleteCallback(WriteCompleteCallback &&cb) + { + writeCompleteCallback_ = std::move(cb); + } + + /** + * @brief Set the callback for errors of SSL + * @param cb The callback is called when an SSL error occurs. + */ + void setSSLErrorCallback(const SSLErrorCallback &cb) + { + sslErrorCallback_ = cb; + } + void setSSLErrorCallback(SSLErrorCallback &&cb) + { + sslErrorCallback_ = std::move(cb); + } + + /** + * @brief Enable SSL encryption. + * @param useOldTLS If true, the TLS 1.0 and 1.1 are supported by the + * client. + * @param validateCert If true, we try to validate if the peer's SSL cert + * is valid. + * @param hostname The server hostname for SNI. If it is empty, the SNI is + * not used. + * @param sslConfCmds The commands used to call the SSL_CONF_cmd function in + * OpenSSL. + * @note It's well known that TLS 1.0 and 1.1 are not considered secure in + * 2020. And it's a good practice to only use TLS 1.2 and above. + */ + void enableSSL(bool useOldTLS = false, + bool validateCert = true, + std::string hostname = "", + const std::vector> + &sslConfCmds = {}); + + private: + /// Not thread safe, but in loop + void newConnection(int sockfd); + /// Not thread safe, but in loop + void removeConnection(const TcpConnectionPtr &conn); + + EventLoop *loop_; + ConnectorPtr connector_; // avoid revealing Connector + const std::string name_; + ConnectionCallback connectionCallback_; + ConnectionErrorCallback connectionErrorCallback_; + RecvMessageCallback messageCallback_; + WriteCompleteCallback writeCompleteCallback_; + SSLErrorCallback sslErrorCallback_; + std::atomic_bool retry_; // atomic + std::atomic_bool connect_; // atomic + // always in loop thread + mutable std::mutex mutex_; + TcpConnectionPtr connection_; // @GuardedBy mutex_ + std::shared_ptr sslCtxPtr_; + bool validateCert_{false}; + std::string SSLHostName_; +#ifndef _WIN32 + class IgnoreSigPipe + { + public: + IgnoreSigPipe() + { + ::signal(SIGPIPE, SIG_IGN); + } + }; + + static IgnoreSigPipe initObj; +#endif +}; + +} // namespace trantor diff --git a/web_backends/drogon/trantor/net/TcpConnection.h b/web_backends/drogon/trantor/net/TcpConnection.h new file mode 100644 index 0000000..90f2446 --- /dev/null +++ b/web_backends/drogon/trantor/net/TcpConnection.h @@ -0,0 +1,261 @@ +/** + * + * @file TcpConnection.h + * @author An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace trantor +{ +class SSLContext; +TRANTOR_EXPORT std::shared_ptr newSSLServerContext( + const std::string &certPath, + const std::string &keyPath, + bool useOldTLS = false, + const std::vector> &sslConfCmds = {}); +/** + * @brief This class represents a TCP connection. + * + */ +class TRANTOR_EXPORT TcpConnection +{ + public: + TcpConnection() = default; + virtual ~TcpConnection(){}; + + /** + * @brief Send some data to the peer. + * + * @param msg + * @param len + */ + virtual void send(const char *msg, size_t len) = 0; + virtual void send(const void *msg, size_t len) = 0; + virtual void send(const std::string &msg) = 0; + virtual void send(std::string &&msg) = 0; + virtual void send(const MsgBuffer &buffer) = 0; + virtual void send(MsgBuffer &&buffer) = 0; + virtual void send(const std::shared_ptr &msgPtr) = 0; + virtual void send(const std::shared_ptr &msgPtr) = 0; + + /** + * @brief Send a file to the peer. + * + * @param fileName + * @param offset + * @param length + */ + virtual void sendFile(const char *fileName, + size_t offset = 0, + size_t length = 0) = 0; + + /** + * @brief Get the local address of the connection. + * + * @return const InetAddress& + */ + virtual const InetAddress &localAddr() const = 0; + + /** + * @brief Get the remote address of the connection. + * + * @return const InetAddress& + */ + virtual const InetAddress &peerAddr() const = 0; + + /** + * @brief Return true if the connection is established. + * + * @return true + * @return false + */ + virtual bool connected() const = 0; + + /** + * @brief Return false if the connection is established. + * + * @return true + * @return false + */ + virtual bool disconnected() const = 0; + + /** + * @brief Get the buffer in which the received data stored. + * + * @return MsgBuffer* + */ + virtual MsgBuffer *getRecvBuffer() = 0; + + /** + * @brief Set the high water mark callback + * + * @param cb The callback is called when the data in sending buffer is + * larger than the water mark. + * @param markLen The water mark in bytes. + */ + virtual void setHighWaterMarkCallback(const HighWaterMarkCallback &cb, + size_t markLen) = 0; + + /** + * @brief Set the TCP_NODELAY option to the socket. + * + * @param on + */ + virtual void setTcpNoDelay(bool on) = 0; + + /** + * @brief Shutdown the connection. + * @note This method only closes the writing direction. + */ + virtual void shutdown() = 0; + + /** + * @brief Close the connection forcefully. + * + */ + virtual void forceClose() = 0; + + /** + * @brief Get the event loop in which the connection I/O is handled. + * + * @return EventLoop* + */ + virtual EventLoop *getLoop() = 0; + + /** + * @brief Set the custom data on the connection. + * + * @param context + */ + void setContext(const std::shared_ptr &context) + { + contextPtr_ = context; + } + void setContext(std::shared_ptr &&context) + { + contextPtr_ = std::move(context); + } + + /** + * @brief Get the custom data from the connection. + * + * @tparam T + * @return std::shared_ptr + */ + template + std::shared_ptr getContext() const + { + return std::static_pointer_cast(contextPtr_); + } + + /** + * @brief Return true if the custom data is set by user. + * + * @return true + * @return false + */ + bool hasContext() const + { + return (bool)contextPtr_; + } + + /** + * @brief Clear the custom data. + * + */ + void clearContext() + { + contextPtr_.reset(); + } + + /** + * @brief Call this method to avoid being kicked off by TcpServer, refer to + * the kickoffIdleConnections method in the TcpServer class. + * + */ + virtual void keepAlive() = 0; + + /** + * @brief Return true if the keepAlive() method is called. + * + * @return true + * @return false + */ + virtual bool isKeepAlive() = 0; + + /** + * @brief Return the number of bytes sent + * + * @return size_t + */ + virtual size_t bytesSent() const = 0; + + /** + * @brief Return the number of bytes received. + * + * @return size_t + */ + virtual size_t bytesReceived() const = 0; + + /** + * @brief Check whether the connection is SSL encrypted. + * + * @return true + * @return false + */ + virtual bool isSSLConnection() const = 0; + + /** + * @brief Start the SSL encryption on the connection (as a client). + * + * @param callback The callback is called when the SSL connection is + * established. + * @param hostname The server hostname for SNI. If it is empty, the SNI is + * not used. + * @param sslConfCmds The commands used to call the SSL_CONF_cmd function in + * OpenSSL. + */ + virtual void startClientEncryption( + std::function callback, + bool useOldTLS = false, + bool validateCert = true, + std::string hostname = "", + const std::vector> &sslConfCmds = + {}) = 0; + + /** + * @brief Start the SSL encryption on the connection (as a server). + * + * @param ctx The SSL context. + * @param callback The callback is called when the SSL connection is + * established. + */ + virtual void startServerEncryption(const std::shared_ptr &ctx, + std::function callback) = 0; + + protected: + bool validateCert_ = false; + + private: + std::shared_ptr contextPtr_; +}; + +} // namespace trantor diff --git a/core/net/tcp_server.cpp b/web_backends/drogon/trantor/net/TcpServer.cc similarity index 55% rename from core/net/tcp_server.cpp rename to web_backends/drogon/trantor/net/TcpServer.cc index ed71d08..2ef0e96 100644 --- a/core/net/tcp_server.cpp +++ b/web_backends/drogon/trantor/net/TcpServer.cc @@ -1,43 +1,31 @@ +/** + * + * @file TcpServer.cc + * @author An Tao + * + * Copyright 2018, An Tao. All rights reserved. + * https://github.com/an-tao/trantor + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * Trantor + * + */ -// This file is originally from Trantor - TcpServer.cc - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "core/net/tcp_server.h" -#include "core/log/logger.h" -#include "core/net/acceptor.h" -#include "core/net/connections/tcp_connection_impl.h" +#include "Acceptor.h" +#include "inner/TcpConnectionImpl.h" +#include +#include #include #include - +using namespace trantor; using namespace std::placeholders; -TcpServer::TcpServer(EventLoop *loop, const InetAddress &address, const std::string &name, bool reUseAddr, bool reUsePort) : +TcpServer::TcpServer(EventLoop *loop, + const InetAddress &address, + const std::string &name, + bool reUseAddr, + bool reUsePort) : loop_(loop), acceptorPtr_(new Acceptor(loop, address, reUseAddr, reUsePort)), serverName_(name), @@ -46,8 +34,8 @@ TcpServer::TcpServer(EventLoop *loop, const InetAddress &address, const std::str << " bytes]"; buffer->retrieveAll(); }) { - - acceptorPtr_->setNewConnectionCallback(std::bind(&TcpServer::newConnection, this, _1, _2)); + acceptorPtr_->setNewConnectionCallback( + std::bind(&TcpServer::newConnection, this, _1, _2)); } TcpServer::~TcpServer() { @@ -65,36 +53,35 @@ void TcpServer::newConnection(int sockfd, const InetAddress &peer) { // LOG_TRACE<<"vector size:"<assertInLoopThread(); - EventLoop *ioLoop = NULL; if (loopPoolPtr_ && loopPoolPtr_->size() > 0) { ioLoop = loopPoolPtr_->getNextLoop(); } - - if (ioLoop == NULL) { + if (ioLoop == NULL) ioLoop = loop_; - } - std::shared_ptr newPtr; - if (sslCtxPtr_) { #ifdef USE_OPENSSL - newPtr = std::make_shared(ioLoop, sockfd, InetAddress(Socket::getLocalAddr(sockfd)), peer, sslCtxPtr_); + newPtr = std::make_shared( + ioLoop, + sockfd, + InetAddress(Socket::getLocalAddr(sockfd)), + peer, + sslCtxPtr_); #else LOG_FATAL << "OpenSSL is not found in your system!"; abort(); #endif } else { - newPtr = std::make_shared(ioLoop, sockfd, InetAddress(Socket::getLocalAddr(sockfd)), peer); + newPtr = std::make_shared( + ioLoop, sockfd, InetAddress(Socket::getLocalAddr(sockfd)), peer); } if (idleTimeout_ > 0) { assert(timingWheelMap_[ioLoop]); newPtr->enableKickingOff(idleTimeout_, timingWheelMap_[ioLoop]); } - newPtr->setRecvMsgCallback(recvMessageCallback_); newPtr->setConnectionCallback( @@ -102,13 +89,11 @@ void TcpServer::newConnection(int sockfd, const InetAddress &peer) { if (connectionCallback_) connectionCallback_(connectionPtr); }); - newPtr->setWriteCompleteCallback( [this](const TcpConnectionPtr &connectionPtr) { if (writeCompleteCallback_) writeCompleteCallback_(connectionPtr); }); - newPtr->setCloseCallback(std::bind(&TcpServer::connectionClosed, this, _1)); connSet_.insert(newPtr); newPtr->connectEstablished(); @@ -118,57 +103,53 @@ void TcpServer::start() { loop_->runInLoop([this]() { assert(!started_); started_ = true; - if (idleTimeout_ > 0) { - timingWheelMap_[loop_] = std::make_shared(loop_, idleTimeout_, 1.0F, idleTimeout_ < 500 ? idleTimeout_ + 1 : 100); - + timingWheelMap_[loop_] = + std::make_shared(loop_, + idleTimeout_, + 1.0F, + idleTimeout_ < 500 ? idleTimeout_ + 1 : 100); if (loopPoolPtr_) { auto loopNum = loopPoolPtr_->size(); while (loopNum > 0) { // LOG_TRACE << "new Wheel loopNum=" << loopNum; auto poolLoop = loopPoolPtr_->getNextLoop(); - timingWheelMap_[poolLoop] = std::make_shared(poolLoop, idleTimeout_, 1.0F, idleTimeout_ < 500 ? idleTimeout_ + 1 : 100); + timingWheelMap_[poolLoop] = + std::make_shared(poolLoop, + idleTimeout_, + 1.0F, + idleTimeout_ < 500 ? idleTimeout_ + 1 : 100); --loopNum; } } } - LOG_TRACE << "map size=" << timingWheelMap_.size(); acceptorPtr_->listen(); }); } - void TcpServer::stop() { loop_->runInLoop([this]() { acceptorPtr_.reset(); }); - for (auto connection : connSet_) { connection->forceClose(); } - loopPoolPtr_.reset(); - for (auto &iter : timingWheelMap_) { std::promise pro; auto f = pro.get_future(); - iter.second->getLoop()->runInLoop([&iter, &pro]() mutable { iter.second.reset(); pro.set_value(1); }); - f.get(); } } - void TcpServer::connectionClosed(const TcpConnectionPtr &connectionPtr) { LOG_TRACE << "connectionClosed"; // loop_->assertInLoopThread(); loop_->runInLoop([this, connectionPtr]() { - size_t n = connSet_.erase(connectionPtr); (void)n; assert(n == 1); - }); static_cast(connectionPtr.get())->connectDestroyed(); @@ -178,11 +159,15 @@ const std::string TcpServer::ipPort() const { return acceptorPtr_->addr().toIpPort(); } -const InetAddress &TcpServer::address() const { +const trantor::InetAddress &TcpServer::address() const { return acceptorPtr_->addr(); } -void TcpServer::enableSSL(const std::string &certPath, const std::string &keyPath, bool useOldTLS, const std::vector > &sslConfCmds) { +void TcpServer::enableSSL( + const std::string &certPath, + const std::string &keyPath, + bool useOldTLS, + const std::vector > &sslConfCmds) { #ifdef USE_OPENSSL /* Create a new OpenSSL context */ sslCtxPtr_ = newSSLServerContext(certPath, keyPath, useOldTLS, sslConfCmds); diff --git a/web_backends/drogon/trantor/net/TcpServer.h b/web_backends/drogon/trantor/net/TcpServer.h new file mode 100644 index 0000000..194fbb2 --- /dev/null +++ b/web_backends/drogon/trantor/net/TcpServer.h @@ -0,0 +1,250 @@ +/** + * + * @file TcpServer.h + * @author An Tao + * + * Copyright 2018, An Tao. All rights reserved. + * https://github.com/an-tao/trantor + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * Trantor + * + */ + +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +namespace trantor +{ +class Acceptor; +class SSLContext; +/** + * @brief This class represents a TCP server. + * + */ +class TRANTOR_EXPORT TcpServer : NonCopyable +{ + public: + /** + * @brief Construct a new TCP server instance. + * + * @param loop The event loop in which the acceptor of the server is + * handled. + * @param address The address of the server. + * @param name The name of the server. + * @param reUseAddr The SO_REUSEADDR option. + * @param reUsePort The SO_REUSEPORT option. + */ + TcpServer(EventLoop *loop, + const InetAddress &address, + const std::string &name, + bool reUseAddr = true, + bool reUsePort = true); + ~TcpServer(); + + /** + * @brief Start the server. + * + */ + void start(); + + /** + * @brief Stop the server. + * + */ + void stop(); + + /** + * @brief Set the number of event loops in which the I/O of connections to + * the server is handled. + * + * @param num + */ + void setIoLoopNum(size_t num) + { + assert(!started_); + loopPoolPtr_ = std::make_shared(num); + loopPoolPtr_->start(); + } + + /** + * @brief Set the event loops pool in which the I/O of connections to + * the server is handled. + * + * @param pool + */ + void setIoLoopThreadPool(const std::shared_ptr &pool) + { + assert(pool->size() > 0); + assert(!started_); + loopPoolPtr_ = pool; + loopPoolPtr_->start(); + } + + /** + * @brief Set the message callback. + * + * @param cb The callback is called when some data is received on a + * connection to the server. + */ + void setRecvMessageCallback(const RecvMessageCallback &cb) + { + recvMessageCallback_ = cb; + } + void setRecvMessageCallback(RecvMessageCallback &&cb) + { + recvMessageCallback_ = std::move(cb); + } + + /** + * @brief Set the connection callback. + * + * @param cb The callback is called when a connection is established or + * closed. + */ + void setConnectionCallback(const ConnectionCallback &cb) + { + connectionCallback_ = cb; + } + void setConnectionCallback(ConnectionCallback &&cb) + { + connectionCallback_ = std::move(cb); + } + + /** + * @brief Set the write complete callback. + * + * @param cb The callback is called when data to send is written to the + * socket of a connection. + */ + void setWriteCompleteCallback(const WriteCompleteCallback &cb) + { + writeCompleteCallback_ = cb; + } + void setWriteCompleteCallback(WriteCompleteCallback &&cb) + { + writeCompleteCallback_ = std::move(cb); + } + + /** + * @brief Get the name of the server. + * + * @return const std::string& + */ + const std::string &name() const + { + return serverName_; + } + + /** + * @brief Get the IP and port string of the server. + * + * @return const std::string + */ + const std::string ipPort() const; + + /** + * @brief Get the address of the server. + * + * @return const trantor::InetAddress& + */ + const trantor::InetAddress &address() const; + + /** + * @brief Get the event loop of the server. + * + * @return EventLoop* + */ + EventLoop *getLoop() const + { + return loop_; + } + + /** + * @brief Get the I/O event loops of the server. + * + * @return std::vector + */ + std::vector getIoLoops() const + { + return loopPoolPtr_->getLoops(); + } + + /** + * @brief An idle connection is a connection that has no read or write, kick + * off it after timeout seconds. + * + * @param timeout + */ + void kickoffIdleConnections(size_t timeout) + { + loop_->runInLoop([this, timeout]() { + assert(!started_); + idleTimeout_ = timeout; + }); + } + + /** + * @brief Enable SSL encryption. + * + * @param certPath The path of the certificate file. + * @param keyPath The path of the private key file. + * @param useOldTLS If true, the TLS 1.0 and 1.1 are supported by the + * server. + * @param sslConfCmds The commands used to call the SSL_CONF_cmd function in + * OpenSSL. + * @note It's well known that TLS 1.0 and 1.1 are not considered secure in + * 2020. And it's a good practice to only use TLS 1.2 and above. + */ + void enableSSL(const std::string &certPath, + const std::string &keyPath, + bool useOldTLS = false, + const std::vector> + &sslConfCmds = {}); + + private: + EventLoop *loop_; + std::unique_ptr acceptorPtr_; + void newConnection(int fd, const InetAddress &peer); + std::string serverName_; + std::set connSet_; + + RecvMessageCallback recvMessageCallback_; + ConnectionCallback connectionCallback_; + WriteCompleteCallback writeCompleteCallback_; + + size_t idleTimeout_{0}; + std::map> timingWheelMap_; + void connectionClosed(const TcpConnectionPtr &connectionPtr); + std::shared_ptr loopPoolPtr_; +#ifndef _WIN32 + class IgnoreSigPipe + { + public: + IgnoreSigPipe() + { + ::signal(SIGPIPE, SIG_IGN); + LOG_TRACE << "Ignore SIGPIPE"; + } + }; + + IgnoreSigPipe initObj; +#endif + bool started_{false}; + + // OpenSSL SSL context Object; + std::shared_ptr sslCtxPtr_; +}; + +} // namespace trantor diff --git a/web_backends/drogon/trantor/net/callbacks.h b/web_backends/drogon/trantor/net/callbacks.h new file mode 100644 index 0000000..f737870 --- /dev/null +++ b/web_backends/drogon/trantor/net/callbacks.h @@ -0,0 +1,43 @@ +/** + * + * callbacks.h + * An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#pragma once + +#include +#include +namespace trantor +{ +enum class SSLError +{ + kSSLHandshakeError, + kSSLInvalidCertificate +}; +using TimerCallback = std::function; + +// the data has been read to (buf, len) +class TcpConnection; +class MsgBuffer; +using TcpConnectionPtr = std::shared_ptr; +// tcp server and connection callback +using RecvMessageCallback = + std::function; +using ConnectionErrorCallback = std::function; +using ConnectionCallback = std::function; +using CloseCallback = std::function; +using WriteCompleteCallback = std::function; +using HighWaterMarkCallback = + std::function; +using SSLErrorCallback = std::function; + +} // namespace trantor diff --git a/web_backends/drogon/trantor/net/inner/Acceptor.cc b/web_backends/drogon/trantor/net/inner/Acceptor.cc new file mode 100644 index 0000000..9cb1bd0 --- /dev/null +++ b/web_backends/drogon/trantor/net/inner/Acceptor.cc @@ -0,0 +1,85 @@ +/** + * + * Acceptor.cc + * An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#include "Acceptor.h" +using namespace trantor; + +#ifndef O_CLOEXEC +#define O_CLOEXEC O_NOINHERIT +#endif + +Acceptor::Acceptor(EventLoop *loop, + const InetAddress &addr, + bool reUseAddr, + bool reUsePort) + + : +#ifndef _WIN32 + idleFd_(::open("/dev/null", O_RDONLY | O_CLOEXEC)), +#endif + sock_( + Socket::createNonblockingSocketOrDie(addr.getSockAddr()->sa_family)), + addr_(addr), + loop_(loop), + acceptChannel_(loop, sock_.fd()) { + sock_.setReuseAddr(reUseAddr); + sock_.setReusePort(reUsePort); + sock_.bindAddress(addr_); + acceptChannel_.setReadCallback(std::bind(&Acceptor::readCallback, this)); + if (addr_.toPort() == 0) { + addr_ = InetAddress{ Socket::getLocalAddr(sock_.fd()) }; + } +} +Acceptor::~Acceptor() { + acceptChannel_.disableAll(); + acceptChannel_.remove(); +#ifndef _WIN32 + ::close(idleFd_); +#endif +} +void Acceptor::listen() { + loop_->assertInLoopThread(); + sock_.listen(); + acceptChannel_.enableReading(); +} + +void Acceptor::readCallback() { + InetAddress peer; + int newsock = sock_.accept(&peer); + if (newsock >= 0) { + if (newConnectionCallback_) { + newConnectionCallback_(newsock, peer); + } else { +#ifndef _WIN32 + ::close(newsock); +#else + closesocket(newsock); +#endif + } + } else { + LOG_SYSERR << "Accpetor::readCallback"; +// Read the section named "The special problem of +// accept()ing when you can't" in libev's doc. +// By Marc Lehmann, author of libev. +/// errno is thread safe +#ifndef _WIN32 + if (errno == EMFILE) { + ::close(idleFd_); + idleFd_ = sock_.accept(&peer); + ::close(idleFd_); + idleFd_ = ::open("/dev/null", O_RDONLY | O_CLOEXEC); + } +#endif + } +} diff --git a/web_backends/drogon/trantor/net/inner/Acceptor.h b/web_backends/drogon/trantor/net/inner/Acceptor.h new file mode 100644 index 0000000..62ec421 --- /dev/null +++ b/web_backends/drogon/trantor/net/inner/Acceptor.h @@ -0,0 +1,56 @@ +/** + * + * Acceptor.h + * An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#pragma once + +#include +#include +#include "Socket.h" +#include +#include "Channel.h" +#include + +namespace trantor +{ +using NewConnectionCallback = std::function; +class Acceptor : NonCopyable +{ + public: + Acceptor(EventLoop *loop, + const InetAddress &addr, + bool reUseAddr = true, + bool reUsePort = true); + ~Acceptor(); + const InetAddress &addr() const + { + return addr_; + } + void setNewConnectionCallback(const NewConnectionCallback &cb) + { + newConnectionCallback_ = cb; + }; + void listen(); + + protected: +#ifndef _WIN32 + int idleFd_; +#endif + Socket sock_; + InetAddress addr_; + EventLoop *loop_; + NewConnectionCallback newConnectionCallback_; + Channel acceptChannel_; + void readCallback(); +}; +} // namespace trantor diff --git a/core/net/resolvers/ares_resolver.cpp b/web_backends/drogon/trantor/net/inner/AresResolver.cc similarity index 65% rename from core/net/resolvers/ares_resolver.cpp rename to web_backends/drogon/trantor/net/inner/AresResolver.cc index dde3f0d..0b08425 100644 --- a/core/net/resolvers/ares_resolver.cpp +++ b/web_backends/drogon/trantor/net/inner/AresResolver.cc @@ -1,36 +1,13 @@ - -// This file is originally from Trantor - AresResolver.cc - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: +// Copyright 2016, Tao An. All rights reserved. // -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// Use of this source code is governed by a BSD-style license +// that can be found in the License file. -#include "ares_resolver.h" -#include "core/net/channel.h" +// Author: Tao An + +#include "AresResolver.h" #include +#include #ifdef _WIN32 #include #else @@ -42,8 +19,10 @@ #include #include +using namespace trantor; using namespace std::placeholders; +namespace { double getSeconds(struct timeval *tv) { if (tv) return double(tv->tv_sec) + double(tv->tv_usec) / 1000000.0; @@ -60,6 +39,8 @@ const char *getSocketType(int type) { return "Unknown"; } +} // namespace + bool Resolver::isCAresUsed() { return true; } @@ -67,14 +48,14 @@ bool Resolver::isCAresUsed() { AresResolver::LibraryInitializer::LibraryInitializer() { ares_library_init(ARES_LIB_INIT_ALL); } - AresResolver::LibraryInitializer::~LibraryInitializer() { ares_library_cleanup(); } AresResolver::LibraryInitializer AresResolver::libraryInitializer_; -std::shared_ptr Resolver::newResolver(EventLoop *loop, size_t timeout) { +std::shared_ptr Resolver::newResolver(trantor::EventLoop *loop, + size_t timeout) { return std::make_shared(loop, timeout); } @@ -84,7 +65,6 @@ AresResolver::AresResolver(EventLoop *loop, size_t timeout) : loop_ = getLoop(); } } - void AresResolver::init() { if (!ctx_) { struct ares_options options; @@ -109,34 +89,35 @@ void AresResolver::init() { this); } } - AresResolver::~AresResolver() { if (ctx_) ares_destroy(ctx_); } -void AresResolver::resolveInLoop(const std::string &hostname, const Callback &cb) { - +void AresResolver::resolveInLoop(const std::string &hostname, + const Callback &cb) { loop_->assertInLoopThread(); - #ifdef _WIN32 if (hostname == "localhost") { - const static InetAddress localhost_{ "127.0.0.1", 0 }; + const static trantor::InetAddress localhost_{ "127.0.0.1", 0 }; cb(localhost_); return; } #endif - init(); QueryData *queryData = new QueryData(this, cb, hostname); - ares_gethostbyname(ctx_, hostname.c_str(), AF_INET, &AresResolver::ares_hostcallback_, queryData); + ares_gethostbyname(ctx_, + hostname.c_str(), + AF_INET, + &AresResolver::ares_hostcallback_, + queryData); struct timeval tv; struct timeval *tvp = ares_timeout(ctx_, NULL, &tv); double timeout = getSeconds(tvp); - // LOG_DEBUG << "timeout " << timeout << " active " << timerActive_; if (!timerActive_ && timeout >= 0.0) { - loop_->runAfter(timeout, std::bind(&AresResolver::onTimer, shared_from_this())); + loop_->runAfter(timeout, + std::bind(&AresResolver::onTimer, shared_from_this())); timerActive_ = true; } return; @@ -161,26 +142,25 @@ void AresResolver::onTimer() { } } -void AresResolver::onQueryResult(int status, struct hostent *result, const std::string &hostname, const Callback &callback) { - +void AresResolver::onQueryResult(int status, + struct hostent *result, + const std::string &hostname, + const Callback &callback) { LOG_TRACE << "onQueryResult " << status; struct sockaddr_in addr; memset(&addr, 0, sizeof addr); addr.sin_family = AF_INET; addr.sin_port = 0; - if (result) { addr.sin_addr = *reinterpret_cast(result->h_addr); } - InetAddress inet(addr); { std::lock_guard lock(globalMutex()); auto &addrItem = globalCache()[hostname]; addrItem.first = addr.sin_addr; - addrItem.second = Date::date(); + addrItem.second = trantor::Date::date(); } - callback(inet); } @@ -199,7 +179,6 @@ void AresResolver::onSockStateChange(int sockfd, bool read, bool write) { loop_->assertInLoopThread(); ChannelList::iterator it = channels_.find(sockfd); assert(it != channels_.end()); - if (read) { // update // if (write) { } else { } @@ -211,12 +190,17 @@ void AresResolver::onSockStateChange(int sockfd, bool read, bool write) { } } -void AresResolver::ares_hostcallback_(void *data, int status, int timeouts, struct hostent *hostent) { +void AresResolver::ares_hostcallback_(void *data, + int status, + int timeouts, + struct hostent *hostent) { (void)timeouts; QueryData *query = static_cast(data); - query->owner_->onQueryResult(status, hostent, query->hostname_, query->callback_); - + query->owner_->onQueryResult(status, + hostent, + query->hostname_, + query->callback_); delete query; } @@ -239,7 +223,6 @@ void AresResolver::ares_sock_statecallback_(void *data, #endif int read, int write) { - LOG_TRACE << "sockfd=" << sockfd << " read=" << read << " write=" << write; static_cast(data)->onSockStateChange(sockfd, read, write); } diff --git a/web_backends/drogon/trantor/net/inner/AresResolver.h b/web_backends/drogon/trantor/net/inner/AresResolver.h new file mode 100644 index 0000000..6f4adac --- /dev/null +++ b/web_backends/drogon/trantor/net/inner/AresResolver.h @@ -0,0 +1,148 @@ +// Copyright 2016, Tao An. All rights reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the License file. + +// Author: Tao An + +#pragma once +#include +#include +#include +#include +#include +#include + +extern "C" +{ + struct hostent; + struct ares_channeldata; + using ares_channel = struct ares_channeldata*; +} +namespace trantor +{ +class AresResolver : public Resolver, + public NonCopyable, + public std::enable_shared_from_this +{ + public: + AresResolver(trantor::EventLoop* loop, size_t timeout); + ~AresResolver(); + + virtual void resolve(const std::string& hostname, + const Callback& cb) override + { + bool cached = false; + InetAddress inet; + { + std::lock_guard lock(globalMutex()); + auto iter = globalCache().find(hostname); + if (iter != globalCache().end()) + { + auto& cachedAddr = iter->second; + if (timeout_ == 0 || + cachedAddr.second.after(timeout_) > trantor::Date::date()) + { + struct sockaddr_in addr; + memset(&addr, 0, sizeof addr); + addr.sin_family = AF_INET; + addr.sin_port = 0; + addr.sin_addr = cachedAddr.first; + inet = InetAddress(addr); + cached = true; + } + } + } + if (cached) + { + cb(inet); + return; + } + if (loop_->isInLoopThread()) + { + resolveInLoop(hostname, cb); + } + else + { + loop_->queueInLoop([thisPtr = shared_from_this(), hostname, cb]() { + thisPtr->resolveInLoop(hostname, cb); + }); + } + } + + private: + struct QueryData + { + AresResolver* owner_; + Callback callback_; + std::string hostname_; + QueryData(AresResolver* o, + const Callback& cb, + const std::string& hostname) + : owner_(o), callback_(cb), hostname_(hostname) + { + } + }; + void resolveInLoop(const std::string& hostname, const Callback& cb); + void init(); + trantor::EventLoop* loop_; + ares_channel ctx_{nullptr}; + bool timerActive_{false}; + using ChannelList = std::map>; + ChannelList channels_; + static std::unordered_map>& + globalCache() + { + static std::unordered_map> + dnsCache; + return dnsCache; + } + static std::mutex& globalMutex() + { + static std::mutex mutex_; + return mutex_; + } + static EventLoop* getLoop() + { + static EventLoopThread loopThread; + loopThread.run(); + return loopThread.getLoop(); + } + const size_t timeout_{60}; + + void onRead(int sockfd); + void onTimer(); + void onQueryResult(int status, + struct hostent* result, + const std::string& hostname, + const Callback& callback); + void onSockCreate(int sockfd, int type); + void onSockStateChange(int sockfd, bool read, bool write); + + static void ares_hostcallback_(void* data, + int status, + int timeouts, + struct hostent* hostent); +#ifdef _WIN32 + static int ares_sock_createcallback_(SOCKET sockfd, int type, void* data); +#else + static int ares_sock_createcallback_(int sockfd, int type, void* data); +#endif + static void ares_sock_statecallback_(void* data, +#ifdef _WIN32 + SOCKET sockfd, +#else + int sockfd, +#endif + int read, + int write); + struct LibraryInitializer + { + LibraryInitializer(); + ~LibraryInitializer(); + }; + static LibraryInitializer libraryInitializer_; +}; +} // namespace trantor diff --git a/core/net/connector.cpp b/web_backends/drogon/trantor/net/inner/Connector.cc similarity index 72% rename from core/net/connector.cpp rename to web_backends/drogon/trantor/net/inner/Connector.cc index af8102f..7a69bbf 100644 --- a/core/net/connector.cpp +++ b/web_backends/drogon/trantor/net/inner/Connector.cc @@ -1,41 +1,26 @@ +/** + * + * @file Connector.cc + * @author An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ -// This file is originally from Trantor - Connector.cc +#include "Connector.h" +#include "Channel.h" +#include "Socket.h" -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "connector.h" -#include "channel.h" -#include "core/net/socket.h" +using namespace trantor; Connector::Connector(EventLoop *loop, const InetAddress &addr, bool retry) : loop_(loop), serverAddr_(addr), retry_(retry) { } - Connector::Connector(EventLoop *loop, InetAddress &&addr, bool retry) : loop_(loop), serverAddr_(std::move(addr)), retry_(retry) { } @@ -44,10 +29,8 @@ void Connector::start() { connect_ = true; loop_->runInLoop([this]() { startInLoop(); }); } - void Connector::restart() { } - void Connector::stop() { } @@ -60,7 +43,6 @@ void Connector::startInLoop() { LOG_DEBUG << "do not connect"; } } - void Connector::connect() { int sockfd = Socket::createNonblockingSocketOrDie(serverAddr_.family()); errno = 0; diff --git a/web_backends/drogon/trantor/net/inner/Connector.h b/web_backends/drogon/trantor/net/inner/Connector.h new file mode 100644 index 0000000..2c943ba --- /dev/null +++ b/web_backends/drogon/trantor/net/inner/Connector.h @@ -0,0 +1,88 @@ +/** + * + * Connector.h + * An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#pragma once + +#include +#include +#include +#include + +namespace trantor +{ +class Connector : public NonCopyable, + public std::enable_shared_from_this +{ + public: + using NewConnectionCallback = std::function; + using ConnectionErrorCallback = std::function; + Connector(EventLoop *loop, const InetAddress &addr, bool retry = true); + Connector(EventLoop *loop, InetAddress &&addr, bool retry = true); + void setNewConnectionCallback(const NewConnectionCallback &cb) + { + newConnectionCallback_ = cb; + } + void setNewConnectionCallback(NewConnectionCallback &&cb) + { + newConnectionCallback_ = std::move(cb); + } + void setErrorCallback(const ConnectionErrorCallback &cb) + { + errorCallback_ = cb; + } + void setErrorCallback(ConnectionErrorCallback &&cb) + { + errorCallback_ = std::move(cb); + } + const InetAddress &serverAddress() const + { + return serverAddr_; + } + void start(); + void restart(); + void stop(); + + private: + NewConnectionCallback newConnectionCallback_; + ConnectionErrorCallback errorCallback_; + enum class Status + { + Disconnected, + Connecting, + Connected + }; + static constexpr int kMaxRetryDelayMs = 30 * 1000; + static constexpr int kInitRetryDelayMs = 500; + std::shared_ptr channelPtr_; + EventLoop *loop_; + InetAddress serverAddr_; + + std::atomic_bool connect_{false}; + std::atomic status_{Status::Disconnected}; + + int retryInterval_{kInitRetryDelayMs}; + int maxRetryInterval_{kMaxRetryDelayMs}; + + bool retry_; + + void startInLoop(); + void connect(); + void connecting(int sockfd); + int removeAndResetChannel(); + void handleWrite(); + void handleError(); + void retry(int sockfd); +}; + +} // namespace trantor diff --git a/core/net/resolvers/normal_resolver.cpp b/web_backends/drogon/trantor/net/inner/NormalResolver.cc similarity index 53% rename from core/net/resolvers/normal_resolver.cpp rename to web_backends/drogon/trantor/net/inner/NormalResolver.cc index 0354506..6ea075e 100644 --- a/core/net/resolvers/normal_resolver.cpp +++ b/web_backends/drogon/trantor/net/inner/NormalResolver.cc @@ -1,35 +1,5 @@ - -// This file is originally from Trantor - NormalResolver.cc - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "normal_resolver.h" -#include "core/log/logger.h" +#include "NormalResolver.h" +#include #ifdef _WIN32 #include #else @@ -40,15 +10,15 @@ #include #endif -std::shared_ptr Resolver::newResolver(EventLoop *, +using namespace trantor; + +std::shared_ptr Resolver::newResolver(trantor::EventLoop *, size_t timeout) { return std::make_shared(timeout); } - bool Resolver::isCAresUsed() { return false; } - void NormalResolver::resolve(const std::string &hostname, const Callback &callback) { { @@ -57,7 +27,7 @@ void NormalResolver::resolve(const std::string &hostname, if (iter != globalCache().end()) { auto &cachedAddr = iter->second; if (timeout_ == 0 || cachedAddr.second.after(static_cast( - timeout_)) > Date::date()) { + timeout_)) > trantor::Date::date()) { callback(cachedAddr.first); return; } @@ -73,7 +43,7 @@ void NormalResolver::resolve(const std::string &hostname, auto &cachedAddr = iter->second; if (thisPtr->timeout_ == 0 || cachedAddr.second.after(static_cast( - thisPtr->timeout_)) > Date::date()) { + thisPtr->timeout_)) > trantor::Date::date()) { callback(cachedAddr.first); return; } @@ -107,7 +77,7 @@ void NormalResolver::resolve(const std::string &hostname, std::lock_guard guard(thisPtr->globalMutex()); auto &addrItem = thisPtr->globalCache()[hostname]; addrItem.first = inet; - addrItem.second = Date::date(); + addrItem.second = trantor::Date::date(); } return; }); diff --git a/web_backends/drogon/trantor/net/inner/NormalResolver.h b/web_backends/drogon/trantor/net/inner/NormalResolver.h new file mode 100644 index 0000000..bc19e0f --- /dev/null +++ b/web_backends/drogon/trantor/net/inner/NormalResolver.h @@ -0,0 +1,62 @@ +// Copyright 2016, Tao An. All rights reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the License file. + +// Author: Tao An + +#pragma once +#include +#include +#include +#include +#include +#include + +namespace trantor +{ +constexpr size_t kResolveBufferLength{16 * 1024}; +class NormalResolver : public Resolver, + public NonCopyable, + public std::enable_shared_from_this +{ + public: + virtual void resolve(const std::string& hostname, + const Callback& callback) override; + explicit NormalResolver(size_t timeout) + : timeout_(timeout), resolveBuffer_(kResolveBufferLength) + { + } + virtual ~NormalResolver() + { + } + + private: + static std::unordered_map>& + globalCache() + { + static std::unordered_map< + std::string, + std::pair> + dnsCache_; + return dnsCache_; + } + static std::mutex& globalMutex() + { + static std::mutex mutex_; + return mutex_; + } + static trantor::ConcurrentTaskQueue& concurrentTaskQueue() + { + static trantor::ConcurrentTaskQueue queue( + std::thread::hardware_concurrency() < 8 + ? 8 + : std::thread::hardware_concurrency(), + "Dns Queue"); + return queue; + } + const size_t timeout_; + std::vector resolveBuffer_; +}; +} // namespace trantor \ No newline at end of file diff --git a/web_backends/drogon/trantor/net/inner/Poller.cc b/web_backends/drogon/trantor/net/inner/Poller.cc new file mode 100644 index 0000000..89405c5 --- /dev/null +++ b/web_backends/drogon/trantor/net/inner/Poller.cc @@ -0,0 +1,31 @@ +/** + * + * Poller.cc + * An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#include "Poller.h" +#ifdef __linux__ +#include "poller/EpollPoller.h" +#elif defined _WIN32 +#include "Wepoll.h" +#include "poller/EpollPoller.h" +#else +#include "poller/KQueue.h" +#endif +using namespace trantor; +Poller *Poller::newPoller(EventLoop *loop) { +#if defined __linux__ || defined _WIN32 + return new EpollPoller(loop); +#else + return new KQueue(loop); +#endif +} diff --git a/web_backends/drogon/trantor/net/inner/Poller.h b/web_backends/drogon/trantor/net/inner/Poller.h new file mode 100644 index 0000000..9261824 --- /dev/null +++ b/web_backends/drogon/trantor/net/inner/Poller.h @@ -0,0 +1,54 @@ +/** + * + * Poller.h + * An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#pragma once +#include "NonCopyable.h" +#include "EventLoop.h" + +#include +#include + +namespace trantor +{ +class Channel; +#ifdef _WIN32 +using EventCallback = std::function; +#endif +class Poller : NonCopyable +{ + public: + explicit Poller(EventLoop *loop) : ownerLoop_(loop){}; + virtual ~Poller() + { + } + void assertInLoopThread() + { + ownerLoop_->assertInLoopThread(); + } + virtual void poll(int timeoutMs, ChannelList *activeChannels) = 0; + virtual void updateChannel(Channel *channel) = 0; + virtual void removeChannel(Channel *channel) = 0; +#ifdef _WIN32 + virtual void postEvent(uint64_t event) = 0; + virtual void setEventCallback(const EventCallback &cb) = 0; +#endif + virtual void resetAfterFork() + { + } + static Poller *newPoller(EventLoop *loop); + + private: + EventLoop *ownerLoop_; +}; +} // namespace trantor diff --git a/core/net/socket.cpp b/web_backends/drogon/trantor/net/inner/Socket.cc similarity index 73% rename from core/net/socket.cpp rename to web_backends/drogon/trantor/net/inner/Socket.cc index c3669e8..5fc8e76 100644 --- a/core/net/socket.cpp +++ b/web_backends/drogon/trantor/net/inner/Socket.cc @@ -1,37 +1,21 @@ +/** + * + * Socket.cc + * An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ -// This file is originally from Trantor - Socket.cc - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "socket.h" -#include "core/log/logger.h" +#include "Socket.h" #include #include +#include #ifdef _WIN32 #include #else @@ -39,6 +23,8 @@ #include #endif +using namespace trantor; + bool Socket::isSelfConnect(int sockfd) { struct sockaddr_in6 localaddr = getLocalAddr(sockfd); struct sockaddr_in6 peeraddr = getPeerAddr(sockfd); @@ -74,7 +60,6 @@ void Socket::bindAddress(const InetAddress &localaddr) { exit(1); } } - void Socket::listen() { assert(sockFd_ > 0); int ret = ::listen(sockFd_, SOMAXCONN); @@ -83,7 +68,6 @@ void Socket::listen() { exit(1); } } - int Socket::accept(InetAddress *peeraddr) { struct sockaddr_in6 addr6; memset(&addr6, 0, sizeof(addr6)); @@ -103,7 +87,6 @@ int Socket::accept(InetAddress *peeraddr) { } return connfd; } - void Socket::closeWrite() { #ifndef _WIN32 if (::shutdown(sockFd_, SHUT_WR) < 0) @@ -114,7 +97,6 @@ void Socket::closeWrite() { LOG_SYSERR << "sockets::shutdownWrite"; } } - int Socket::read(char *buffer, uint64_t len) { #ifndef _WIN32 return ::read(sockFd_, buffer, len); diff --git a/web_backends/drogon/trantor/net/inner/Socket.h b/web_backends/drogon/trantor/net/inner/Socket.h new file mode 100644 index 0000000..8cce9dd --- /dev/null +++ b/web_backends/drogon/trantor/net/inner/Socket.h @@ -0,0 +1,157 @@ +/** + * + * Socket.h + * An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#pragma once + +#include +#include +#include +#include +#ifndef _WIN32 +#include +#endif +#include + +namespace trantor +{ +class Socket : NonCopyable +{ + public: + static int createNonblockingSocketOrDie(int family) + { +#ifdef __linux__ + int sock = ::socket(family, + SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, + IPPROTO_TCP); +#else + int sock = static_cast(::socket(family, SOCK_STREAM, IPPROTO_TCP)); + setNonBlockAndCloseOnExec(sock); +#endif + if (sock < 0) + { + LOG_SYSERR << "sockets::createNonblockingOrDie"; + exit(1); + } + LOG_TRACE << "sock=" << sock; + return sock; + } + + static int getSocketError(int sockfd) + { + int optval; + socklen_t optlen = static_cast(sizeof optval); +#ifdef _WIN32 + if (::getsockopt( + sockfd, SOL_SOCKET, SO_ERROR, (char *)&optval, &optlen) < 0) +#else + if (::getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) < 0) +#endif + { + return errno; + } + else + { + return optval; + } + } + + static int connect(int sockfd, const InetAddress &addr) + { + if (addr.isIpV6()) + return ::connect(sockfd, + addr.getSockAddr(), + static_cast( + sizeof(struct sockaddr_in6))); + else + return ::connect(sockfd, + addr.getSockAddr(), + static_cast( + sizeof(struct sockaddr_in))); + } + + static bool isSelfConnect(int sockfd); + + explicit Socket(int sockfd) : sockFd_(sockfd) + { + } + ~Socket(); + /// abort if address in use + void bindAddress(const InetAddress &localaddr); + /// abort if address in use + void listen(); + int accept(InetAddress *peeraddr); + void closeWrite(); + int read(char *buffer, uint64_t len); + int fd() + { + return sockFd_; + } + static struct sockaddr_in6 getLocalAddr(int sockfd); + static struct sockaddr_in6 getPeerAddr(int sockfd); + + /// + /// Enable/disable TCP_NODELAY (disable/enable Nagle's algorithm). + /// + void setTcpNoDelay(bool on); + + /// + /// Enable/disable SO_REUSEADDR + /// + void setReuseAddr(bool on); + + /// + /// Enable/disable SO_REUSEPORT + /// + void setReusePort(bool on); + + /// + /// Enable/disable SO_KEEPALIVE + /// + void setKeepAlive(bool on); + int getSocketError(); + + protected: + int sockFd_; + + public: + // taken from muduo + static void setNonBlockAndCloseOnExec(int sockfd) + { +#ifdef _WIN32 + // TODO how to set FD_CLOEXEC on windows? is it necessary? + u_long arg = 1; + auto ret = ioctlsocket(sockfd, (long)FIONBIO, &arg); + if (ret) + { + LOG_ERROR << "ioctlsocket error"; + } +#else + // non-block + int flags = ::fcntl(sockfd, F_GETFL, 0); + flags |= O_NONBLOCK; + int ret = ::fcntl(sockfd, F_SETFL, flags); + // TODO check + + // close-on-exec + flags = ::fcntl(sockfd, F_GETFD, 0); + flags |= FD_CLOEXEC; + ret = ::fcntl(sockfd, F_SETFD, flags); + // TODO check + + (void)ret; +#endif + } +}; + +} // namespace trantor diff --git a/core/net/connections/tcp_connection_impl.cpp b/web_backends/drogon/trantor/net/inner/TcpConnectionImpl.cc similarity index 80% rename from core/net/connections/tcp_connection_impl.cpp rename to web_backends/drogon/trantor/net/inner/TcpConnectionImpl.cc index 175dea2..494f338 100644 --- a/core/net/connections/tcp_connection_impl.cpp +++ b/web_backends/drogon/trantor/net/inner/TcpConnectionImpl.cc @@ -1,36 +1,20 @@ +/** + * + * @file TcpConnectionImpl.cc + * @author An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ -// This file is originally from Trantor - TcpConnectionImpl.cc - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "tcp_connection_impl.h" -#include "core/net/channel.h" -#include "core/net/socket.h" +#include "TcpConnectionImpl.h" +#include "Channel.h" +#include "Socket.h" #ifdef __linux__ #include #endif @@ -54,7 +38,10 @@ #endif #include +using namespace trantor; + #ifdef USE_OPENSSL +namespace trantor { namespace internal { #ifdef _WIN32 // Code yanked from stackoverflow @@ -67,11 +54,12 @@ inline bool loadWindowsSystemCert(X509_STORE *store) { } PCCERT_CONTEXT pContext = NULL; - while ((pContext = CertEnumCertificatesInStore(hStore, pContext)) != nullptr) { - auto encoded_cert = static_cast(pContext->pbCertEncoded); + while ((pContext = CertEnumCertificatesInStore(hStore, pContext)) != + nullptr) { + auto encoded_cert = + static_cast(pContext->pbCertEncoded); auto x509 = d2i_X509(NULL, &encoded_cert, pContext->cbCertEncoded); - if (x509) { X509_STORE_add_cert(store, x509); X509_free(x509); @@ -124,12 +112,15 @@ inline bool verifyCommonName(X509 *cert, const std::string &hostname) { if (subjectName != nullptr) { std::array name; - auto length = X509_NAME_get_text_by_NID(subjectName, NID_commonName, name.data(), (int)name.size()); - + auto length = X509_NAME_get_text_by_NID(subjectName, + NID_commonName, + name.data(), + (int)name.size()); if (length == -1) return false; - return verifyName(std::string(name.begin(), name.begin() + length), hostname); + return verifyName(std::string(name.begin(), name.begin() + length), + hostname); } return false; @@ -137,7 +128,8 @@ inline bool verifyCommonName(X509 *cert, const std::string &hostname) { inline bool verifyAltName(X509 *cert, const std::string &hostname) { bool good = false; - auto altNames = static_cast(X509_get_ext_d2i(cert, NID_subject_alt_name, nullptr, nullptr)); + auto altNames = static_cast( + X509_get_ext_d2i(cert, NID_subject_alt_name, nullptr, nullptr)); if (altNames) { int numNames = sk_GENERAL_NAME_num(altNames); @@ -149,7 +141,6 @@ inline bool verifyAltName(X509 *cert, const std::string &hostname) { "an issue if you need that feature"; continue; } - #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) auto name = (const char *)ASN1_STRING_get0_data(val->d.ia5); #else @@ -167,10 +158,11 @@ inline bool verifyAltName(X509 *cert, const std::string &hostname) { } // namespace internal void initOpenSSL() { -#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L) +#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \ + (defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER < 0x20700000L) // Initialize OpenSSL once; static std::once_flag once; - std::call_once(once, []() { SSL_library_init(); ERR_load_crypto_strings(); @@ -182,7 +174,10 @@ void initOpenSSL() { class SSLContext { public: - explicit SSLContext(bool useOldTLS, bool enableValidtion, const std::vector > &sslConfCmds) { + explicit SSLContext( + bool useOldTLS, + bool enableValidtion, + const std::vector > &sslConfCmds) { #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) ctxPtr_ = SSL_CTX_new(TLS_method()); SSL_CONF_CTX *cctx = SSL_CONF_CTX_new(); @@ -191,11 +186,9 @@ public: SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CERTIFICATE); SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_FILE); SSL_CONF_CTX_set_ssl_ctx(cctx, ctxPtr_); - for (const auto &cmd : sslConfCmds) { SSL_CONF_cmd(cctx, cmd.first.data(), cmd.second.data()); } - SSL_CONF_CTX_finish(cctx); if (!useOldTLS) { SSL_CTX_set_min_proto_version(ctxPtr_, TLS1_2_VERSION); @@ -204,7 +197,6 @@ public: "obsolete, insecure standards and should only be " "used for legacy purpose."; } - #else ctxPtr_ = SSL_CTX_new(SSLv23_method()); SSL_CONF_CTX *cctx = SSL_CONF_CTX_new(); @@ -213,13 +205,10 @@ public: SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CERTIFICATE); SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_FILE); SSL_CONF_CTX_set_ssl_ctx(cctx, ctxPtr_); - for (const auto &cmd : sslConfCmds) { SSL_CONF_cmd(cctx, cmd.first.data(), cmd.second.data()); } - SSL_CONF_CTX_finish(cctx); - if (!useOldTLS) { SSL_CTX_set_options(ctxPtr_, SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1); } else { @@ -236,7 +225,6 @@ public: SSL_CTX_set_default_verify_paths(ctxPtr_); #endif } - ~SSLContext() { if (ctxPtr_) { SSL_CTX_free(ctxPtr_); @@ -250,7 +238,6 @@ public: private: SSL_CTX *ctxPtr_; }; - class SSLConn { public: explicit SSLConn(SSL_CTX *ctx) { @@ -269,17 +256,20 @@ private: SSL *SSL_; }; -std::shared_ptr newSSLContext(bool useOldTLS, bool validateCert, const std::vector > &sslConfCmds) { // init OpenSSL +std::shared_ptr newSSLContext( + bool useOldTLS, + bool validateCert, + const std::vector > &sslConfCmds) { // init OpenSSL initOpenSSL(); return std::make_shared(useOldTLS, validateCert, sslConfCmds); } - -std::shared_ptr newSSLServerContext(const std::string &certPath, const std::string &keyPath, bool useOldTLS, const std::vector > &sslConfCmds) { - +std::shared_ptr newSSLServerContext( + const std::string &certPath, + const std::string &keyPath, + bool useOldTLS, + const std::vector > &sslConfCmds) { auto ctx = newSSLContext(useOldTLS, false, sslConfCmds); - auto r = SSL_CTX_use_certificate_chain_file(ctx->get(), certPath.c_str()); - if (!r) { #ifndef _MSC_VER LOG_FATAL << strerror(errno); @@ -288,9 +278,9 @@ std::shared_ptr newSSLServerContext(const std::string &certPath, con #endif abort(); } - - r = SSL_CTX_use_PrivateKey_file(ctx->get(), keyPath.c_str(), SSL_FILETYPE_PEM); - + r = SSL_CTX_use_PrivateKey_file(ctx->get(), + keyPath.c_str(), + SSL_FILETYPE_PEM); if (!r) { #ifndef _MSC_VER LOG_FATAL << strerror(errno); @@ -299,9 +289,7 @@ std::shared_ptr newSSLServerContext(const std::string &certPath, con #endif abort(); } - r = SSL_CTX_check_private_key(ctx->get()); - if (!r) { #ifndef _MSC_VER LOG_FATAL << strerror(errno); @@ -310,100 +298,113 @@ std::shared_ptr newSSLServerContext(const std::string &certPath, con #endif abort(); } - return ctx; } - +} // namespace trantor #else - -std::shared_ptr newSSLServerContext(const std::string &certPath, const std::string &keyPath, bool useOldTLS, const std::vector > &sslConfCmds) { +namespace trantor { +std::shared_ptr newSSLServerContext( + const std::string &certPath, + const std::string &keyPath, + bool useOldTLS, + const std::vector > &sslConfCmds) { LOG_FATAL << "OpenSSL is not found in your system!"; abort(); } - +} // namespace trantor #endif -TcpConnectionImpl::TcpConnectionImpl(EventLoop *loop, int socketfd, const InetAddress &localAddr, const InetAddress &peerAddr) : - loop_(loop), ioChannelPtr_(new Channel(loop, socketfd)), socketPtr_(new Socket(socketfd)), localAddr_(localAddr), peerAddr_(peerAddr) { - LOG_TRACE << "new connection:" << peerAddr.toIpPort() << "->" << localAddr.toIpPort(); - - ioChannelPtr_->setReadCallback(std::bind(&TcpConnectionImpl::readCallback, this)); - ioChannelPtr_->setWriteCallback(std::bind(&TcpConnectionImpl::writeCallback, this)); - ioChannelPtr_->setCloseCallback(std::bind(&TcpConnectionImpl::handleClose, this)); - ioChannelPtr_->setErrorCallback(std::bind(&TcpConnectionImpl::handleError, this)); +TcpConnectionImpl::TcpConnectionImpl(EventLoop *loop, + int socketfd, + const InetAddress &localAddr, + const InetAddress &peerAddr) : + loop_(loop), + ioChannelPtr_(new Channel(loop, socketfd)), + socketPtr_(new Socket(socketfd)), + localAddr_(localAddr), + peerAddr_(peerAddr) { + LOG_TRACE << "new connection:" << peerAddr.toIpPort() << "->" + << localAddr.toIpPort(); + ioChannelPtr_->setReadCallback( + std::bind(&TcpConnectionImpl::readCallback, this)); + ioChannelPtr_->setWriteCallback( + std::bind(&TcpConnectionImpl::writeCallback, this)); + ioChannelPtr_->setCloseCallback( + std::bind(&TcpConnectionImpl::handleClose, this)); + ioChannelPtr_->setErrorCallback( + std::bind(&TcpConnectionImpl::handleError, this)); socketPtr_->setKeepAlive(true); - name_ = localAddr.toIpPort() + "--" + peerAddr.toIpPort(); } - TcpConnectionImpl::~TcpConnectionImpl() { } - #ifdef USE_OPENSSL -void TcpConnectionImpl::startClientEncryptionInLoop(std::function &&callback, bool useOldTLS, bool validateCert, const std::string &hostname, const std::vector > &sslConfCmds) { +void TcpConnectionImpl::startClientEncryptionInLoop( + std::function &&callback, + bool useOldTLS, + bool validateCert, + const std::string &hostname, + const std::vector > &sslConfCmds) { validateCert_ = validateCert; loop_->assertInLoopThread(); - if (isEncrypted_) { LOG_WARN << "This connection is already encrypted"; return; } - sslEncryptionPtr_ = std::make_unique(); sslEncryptionPtr_->upgradeCallback_ = std::move(callback); - sslEncryptionPtr_->sslCtxPtr_ = newSSLContext(useOldTLS, validateCert_, sslConfCmds); - sslEncryptionPtr_->sslPtr_ = std::make_unique(sslEncryptionPtr_->sslCtxPtr_->get()); - + sslEncryptionPtr_->sslCtxPtr_ = + newSSLContext(useOldTLS, validateCert_, sslConfCmds); + sslEncryptionPtr_->sslPtr_ = + std::make_unique(sslEncryptionPtr_->sslCtxPtr_->get()); if (validateCert) { - SSL_set_verify(sslEncryptionPtr_->sslPtr_->get(), SSL_VERIFY_NONE, nullptr); + SSL_set_verify(sslEncryptionPtr_->sslPtr_->get(), + SSL_VERIFY_NONE, + nullptr); validateCert_ = validateCert; } - if (!hostname.empty()) { SSL_set_tlsext_host_name(sslEncryptionPtr_->sslPtr_->get(), hostname.data()); sslEncryptionPtr_->hostname_ = hostname; } - isEncrypted_ = true; sslEncryptionPtr_->isUpgrade_ = true; auto r = SSL_set_fd(sslEncryptionPtr_->sslPtr_->get(), socketPtr_->fd()); (void)r; assert(r); - - sslEncryptionPtr_->sendBufferPtr_ = std::make_unique >(); + sslEncryptionPtr_->sendBufferPtr_ = + std::make_unique >(); LOG_TRACE << "connectEstablished"; ioChannelPtr_->enableWriting(); SSL_set_connect_state(sslEncryptionPtr_->sslPtr_->get()); } - -void TcpConnectionImpl::startServerEncryptionInLoop(const std::shared_ptr &ctx, std::function &&callback) { +void TcpConnectionImpl::startServerEncryptionInLoop( + const std::shared_ptr &ctx, + std::function &&callback) { loop_->assertInLoopThread(); - if (isEncrypted_) { LOG_WARN << "This connection is already encrypted"; return; } - sslEncryptionPtr_ = std::make_unique(); sslEncryptionPtr_->upgradeCallback_ = std::move(callback); sslEncryptionPtr_->sslCtxPtr_ = ctx; sslEncryptionPtr_->isServer_ = true; - sslEncryptionPtr_->sslPtr_ = std::make_unique(sslEncryptionPtr_->sslCtxPtr_->get()); + sslEncryptionPtr_->sslPtr_ = + std::make_unique(sslEncryptionPtr_->sslCtxPtr_->get()); isEncrypted_ = true; sslEncryptionPtr_->isUpgrade_ = true; - - if (sslEncryptionPtr_->isServer_ == false) { - SSL_set_verify(sslEncryptionPtr_->sslPtr_->get(), SSL_VERIFY_NONE, nullptr); - } - + if (sslEncryptionPtr_->isServer_ == false) + SSL_set_verify(sslEncryptionPtr_->sslPtr_->get(), + SSL_VERIFY_NONE, + nullptr); auto r = SSL_set_fd(sslEncryptionPtr_->sslPtr_->get(), socketPtr_->fd()); (void)r; assert(r); - - sslEncryptionPtr_->sendBufferPtr_ = std::make_unique >(); + sslEncryptionPtr_->sendBufferPtr_ = + std::make_unique >(); LOG_TRACE << "upgrade to ssl"; - SSL_set_accept_state(sslEncryptionPtr_->sslPtr_->get()); } #endif @@ -426,13 +427,16 @@ void TcpConnectionImpl::startServerEncryption( #endif } - -void TcpConnectionImpl::startClientEncryption(std::function callback, bool useOldTLS, bool validateCert, std::string hostname, const std::vector > &sslConfCmds) { +void TcpConnectionImpl::startClientEncryption( + std::function callback, + bool useOldTLS, + bool validateCert, + std::string hostname, + const std::vector > &sslConfCmds) { #ifndef USE_OPENSSL LOG_FATAL << "OpenSSL is not found in your system!"; abort(); #else - if (!hostname.empty()) { std::transform(hostname.begin(), hostname.end(), @@ -441,17 +445,28 @@ void TcpConnectionImpl::startClientEncryption(std::function callback, bo assert(sslEncryptionPtr_ != nullptr); sslEncryptionPtr_->hostname_ = hostname; } - if (loop_->isInLoopThread()) { - startClientEncryptionInLoop(std::move(callback), useOldTLS, validateCert, hostname, sslConfCmds); + startClientEncryptionInLoop(std::move(callback), + useOldTLS, + validateCert, + hostname, + sslConfCmds); } else { - loop_->queueInLoop([thisPtr = shared_from_this(), callback = std::move(callback), useOldTLS, hostname = std::move(hostname), validateCert, &sslConfCmds]() mutable { - thisPtr->startClientEncryptionInLoop(std::move(callback), useOldTLS, validateCert, hostname, sslConfCmds); + loop_->queueInLoop([thisPtr = shared_from_this(), + callback = std::move(callback), + useOldTLS, + hostname = std::move(hostname), + validateCert, + &sslConfCmds]() mutable { + thisPtr->startClientEncryptionInLoop(std::move(callback), + useOldTLS, + validateCert, + hostname, + sslConfCmds); }); } #endif } - void TcpConnectionImpl::readCallback() { // LOG_TRACE<<"read Callback"; #ifdef USE_OPENSSL @@ -482,21 +497,17 @@ void TcpConnectionImpl::readCallback() { handleClose(); return; } - extendLife(); - if (n > 0) { bytesReceived_ += n; if (recvMsgCallback_) { recvMsgCallback_(shared_from_this(), &readBuffer_); } } - #ifdef USE_OPENSSL } else { LOG_TRACE << "read Callback"; loop_->assertInLoopThread(); - if (sslEncryptionPtr_->statusOfSSL_ == SSLStatus::Handshaking) { doHandshaking(); return; @@ -540,10 +551,8 @@ void TcpConnectionImpl::extendLife() { auto now = Date::date(); if (now < lastTimingWheelUpdateTime_.after(1.0)) return; - lastTimingWheelUpdateTime_ = now; auto entry = kickoffEntry_.lock(); - if (entry) { auto timingWheelPtr = timingWheelWeakPtr_.lock(); if (timingWheelPtr) @@ -553,11 +562,12 @@ void TcpConnectionImpl::extendLife() { } void TcpConnectionImpl::writeCallback() { #ifdef USE_OPENSSL - if (!isEncrypted_ || (sslEncryptionPtr_ && sslEncryptionPtr_->statusOfSSL_ == SSLStatus::Connected)) { + if (!isEncrypted_ || + (sslEncryptionPtr_ && + sslEncryptionPtr_->statusOfSSL_ == SSLStatus::Connected)) { #endif loop_->assertInLoopThread(); extendLife(); - if (ioChannelPtr_->isWriting()) { assert(!writeBufferList_.empty()); auto writeBuffer_ = writeBufferList_.front(); @@ -568,7 +578,6 @@ void TcpConnectionImpl::writeCallback() { #endif { if (writeBuffer_->msgBuffer_->readableBytes() <= 0) { - writeBufferList_.pop_front(); if (writeBufferList_.empty()) { ioChannelPtr_->disableWriting(); @@ -578,7 +587,6 @@ void TcpConnectionImpl::writeCallback() { if (status_ == ConnStatus::Disconnecting) { socketPtr_->closeWrite(); } - } else { auto fileNode = writeBufferList_.front(); #ifndef _WIN32 @@ -590,7 +598,8 @@ void TcpConnectionImpl::writeCallback() { } } else { auto n = - writeInLoop(writeBuffer_->msgBuffer_->peek(), writeBuffer_->msgBuffer_->readableBytes()); + writeInLoop(writeBuffer_->msgBuffer_->peek(), + writeBuffer_->msgBuffer_->readableBytes()); if (n >= 0) { writeBuffer_->msgBuffer_->retrieve(n); } else { @@ -614,7 +623,6 @@ void TcpConnectionImpl::writeCallback() { } else { // file if (writeBuffer_->fileBytesToSend_ <= 0) { - writeBufferList_.pop_front(); if (writeBufferList_.empty()) { ioChannelPtr_->disableWriting(); @@ -623,7 +631,6 @@ void TcpConnectionImpl::writeCallback() { if (status_ == ConnStatus::Disconnecting) { socketPtr_->closeWrite(); } - } else { #ifndef _WIN32 if (writeBufferList_.front()->sendFd_ < 0) @@ -632,10 +639,13 @@ void TcpConnectionImpl::writeCallback() { #endif { // There is data to be sent in the buffer. - auto n = writeInLoop(writeBufferList_.front()->msgBuffer_->peek(), writeBufferList_.front()->msgBuffer_->readableBytes()); - + auto n = writeInLoop( + writeBufferList_.front()->msgBuffer_->peek(), + writeBufferList_.front() + ->msgBuffer_->readableBytes()); if (n >= 0) { - writeBufferList_.front()->msgBuffer_->retrieve(n); + writeBufferList_.front()->msgBuffer_->retrieve( + n); } else { #ifdef _WIN32 if (errno != 0 && errno != EWOULDBLOCK) @@ -678,7 +688,6 @@ void TcpConnectionImpl::writeCallback() { } #endif } - void TcpConnectionImpl::connectEstablished() { // loop_->assertInLoopThread(); #ifdef USE_OPENSSL @@ -691,9 +700,8 @@ void TcpConnectionImpl::connectEstablished() { thisPtr->ioChannelPtr_->tie(thisPtr); thisPtr->ioChannelPtr_->enableReading(); thisPtr->status_ = ConnStatus::Connected; - if (thisPtr->connectionCallback_) { + if (thisPtr->connectionCallback_) thisPtr->connectionCallback_(thisPtr); - } }); #ifdef USE_OPENSSL } else { @@ -703,31 +711,27 @@ void TcpConnectionImpl::connectEstablished() { thisPtr->ioChannelPtr_->tie(thisPtr); thisPtr->ioChannelPtr_->enableReading(); thisPtr->status_ = ConnStatus::Connected; - if (thisPtr->sslEncryptionPtr_->isServer_) { - SSL_set_accept_state(thisPtr->sslEncryptionPtr_->sslPtr_->get()); + SSL_set_accept_state( + thisPtr->sslEncryptionPtr_->sslPtr_->get()); } else { thisPtr->ioChannelPtr_->enableWriting(); - SSL_set_connect_state(thisPtr->sslEncryptionPtr_->sslPtr_->get()); + SSL_set_connect_state( + thisPtr->sslEncryptionPtr_->sslPtr_->get()); } }); } #endif } - void TcpConnectionImpl::handleClose() { LOG_TRACE << "connection closed, fd=" << socketPtr_->fd(); loop_->assertInLoopThread(); status_ = ConnStatus::Disconnected; ioChannelPtr_->disableAll(); - // ioChannelPtr_->remove(); auto guardThis = shared_from_this(); - - if (connectionCallback_) { + if (connectionCallback_) connectionCallback_(guardThis); - } - if (closeCallback_) { LOG_TRACE << "to call close callback"; closeCallback_(guardThis); @@ -735,10 +739,8 @@ void TcpConnectionImpl::handleClose() { } void TcpConnectionImpl::handleError() { int err = socketPtr_->getSocketError(); - if (err == 0) return; - if (err == EPIPE || err == ECONNRESET || err == 104) { LOG_DEBUG << "[" << name_ << "] - SO_ERROR = " << err << " " << strerror_tl(err); @@ -747,14 +749,11 @@ void TcpConnectionImpl::handleError() { << strerror_tl(err); } } - void TcpConnectionImpl::setTcpNoDelay(bool on) { socketPtr_->setTcpNoDelay(on); } - void TcpConnectionImpl::connectDestroyed() { loop_->assertInLoopThread(); - if (status_ == ConnStatus::Connected) { status_ = ConnStatus::Disconnected; ioChannelPtr_->disableAll(); @@ -765,7 +764,6 @@ void TcpConnectionImpl::connectDestroyed() { } void TcpConnectionImpl::shutdown() { auto thisPtr = shared_from_this(); - loop_->runInLoop([thisPtr]() { if (thisPtr->status_ == ConnStatus::Connected) { thisPtr->status_ = ConnStatus::Disconnecting; @@ -778,7 +776,6 @@ void TcpConnectionImpl::shutdown() { void TcpConnectionImpl::forceClose() { auto thisPtr = shared_from_this(); - loop_->runInLoop([thisPtr]() { if (thisPtr->status_ == ConnStatus::Connected || thisPtr->status_ == ConnStatus::Disconnecting) { @@ -787,7 +784,6 @@ void TcpConnectionImpl::forceClose() { } }); } - #ifndef _WIN32 void TcpConnectionImpl::sendInLoop(const void *buffer, size_t length) #else @@ -795,20 +791,16 @@ void TcpConnectionImpl::sendInLoop(const char *buffer, size_t length) #endif { loop_->assertInLoopThread(); - if (status_ != ConnStatus::Connected) { LOG_WARN << "Connection is not connected,give up sending"; return; } - extendLife(); size_t remainLen = length; ssize_t sendLen = 0; - if (!ioChannelPtr_->isWriting() && writeBufferList_.empty()) { // send directly sendLen = writeInLoop(buffer, length); - if (sendLen < 0) { // error #ifdef _WIN32 @@ -822,7 +814,6 @@ void TcpConnectionImpl::sendInLoop(const char *buffer, size_t length) LOG_DEBUG << "EPIPE or ECONNRESET, erron=" << errno; return; } - LOG_SYSERR << "Unexpected error(" << errno << ")"; return; } @@ -830,15 +821,12 @@ void TcpConnectionImpl::sendInLoop(const char *buffer, size_t length) } remainLen -= sendLen; } - if (remainLen > 0 && status_ == ConnStatus::Connected) { - if (writeBufferList_.empty()) { BufferNodePtr node(new BufferNode); node->msgBuffer_ = std::make_shared(); writeBufferList_.push_back(std::move(node)); } - #ifndef _WIN32 else if (writeBufferList_.back()->sendFd_ >= 0) #else @@ -849,15 +837,16 @@ void TcpConnectionImpl::sendInLoop(const char *buffer, size_t length) node->msgBuffer_ = std::make_shared(); writeBufferList_.push_back(std::move(node)); } - - writeBufferList_.back()->msgBuffer_->append(static_cast(buffer) + sendLen, remainLen); - - if (!ioChannelPtr_->isWriting()) { + writeBufferList_.back()->msgBuffer_->append( + static_cast(buffer) + sendLen, remainLen); + if (!ioChannelPtr_->isWriting()) ioChannelPtr_->enableWriting(); - } - - if (highWaterMarkCallback_ && writeBufferList_.back()->msgBuffer_->readableBytes() > highWaterMarkLen_) { - highWaterMarkCallback_(shared_from_this(), writeBufferList_.back()->msgBuffer_->readableBytes()); + if (highWaterMarkCallback_ && + writeBufferList_.back()->msgBuffer_->readableBytes() > + highWaterMarkLen_) { + highWaterMarkCallback_( + shared_from_this(), + writeBufferList_.back()->msgBuffer_->readableBytes()); } } } @@ -870,7 +859,6 @@ void TcpConnectionImpl::send(const std::shared_ptr &msgPtr) { } else { ++sendNum_; auto thisPtr = shared_from_this(); - loop_->queueInLoop([thisPtr, msgPtr]() { thisPtr->sendInLoop(msgPtr->data(), msgPtr->length()); std::lock_guard guard1(thisPtr->sendNumMutex_); @@ -881,7 +869,6 @@ void TcpConnectionImpl::send(const std::shared_ptr &msgPtr) { auto thisPtr = shared_from_this(); std::lock_guard guard(sendNumMutex_); ++sendNum_; - loop_->queueInLoop([thisPtr, msgPtr]() { thisPtr->sendInLoop(msgPtr->data(), msgPtr->length()); std::lock_guard guard1(thisPtr->sendNumMutex_); @@ -898,7 +885,6 @@ void TcpConnectionImpl::send(const std::shared_ptr &msgPtr) { } else { ++sendNum_; auto thisPtr = shared_from_this(); - loop_->queueInLoop([thisPtr, msgPtr]() { thisPtr->sendInLoop(msgPtr->peek(), msgPtr->readableBytes()); std::lock_guard guard1(thisPtr->sendNumMutex_); @@ -909,7 +895,6 @@ void TcpConnectionImpl::send(const std::shared_ptr &msgPtr) { auto thisPtr = shared_from_this(); std::lock_guard guard(sendNumMutex_); ++sendNum_; - loop_->queueInLoop([thisPtr, msgPtr]() { thisPtr->sendInLoop(msgPtr->peek(), msgPtr->readableBytes()); std::lock_guard guard1(thisPtr->sendNumMutex_); @@ -926,7 +911,6 @@ void TcpConnectionImpl::send(const char *msg, size_t len) { ++sendNum_; auto buffer = std::make_shared(msg, len); auto thisPtr = shared_from_this(); - loop_->queueInLoop([thisPtr, buffer]() { thisPtr->sendInLoop(buffer->data(), buffer->length()); std::lock_guard guard1(thisPtr->sendNumMutex_); @@ -938,7 +922,6 @@ void TcpConnectionImpl::send(const char *msg, size_t len) { auto thisPtr = shared_from_this(); std::lock_guard guard(sendNumMutex_); ++sendNum_; - loop_->queueInLoop([thisPtr, buffer]() { thisPtr->sendInLoop(buffer->data(), buffer->length()); std::lock_guard guard1(thisPtr->sendNumMutex_); @@ -961,7 +944,6 @@ void TcpConnectionImpl::send(const void *msg, size_t len) { std::make_shared(static_cast(msg), len); auto thisPtr = shared_from_this(); - loop_->queueInLoop([thisPtr, buffer]() { thisPtr->sendInLoop(buffer->data(), buffer->length()); std::lock_guard guard1(thisPtr->sendNumMutex_); @@ -974,7 +956,6 @@ void TcpConnectionImpl::send(const void *msg, size_t len) { auto thisPtr = shared_from_this(); std::lock_guard guard(sendNumMutex_); ++sendNum_; - loop_->queueInLoop([thisPtr, buffer]() { thisPtr->sendInLoop(buffer->data(), buffer->length()); std::lock_guard guard1(thisPtr->sendNumMutex_); @@ -990,7 +971,6 @@ void TcpConnectionImpl::send(const std::string &msg) { } else { ++sendNum_; auto thisPtr = shared_from_this(); - loop_->queueInLoop([thisPtr, msg]() { thisPtr->sendInLoop(msg.data(), msg.length()); std::lock_guard guard1(thisPtr->sendNumMutex_); @@ -1001,7 +981,6 @@ void TcpConnectionImpl::send(const std::string &msg) { auto thisPtr = shared_from_this(); std::lock_guard guard(sendNumMutex_); ++sendNum_; - loop_->queueInLoop([thisPtr, msg]() { thisPtr->sendInLoop(msg.data(), msg.length()); std::lock_guard guard1(thisPtr->sendNumMutex_); @@ -1017,7 +996,6 @@ void TcpConnectionImpl::send(std::string &&msg) { } else { auto thisPtr = shared_from_this(); ++sendNum_; - loop_->queueInLoop([thisPtr, msg = std::move(msg)]() { thisPtr->sendInLoop(msg.data(), msg.length()); std::lock_guard guard1(thisPtr->sendNumMutex_); @@ -1028,7 +1006,6 @@ void TcpConnectionImpl::send(std::string &&msg) { auto thisPtr = shared_from_this(); std::lock_guard guard(sendNumMutex_); ++sendNum_; - loop_->queueInLoop([thisPtr, msg = std::move(msg)]() { thisPtr->sendInLoop(msg.data(), msg.length()); std::lock_guard guard1(thisPtr->sendNumMutex_); @@ -1045,7 +1022,6 @@ void TcpConnectionImpl::send(const MsgBuffer &buffer) { } else { ++sendNum_; auto thisPtr = shared_from_this(); - loop_->queueInLoop([thisPtr, buffer]() { thisPtr->sendInLoop(buffer.peek(), buffer.readableBytes()); std::lock_guard guard1(thisPtr->sendNumMutex_); @@ -1056,7 +1032,6 @@ void TcpConnectionImpl::send(const MsgBuffer &buffer) { auto thisPtr = shared_from_this(); std::lock_guard guard(sendNumMutex_); ++sendNum_; - loop_->queueInLoop([thisPtr, buffer]() { thisPtr->sendInLoop(buffer.peek(), buffer.readableBytes()); std::lock_guard guard1(thisPtr->sendNumMutex_); @@ -1066,28 +1041,23 @@ void TcpConnectionImpl::send(const MsgBuffer &buffer) { } void TcpConnectionImpl::send(MsgBuffer &&buffer) { - if (loop_->isInLoopThread()) { std::lock_guard guard(sendNumMutex_); - if (sendNum_ == 0) { sendInLoop(buffer.peek(), buffer.readableBytes()); } else { ++sendNum_; auto thisPtr = shared_from_this(); - loop_->queueInLoop([thisPtr, buffer = std::move(buffer)]() { thisPtr->sendInLoop(buffer.peek(), buffer.readableBytes()); std::lock_guard guard1(thisPtr->sendNumMutex_); --thisPtr->sendNum_; }); } - } else { auto thisPtr = shared_from_this(); std::lock_guard guard(sendNumMutex_); ++sendNum_; - loop_->queueInLoop([thisPtr, buffer = std::move(buffer)]() { thisPtr->sendInLoop(buffer.peek(), buffer.readableBytes()); std::lock_guard guard1(thisPtr->sendNumMutex_); @@ -1095,11 +1065,10 @@ void TcpConnectionImpl::send(MsgBuffer &&buffer) { }); } } - -void TcpConnectionImpl::sendFile(const char *fileName, size_t offset, size_t length) { - +void TcpConnectionImpl::sendFile(const char *fileName, + size_t offset, + size_t length) { assert(fileName); - #ifndef _WIN32 int fd = open(fileName, O_RDONLY); @@ -1115,7 +1084,6 @@ void TcpConnectionImpl::sendFile(const char *fileName, size_t offset, size_t len close(fd); return; } - length = filestat.st_size; } @@ -1141,7 +1109,6 @@ void TcpConnectionImpl::sendFile(const char *fileName, size_t offset, size_t len fclose(fp); return; } - length = filestat.st_size; } @@ -1156,7 +1123,6 @@ void TcpConnectionImpl::sendFile(FILE *fp, size_t offset, size_t length) #endif { assert(length > 0); - #ifndef _WIN32 assert(sfd >= 0); BufferNodePtr node(new BufferNode); @@ -1166,25 +1132,19 @@ void TcpConnectionImpl::sendFile(FILE *fp, size_t offset, size_t length) BufferNodePtr node(new BufferNode); node->sendFp_ = fp; #endif - node->offset_ = static_cast(offset); node->fileBytesToSend_ = length; - if (loop_->isInLoopThread()) { std::lock_guard guard(sendNumMutex_); if (sendNum_ == 0) { - writeBufferList_.push_back(node); if (writeBufferList_.size() == 1) { sendFileInLoop(writeBufferList_.front()); return; } - } else { - ++sendNum_; auto thisPtr = shared_from_this(); - loop_->queueInLoop([thisPtr, node]() { thisPtr->writeBufferList_.push_back(node); { @@ -1198,11 +1158,9 @@ void TcpConnectionImpl::sendFile(FILE *fp, size_t offset, size_t length) }); } } else { - auto thisPtr = shared_from_this(); std::lock_guard guard(sendNumMutex_); ++sendNum_; - loop_->queueInLoop([thisPtr, node]() { LOG_TRACE << "Push sendfile to list"; thisPtr->writeBufferList_.push_back(node); @@ -1220,56 +1178,49 @@ void TcpConnectionImpl::sendFile(FILE *fp, size_t offset, size_t length) } void TcpConnectionImpl::sendFileInLoop(const BufferNodePtr &filePtr) { - loop_->assertInLoopThread(); - #ifndef _WIN32 assert(filePtr->sendFd_ >= 0); #else assert(filePtr->sendFp_); #endif - #ifdef __linux__ if (!isEncrypted_) { - auto bytesSent = sendfile(socketPtr_->fd(), filePtr->sendFd_, &filePtr->offset_, filePtr->fileBytesToSend_); - + auto bytesSent = sendfile(socketPtr_->fd(), + filePtr->sendFd_, + &filePtr->offset_, + filePtr->fileBytesToSend_); if (bytesSent < 0) { if (errno != EAGAIN) { LOG_SYSERR << "TcpConnectionImpl::sendFileInLoop"; - if (ioChannelPtr_->isWriting()) { + if (ioChannelPtr_->isWriting()) ioChannelPtr_->disableWriting(); - } } return; } - if (bytesSent < filePtr->fileBytesToSend_) { if (bytesSent == 0) { LOG_SYSERR << "TcpConnectionImpl::sendFileInLoop"; return; } } - LOG_TRACE << "sendfile() " << bytesSent << " bytes sent"; filePtr->fileBytesToSend_ -= bytesSent; if (!ioChannelPtr_->isWriting()) { ioChannelPtr_->enableWriting(); } - return; } #endif - #ifndef _WIN32 lseek(filePtr->sendFd_, filePtr->offset_, SEEK_SET); - if (!fileBufferPtr_) { fileBufferPtr_ = std::make_unique >(16 * 1024); } - while (filePtr->fileBytesToSend_ > 0) { - auto n = read(filePtr->sendFd_, &(*fileBufferPtr_)[0], fileBufferPtr_->size()); - + auto n = read(filePtr->sendFd_, + &(*fileBufferPtr_)[0], + fileBufferPtr_->size()); #else _fseeki64(filePtr->sendFp_, filePtr->offset_, SEEK_SET); if (!fileBufferPtr_) { @@ -1281,7 +1232,6 @@ void TcpConnectionImpl::sendFileInLoop(const BufferNodePtr &filePtr) { fileBufferPtr_->size(), filePtr->sendFp_); #endif - if (n > 0) { auto nSend = writeInLoop(&(*fileBufferPtr_)[0], n); if (nSend >= 0) { @@ -1307,11 +1257,9 @@ void TcpConnectionImpl::sendFileInLoop(const BufferNodePtr &filePtr) { LOG_DEBUG << "EPIPE or ECONNRESET, erron=" << errno; return; } - LOG_SYSERR << "Unexpected error(" << errno << ")"; return; } - break; } } @@ -1321,18 +1269,15 @@ void TcpConnectionImpl::sendFileInLoop(const BufferNodePtr &filePtr) { ioChannelPtr_->disableWriting(); return; } - if (n == 0) { LOG_SYSERR << "read"; return; } } - if (!ioChannelPtr_->isWriting()) { ioChannelPtr_->enableWriting(); } } - #ifndef _WIN32 ssize_t TcpConnectionImpl::writeInLoop(const void *buffer, size_t length) #else @@ -1362,37 +1307,33 @@ ssize_t TcpConnectionImpl::writeInLoop(const char *buffer, size_t length) LOG_WARN << "SSL is not connected,give up sending"; return -1; } - // send directly size_t sendTotalLen = 0; while (sendTotalLen < length) { - auto len = length - sendTotalLen; - if (len > sslEncryptionPtr_->sendBufferPtr_->size()) { len = sslEncryptionPtr_->sendBufferPtr_->size(); } - - memcpy(sslEncryptionPtr_->sendBufferPtr_->data(), static_cast(buffer) + sendTotalLen, len); - + memcpy(sslEncryptionPtr_->sendBufferPtr_->data(), + static_cast(buffer) + sendTotalLen, + len); ERR_clear_error(); - - auto sendLen = SSL_write(sslEncryptionPtr_->sslPtr_->get(), sslEncryptionPtr_->sendBufferPtr_->data(), static_cast(len)); - + auto sendLen = SSL_write(sslEncryptionPtr_->sslPtr_->get(), + sslEncryptionPtr_->sendBufferPtr_->data(), + static_cast(len)); if (sendLen <= 0) { - int sslerr = SSL_get_error(sslEncryptionPtr_->sslPtr_->get(), sendLen); - - if (sslerr != SSL_ERROR_WANT_WRITE && sslerr != SSL_ERROR_WANT_READ) { + int sslerr = + SSL_get_error(sslEncryptionPtr_->sslPtr_->get(), sendLen); + if (sslerr != SSL_ERROR_WANT_WRITE && + sslerr != SSL_ERROR_WANT_READ) { // LOG_ERROR << "ssl write error:" << sslerr; forceClose(); return -1; } - return sendTotalLen; } sendTotalLen += sendLen; } - return sendTotalLen; } #endif @@ -1400,45 +1341,52 @@ ssize_t TcpConnectionImpl::writeInLoop(const char *buffer, size_t length) #ifdef USE_OPENSSL -TcpConnectionImpl::TcpConnectionImpl(EventLoop *loop, int socketfd, const InetAddress &localAddr, const InetAddress &peerAddr, const std::shared_ptr &ctxPtr, bool isServer, bool validateCert, const std::string &hostname) : +TcpConnectionImpl::TcpConnectionImpl(EventLoop *loop, + int socketfd, + const InetAddress &localAddr, + const InetAddress &peerAddr, + const std::shared_ptr &ctxPtr, + bool isServer, + bool validateCert, + const std::string &hostname) : isEncrypted_(true), loop_(loop), ioChannelPtr_(new Channel(loop, socketfd)), socketPtr_(new Socket(socketfd)), localAddr_(localAddr), peerAddr_(peerAddr) { - - LOG_TRACE << "new connection:" << peerAddr.toIpPort() << "->" << localAddr.toIpPort(); - - ioChannelPtr_->setReadCallback(std::bind(&TcpConnectionImpl::readCallback, this)); - ioChannelPtr_->setWriteCallback(std::bind(&TcpConnectionImpl::writeCallback, this)); - ioChannelPtr_->setCloseCallback(std::bind(&TcpConnectionImpl::handleClose, this)); - ioChannelPtr_->setErrorCallback(std::bind(&TcpConnectionImpl::handleError, this)); - + LOG_TRACE << "new connection:" << peerAddr.toIpPort() << "->" + << localAddr.toIpPort(); + ioChannelPtr_->setReadCallback( + std::bind(&TcpConnectionImpl::readCallback, this)); + ioChannelPtr_->setWriteCallback( + std::bind(&TcpConnectionImpl::writeCallback, this)); + ioChannelPtr_->setCloseCallback( + std::bind(&TcpConnectionImpl::handleClose, this)); + ioChannelPtr_->setErrorCallback( + std::bind(&TcpConnectionImpl::handleError, this)); socketPtr_->setKeepAlive(true); name_ = localAddr.toIpPort() + "--" + peerAddr.toIpPort(); sslEncryptionPtr_ = std::make_unique(); sslEncryptionPtr_->sslPtr_ = std::make_unique(ctxPtr->get()); sslEncryptionPtr_->isServer_ = isServer; validateCert_ = validateCert; - - if (isServer == false) { - SSL_set_verify(sslEncryptionPtr_->sslPtr_->get(), SSL_VERIFY_NONE, nullptr); - } - + if (isServer == false) + SSL_set_verify(sslEncryptionPtr_->sslPtr_->get(), + SSL_VERIFY_NONE, + nullptr); if (!isServer && !hostname.empty()) { - SSL_set_tlsext_host_name(sslEncryptionPtr_->sslPtr_->get(), hostname.data()); + SSL_set_tlsext_host_name(sslEncryptionPtr_->sslPtr_->get(), + hostname.data()); sslEncryptionPtr_->hostname_ = hostname; } - assert(sslEncryptionPtr_->sslPtr_); auto r = SSL_set_fd(sslEncryptionPtr_->sslPtr_->get(), socketfd); - (void)r; assert(r); - isEncrypted_ = true; - sslEncryptionPtr_->sendBufferPtr_ = std::make_unique >(); + sslEncryptionPtr_->sendBufferPtr_ = + std::make_unique >(); } bool TcpConnectionImpl::validatePeerCertificate() { @@ -1448,7 +1396,6 @@ bool TcpConnectionImpl::validatePeerCertificate() { SSL *ssl = sslEncryptionPtr_->sslPtr_->get(); auto result = SSL_get_verify_result(ssl); - if (result != X509_V_OK) { LOG_DEBUG << "cert error code: " << result; LOG_ERROR << "Server certificate is not valid"; @@ -1456,13 +1403,14 @@ bool TcpConnectionImpl::validatePeerCertificate() { } X509 *cert = SSL_get_peer_certificate(ssl); - if (cert == nullptr) { LOG_ERROR << "Unable to obtain peer certificate"; return false; } - bool domainIsValid = internal::verifyCommonName(cert, sslEncryptionPtr_->hostname_) || internal::verifyAltName(cert, sslEncryptionPtr_->hostname_); + bool domainIsValid = + internal::verifyCommonName(cert, sslEncryptionPtr_->hostname_) || + internal::verifyAltName(cert, sslEncryptionPtr_->hostname_); X509_free(cert); if (domainIsValid) { @@ -1478,12 +1426,10 @@ void TcpConnectionImpl::doHandshaking() { int r = SSL_do_handshake(sslEncryptionPtr_->sslPtr_->get()); LOG_TRACE << "hand shaking: " << r; - if (r == 1) { // Clients don't commonly have certificates. Let's not validate // that if (validateCert_ && sslEncryptionPtr_->isServer_ == false) { - if (validatePeerCertificate() == false) { LOG_ERROR << "SSL certificate validation failed."; ioChannelPtr_->disableReading(); @@ -1495,9 +1441,7 @@ void TcpConnectionImpl::doHandshaking() { return; } } - sslEncryptionPtr_->statusOfSSL_ = SSLStatus::Connected; - if (sslEncryptionPtr_->isUpgrade_) { sslEncryptionPtr_->upgradeCallback_(); } else { @@ -1505,33 +1449,25 @@ void TcpConnectionImpl::doHandshaking() { } return; } - int err = SSL_get_error(sslEncryptionPtr_->sslPtr_->get(), r); LOG_TRACE << "hand shaking: " << err; - if (err == SSL_ERROR_WANT_WRITE) { // SSL want writable; - if (!ioChannelPtr_->isWriting()) { + if (!ioChannelPtr_->isWriting()) ioChannelPtr_->enableWriting(); - } // ioChannelPtr_->disableReading(); } else if (err == SSL_ERROR_WANT_READ) { // SSL want readable; - if (!ioChannelPtr_->isReading()) { + if (!ioChannelPtr_->isReading()) ioChannelPtr_->enableReading(); - } - - if (ioChannelPtr_->isWriting()) { + if (ioChannelPtr_->isWriting()) ioChannelPtr_->disableWriting(); - } } else { // ERR_print_errors(err); LOG_TRACE << "SSL handshake err: " << err; ioChannelPtr_->disableReading(); - sslEncryptionPtr_->statusOfSSL_ = SSLStatus::DisConnected; if (sslErrorCallback_) { sslErrorCallback_(SSLError::kSSLHandshakeError); } - forceClose(); } } diff --git a/web_backends/drogon/trantor/net/inner/TcpConnectionImpl.h b/web_backends/drogon/trantor/net/inner/TcpConnectionImpl.h new file mode 100644 index 0000000..cad3dfa --- /dev/null +++ b/web_backends/drogon/trantor/net/inner/TcpConnectionImpl.h @@ -0,0 +1,344 @@ +/** + * + * @file TcpConnectionImpl.h + * @author An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#pragma once + +#include +#include +#include +#include +#ifndef _WIN32 +#include +#endif +#include +#include + +namespace trantor +{ +#ifdef USE_OPENSSL +enum class SSLStatus +{ + Handshaking, + Connecting, + Connected, + DisConnecting, + DisConnected +}; +class SSLContext; +class SSLConn; + +std::shared_ptr newSSLContext( + bool useOldTLS, + bool validateCert, + const std::vector> &sslConfCmds); +std::shared_ptr newSSLServerContext( + const std::string &certPath, + const std::string &keyPath, + bool useOldTLS, + const std::vector> &sslConfCmds); +// void initServerSSLContext(const std::shared_ptr &ctx, +// const std::string &certPath, +// const std::string &keyPath); +#endif +class Channel; +class Socket; +class TcpServer; +void removeConnection(EventLoop *loop, const TcpConnectionPtr &conn); +class TcpConnectionImpl : public TcpConnection, + public NonCopyable, + public std::enable_shared_from_this +{ + friend class TcpServer; + friend class TcpClient; + friend void trantor::removeConnection(EventLoop *loop, + const TcpConnectionPtr &conn); + + public: + class KickoffEntry + { + public: + explicit KickoffEntry(const std::weak_ptr &conn) + : conn_(conn) + { + } + void reset() + { + conn_.reset(); + } + ~KickoffEntry() + { + auto conn = conn_.lock(); + if (conn) + { + conn->forceClose(); + } + } + + private: + std::weak_ptr conn_; + }; + + TcpConnectionImpl(EventLoop *loop, + int socketfd, + const InetAddress &localAddr, + const InetAddress &peerAddr); +#ifdef USE_OPENSSL + TcpConnectionImpl(EventLoop *loop, + int socketfd, + const InetAddress &localAddr, + const InetAddress &peerAddr, + const std::shared_ptr &ctxPtr, + bool isServer = true, + bool validateCert = true, + const std::string &hostname = ""); +#endif + virtual ~TcpConnectionImpl(); + virtual void send(const char *msg, size_t len) override; + virtual void send(const void *msg, size_t len) override; + virtual void send(const std::string &msg) override; + virtual void send(std::string &&msg) override; + virtual void send(const MsgBuffer &buffer) override; + virtual void send(MsgBuffer &&buffer) override; + virtual void send(const std::shared_ptr &msgPtr) override; + virtual void send(const std::shared_ptr &msgPtr) override; + virtual void sendFile(const char *fileName, + size_t offset = 0, + size_t length = 0) override; + + virtual const InetAddress &localAddr() const override + { + return localAddr_; + } + virtual const InetAddress &peerAddr() const override + { + return peerAddr_; + } + + virtual bool connected() const override + { + return status_ == ConnStatus::Connected; + } + virtual bool disconnected() const override + { + return status_ == ConnStatus::Disconnected; + } + + // virtual MsgBuffer* getSendBuffer() override{ return &writeBuffer_;} + virtual MsgBuffer *getRecvBuffer() override + { + return &readBuffer_; + } + // set callbacks + virtual void setHighWaterMarkCallback(const HighWaterMarkCallback &cb, + size_t markLen) override + { + highWaterMarkCallback_ = cb; + highWaterMarkLen_ = markLen; + } + + virtual void keepAlive() override + { + idleTimeout_ = 0; + auto entry = kickoffEntry_.lock(); + if (entry) + { + entry->reset(); + } + } + virtual bool isKeepAlive() override + { + return idleTimeout_ == 0; + } + virtual void setTcpNoDelay(bool on) override; + virtual void shutdown() override; + virtual void forceClose() override; + virtual EventLoop *getLoop() override + { + return loop_; + } + + virtual size_t bytesSent() const override + { + return bytesSent_; + } + virtual size_t bytesReceived() const override + { + return bytesReceived_; + } + virtual void startClientEncryption( + std::function callback, + bool useOldTLS = false, + bool validateCert = true, + std::string hostname = "", + const std::vector> &sslConfCmds = + {}) override; + virtual void startServerEncryption(const std::shared_ptr &ctx, + std::function callback) override; + virtual bool isSSLConnection() const override + { + return isEncrypted_; + } + + private: + /// Internal use only. + + std::weak_ptr kickoffEntry_; + std::weak_ptr timingWheelWeakPtr_; + size_t idleTimeout_{0}; + Date lastTimingWheelUpdateTime_; + + void enableKickingOff(size_t timeout, + const std::shared_ptr &timingWheel) + { + assert(timingWheel); + assert(timingWheel->getLoop() == loop_); + assert(timeout > 0); + auto entry = std::make_shared(shared_from_this()); + kickoffEntry_ = entry; + timingWheelWeakPtr_ = timingWheel; + idleTimeout_ = timeout; + timingWheel->insertEntry(timeout, entry); + } + void extendLife(); +#ifndef _WIN32 + void sendFile(int sfd, size_t offset = 0, size_t length = 0); +#else + void sendFile(FILE *fp, size_t offset = 0, size_t length = 0); +#endif + void setRecvMsgCallback(const RecvMessageCallback &cb) + { + recvMsgCallback_ = cb; + } + void setConnectionCallback(const ConnectionCallback &cb) + { + connectionCallback_ = cb; + } + void setWriteCompleteCallback(const WriteCompleteCallback &cb) + { + writeCompleteCallback_ = cb; + } + void setCloseCallback(const CloseCallback &cb) + { + closeCallback_ = cb; + } + void setSSLErrorCallback(const SSLErrorCallback &cb) + { + sslErrorCallback_ = cb; + } + + void connectDestroyed(); + virtual void connectEstablished(); + + protected: + struct BufferNode + { +#ifndef _WIN32 + int sendFd_{-1}; + off_t offset_; +#else + FILE *sendFp_{nullptr}; + long long offset_; +#endif + ssize_t fileBytesToSend_; + std::shared_ptr msgBuffer_; + ~BufferNode() + { +#ifndef _WIN32 + if (sendFd_ >= 0) + close(sendFd_); +#else + if (sendFp_) + fclose(sendFp_); +#endif + } + }; + using BufferNodePtr = std::shared_ptr; + enum class ConnStatus + { + Disconnected, + Connecting, + Connected, + Disconnecting + }; + bool isEncrypted_{false}; + EventLoop *loop_; + std::unique_ptr ioChannelPtr_; + std::unique_ptr socketPtr_; + MsgBuffer readBuffer_; + std::list writeBufferList_; + void readCallback(); + void writeCallback(); + InetAddress localAddr_, peerAddr_; + ConnStatus status_{ConnStatus::Connecting}; + // callbacks + RecvMessageCallback recvMsgCallback_; + ConnectionCallback connectionCallback_; + CloseCallback closeCallback_; + WriteCompleteCallback writeCompleteCallback_; + HighWaterMarkCallback highWaterMarkCallback_; + SSLErrorCallback sslErrorCallback_; + void handleClose(); + void handleError(); + // virtual void sendInLoop(const std::string &msg); + + void sendFileInLoop(const BufferNodePtr &file); +#ifndef _WIN32 + void sendInLoop(const void *buffer, size_t length); + ssize_t writeInLoop(const void *buffer, size_t length); +#else + void sendInLoop(const char *buffer, size_t length); + ssize_t writeInLoop(const char *buffer, size_t length); +#endif + size_t highWaterMarkLen_; + std::string name_; + + uint64_t sendNum_{0}; + std::mutex sendNumMutex_; + + size_t bytesSent_{0}; + size_t bytesReceived_{0}; + + std::unique_ptr> fileBufferPtr_; + +#ifdef USE_OPENSSL + private: + void doHandshaking(); + bool validatePeerCertificate(); + struct SSLEncryption + { + SSLStatus statusOfSSL_ = SSLStatus::Handshaking; + // OpenSSL + std::shared_ptr sslCtxPtr_; + std::unique_ptr sslPtr_; + std::unique_ptr> sendBufferPtr_; + bool isServer_{false}; + bool isUpgrade_{false}; + std::function upgradeCallback_; + std::string hostname_; + }; + std::unique_ptr sslEncryptionPtr_; + void startClientEncryptionInLoop( + std::function &&callback, + bool useOldTLS, + bool validateCert, + const std::string &hostname, + const std::vector> &sslConfCmds); + void startServerEncryptionInLoop(const std::shared_ptr &ctx, + std::function &&callback); +#endif +}; + +using TcpConnectionImplPtr = std::shared_ptr; + +} // namespace trantor diff --git a/web_backends/drogon/trantor/net/inner/Timer.cc b/web_backends/drogon/trantor/net/inner/Timer.cc new file mode 100644 index 0000000..d6b8261 --- /dev/null +++ b/web_backends/drogon/trantor/net/inner/Timer.cc @@ -0,0 +1,55 @@ +/** + * + * Timer.cc + * An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#include "Timer.h" +#include +#include + +namespace trantor { +std::atomic Timer::timersCreated_ = ATOMIC_VAR_INIT(InvalidTimerId); +Timer::Timer(const TimerCallback &cb, + const TimePoint &when, + const TimeInterval &interval) : + callback_(cb), + when_(when), + interval_(interval), + repeat_(interval.count() > 0), + id_(++timersCreated_) { +} +Timer::Timer(TimerCallback &&cb, + const TimePoint &when, + const TimeInterval &interval) : + callback_(std::move(cb)), + when_(when), + interval_(interval), + repeat_(interval.count() > 0), + id_(++timersCreated_) { + // LOG_TRACE<<"Timer move contrustor"; +} +void Timer::run() const { + callback_(); +} +void Timer::restart(const TimePoint &now) { + if (repeat_) { + when_ = now + interval_; + } else + when_ = std::chrono::steady_clock::now(); +} +bool Timer::operator<(const Timer &t) const { + return when_ < t.when_; +} +bool Timer::operator>(const Timer &t) const { + return when_ > t.when_; +} +} // namespace trantor diff --git a/web_backends/drogon/trantor/net/inner/Timer.h b/web_backends/drogon/trantor/net/inner/Timer.h new file mode 100644 index 0000000..17c6d33 --- /dev/null +++ b/web_backends/drogon/trantor/net/inner/Timer.h @@ -0,0 +1,68 @@ +/** + * + * Timer.h + * An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace trantor +{ +using TimerId = uint64_t; +using TimePoint = std::chrono::steady_clock::time_point; +using TimeInterval = std::chrono::microseconds; +class Timer : public NonCopyable +{ + public: + Timer(const TimerCallback &cb, + const TimePoint &when, + const TimeInterval &interval); + Timer(TimerCallback &&cb, + const TimePoint &when, + const TimeInterval &interval); + ~Timer() + { + // std::cout<<"Timer unconstract!"<(const Timer &t) const; + const TimePoint &when() const + { + return when_; + } + bool isRepeat() + { + return repeat_; + } + TimerId id() + { + return id_; + } + + private: + TimerCallback callback_; + TimePoint when_; + const TimeInterval interval_; + const bool repeat_; + const TimerId id_; + static std::atomic timersCreated_; +}; + +} // namespace trantor diff --git a/core/loops/timer_queue.cpp b/web_backends/drogon/trantor/net/inner/TimerQueue.cc similarity index 78% rename from core/loops/timer_queue.cpp rename to web_backends/drogon/trantor/net/inner/TimerQueue.cc index 76f316c..217fe0d 100644 --- a/core/loops/timer_queue.cpp +++ b/web_backends/drogon/trantor/net/inner/TimerQueue.cc @@ -1,37 +1,21 @@ +/** + * + * @file TimerQueue.cc + * @author An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ -// This file is originally from Trantor - TimerQueue.cc +#include -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "event_loop.h" - -#include "core/net/channel.h" -#include "timer_queue.h" +#include "Channel.h" +#include "TimerQueue.h" #ifdef __linux__ #include #endif @@ -41,6 +25,7 @@ #include #endif +using namespace trantor; #ifdef __linux__ static int createTimerfd() { int timerfd = ::timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); diff --git a/web_backends/drogon/trantor/net/inner/TimerQueue.h b/web_backends/drogon/trantor/net/inner/TimerQueue.h new file mode 100644 index 0000000..6903fb4 --- /dev/null +++ b/web_backends/drogon/trantor/net/inner/TimerQueue.h @@ -0,0 +1,76 @@ +/** + * + * TimerQueue.h + * An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#pragma once + +#include +#include +#include "Timer.h" +#include +#include +#include +#include +namespace trantor +{ +// class Timer; +class EventLoop; +class Channel; +using TimerPtr = std::shared_ptr; +struct TimerPtrComparer +{ + bool operator()(const TimerPtr &x, const TimerPtr &y) const + { + return *x > *y; + } +}; + +class TimerQueue : NonCopyable +{ + public: + explicit TimerQueue(EventLoop *loop); + ~TimerQueue(); + TimerId addTimer(const TimerCallback &cb, + const TimePoint &when, + const TimeInterval &interval); + TimerId addTimer(TimerCallback &&cb, + const TimePoint &when, + const TimeInterval &interval); + void addTimerInLoop(const TimerPtr &timer); + void invalidateTimer(TimerId id); +#ifdef __linux__ + void reset(); +#else + int64_t getTimeout() const; + void processTimers(); +#endif + protected: + EventLoop *loop_; +#ifdef __linux__ + int timerfd_; + std::shared_ptr timerfdChannelPtr_; + void handleRead(); +#endif + std::priority_queue, TimerPtrComparer> + timers_; + + bool callingExpiredTimers_; + bool insert(const TimerPtr &timePtr); + std::vector getExpired(); + void reset(const std::vector &expired, const TimePoint &now); + std::vector getExpired(const TimePoint &now); + + private: + std::unordered_set timerIdSet_; +}; +} // namespace trantor diff --git a/core/polling/poller/epoll_poller.cpp b/web_backends/drogon/trantor/net/inner/poller/EpollPoller.cc similarity index 74% rename from core/polling/poller/epoll_poller.cpp rename to web_backends/drogon/trantor/net/inner/poller/EpollPoller.cc index da31323..2d9b4d5 100644 --- a/core/polling/poller/epoll_poller.cpp +++ b/web_backends/drogon/trantor/net/inner/poller/EpollPoller.cc @@ -1,37 +1,20 @@ +/** + * + * EpollPoller.cc + * An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ -// This file is originally from Trantor - EpollPoller.cc - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "epoll_poller.h" -#include "core/log/logger.h" -#include "core/net/channel.h" - +#include "EpollPoller.h" +#include "Channel.h" +#include #ifdef __linux__ #include #include @@ -47,7 +30,7 @@ #include #define EPOLL_CLOEXEC _O_NOINHERIT #endif - +namespace trantor { #if defined __linux__ || defined _WIN32 #if defined __linux__ @@ -218,3 +201,4 @@ void EpollPoller::removeChannel(Channel *) { } #endif +} // namespace trantor diff --git a/web_backends/drogon/trantor/net/inner/poller/EpollPoller.h b/web_backends/drogon/trantor/net/inner/poller/EpollPoller.h new file mode 100644 index 0000000..be04a4a --- /dev/null +++ b/web_backends/drogon/trantor/net/inner/poller/EpollPoller.h @@ -0,0 +1,64 @@ +/** + * + * EpollPoller.h + * An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#pragma once + +#include "../Poller.h" +#include +#include + +#if defined __linux__ || defined _WIN32 +#include +#include +using EventList = std::vector; +#endif +namespace trantor +{ +class Channel; + +class EpollPoller : public Poller +{ + public: + explicit EpollPoller(EventLoop *loop); + virtual ~EpollPoller(); + virtual void poll(int timeoutMs, ChannelList *activeChannels) override; + virtual void updateChannel(Channel *channel) override; + virtual void removeChannel(Channel *channel) override; +#ifdef _WIN32 + virtual void postEvent(uint64_t event) override; + virtual void setEventCallback(const EventCallback &cb) override + { + eventCallback_ = cb; + } +#endif + + private: +#if defined __linux__ || defined _WIN32 + static const int kInitEventListSize = 16; +#ifdef _WIN32 + void *epollfd_; + EventCallback eventCallback_{[](uint64_t event) {}}; +#else + int epollfd_; +#endif + EventList events_; + void update(int operation, Channel *channel); +#ifndef NDEBUG + using ChannelMap = std::map; + ChannelMap channels_; +#endif + void fillActiveChannels(int numEvents, ChannelList *activeChannels) const; +#endif +}; +} // namespace trantor diff --git a/core/polling/poller/kqueue.cpp b/web_backends/drogon/trantor/net/inner/poller/KQueue.cc similarity index 73% rename from core/polling/poller/kqueue.cpp rename to web_backends/drogon/trantor/net/inner/poller/KQueue.cc index 1d8dd4d..8481455 100644 --- a/core/polling/poller/kqueue.cpp +++ b/web_backends/drogon/trantor/net/inner/poller/KQueue.cc @@ -1,46 +1,14 @@ - -// This file is originally from Trantor - KQueue.cc - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -#include "kqueue.h" - -#include "core/net/channel.h" +#include "KQueue.h" +#include "Channel.h" #ifdef USE_KQUEUE -#include "core/log/logger.h" #include #include #include #include +#include #include #endif - +namespace trantor { #ifdef USE_KQUEUE namespace { const int kNew = -1; @@ -231,3 +199,4 @@ void KQueue::removeChannel(Channel *) { void KQueue::resetAfterFork() { } #endif +} // namespace trantor diff --git a/web_backends/drogon/trantor/net/inner/poller/KQueue.h b/web_backends/drogon/trantor/net/inner/poller/KQueue.h new file mode 100644 index 0000000..290082d --- /dev/null +++ b/web_backends/drogon/trantor/net/inner/poller/KQueue.h @@ -0,0 +1,55 @@ +/** + * + * KQueue.h + * An Tao + * + * Copyright 2018, An Tao. All rights reserved. + * https://github.com/an-tao/trantor + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * Trantor + * + */ + +#pragma once +#include "../Poller.h" +#include +#include + +#if (defined(__unix__) && !defined(__linux__)) || \ + (defined(__APPLE__) && defined(__MACH__)) +#define USE_KQUEUE +#include +#include +#include +using EventList = std::vector; +#endif +namespace trantor +{ +class Channel; + +class KQueue : public Poller +{ + public: + explicit KQueue(EventLoop *loop); + virtual ~KQueue(); + virtual void poll(int timeoutMs, ChannelList *activeChannels) override; + virtual void updateChannel(Channel *channel) override; + virtual void removeChannel(Channel *channel) override; + virtual void resetAfterFork() override; + + private: +#ifdef USE_KQUEUE + static const int kInitEventListSize = 16; + int kqfd_; + EventList events_; + using ChannelMap = std::unordered_map>; + ChannelMap channels_; + + void fillActiveChannels(int numEvents, ChannelList *activeChannels) const; + void update(Channel *channel); +#endif +}; + +} // namespace trantor \ No newline at end of file diff --git a/web_backends/drogon/trantor/tests/AsyncFileLoggerTest.cc b/web_backends/drogon/trantor/tests/AsyncFileLoggerTest.cc new file mode 100644 index 0000000..66c7219 --- /dev/null +++ b/web_backends/drogon/trantor/tests/AsyncFileLoggerTest.cc @@ -0,0 +1,45 @@ +#include +#include +#include +#include +int main() +{ + trantor::AsyncFileLogger asyncFileLogger; + asyncFileLogger.setFileName("async_test"); + asyncFileLogger.startLogging(); + trantor::Logger::setOutputFunction( + [&](const char *msg, const uint64_t len) { + asyncFileLogger.output(msg, len); + }, + [&]() { asyncFileLogger.flush(); }); + asyncFileLogger.setFileSizeLimit(100000000); + // LOG_DEBUG<<"debug log!"<<1; + // LOG_TRACE<<"trace log!"<<2; + // LOG_INFO<<"info log!"<<3; + // LOG_WARN<<"warning log!"<<4; + // if(1) + // LOG_ERROR<<"error log!"<<5; + // std::thread thread_([](){ + // LOG_FATAL<<"fatal log!"<<6; + // }); + // + // FILE *fp=fopen("/notexistfile","rb"); + // if(fp==NULL) + // { + // LOG_SYSERR<<"syserr log!"<<7; + // } + + int i = 0; + while (i < 1000000) + { + ++i; + if (i % 100 == 0) + { + LOG_ERROR << "this is the " << i << "th log"; + continue; + } + LOG_INFO << "this is the " << i << "th log"; + ++i; + LOG_DEBUG << "this is the " << i << "th log"; + } +} diff --git a/web_backends/drogon/trantor/tests/AsyncFileLoggerTest1.cc b/web_backends/drogon/trantor/tests/AsyncFileLoggerTest1.cc new file mode 100644 index 0000000..63c6916 --- /dev/null +++ b/web_backends/drogon/trantor/tests/AsyncFileLoggerTest1.cc @@ -0,0 +1,33 @@ +#include +#include +#include +#include +#include + +using namespace std::chrono_literals; +int main() +{ + trantor::AsyncFileLogger asyncFileLogger; + asyncFileLogger.setFileName("async_test"); + asyncFileLogger.startLogging(); + trantor::Logger::setOutputFunction( + [&](const char *msg, const uint64_t len) { + asyncFileLogger.output(msg, len); + }, + [&]() { asyncFileLogger.flush(); }); + asyncFileLogger.setFileSizeLimit(100000000); + int i = 0; + while (i < 1000000) + { + ++i; + if (i % 100 == 0) + { + LOG_ERROR << "this is the " << i << "th log"; + continue; + } + LOG_INFO << "this is the " << i << "th log"; + ++i; + LOG_DEBUG << "this is the " << i << "th log"; + std::this_thread::sleep_for(1s); + } +} diff --git a/web_backends/drogon/trantor/tests/CMakeLists.txt b/web_backends/drogon/trantor/tests/CMakeLists.txt new file mode 100644 index 0000000..180f556 --- /dev/null +++ b/web_backends/drogon/trantor/tests/CMakeLists.txt @@ -0,0 +1,51 @@ +add_executable(ssl_server_test SSLServerTest.cc) +add_executable(ssl_client_test SSLClientTest.cc) +add_executable(serial_task_queue_test1 SerialTaskQueueTest1.cc) +add_executable(serial_task_queue_test2 SerialTaskQueueTest2.cc) +add_executable(timer_test TimerTest.cc) +add_executable(timer_test1 TimerTest1.cc) +add_executable(run_in_loop_test1 RunInLoopTest1.cc) +add_executable(run_in_loop_test2 RunInLoopTest2.cc) +add_executable(logger_test LoggerTest.cc) +add_executable(async_file_logger_test AsyncFileLoggerTest.cc) +add_executable(tcp_server_test TcpServerTest.cc) +add_executable(concurrent_task_queue_test ConcurrentTaskQueueTest.cc) +add_executable(tcp_client_test TcpClientTest.cc) +add_executable(async_file_logger_test1 AsyncFileLoggerTest1.cc) +add_executable(sendfile_test SendfileTest.cc) +add_executable(timing_wheel_test TimingWheelTest.cc) +add_executable(kickoff_test KickoffTest.cc) +add_executable(dns_test DnsTest.cc) +add_executable(delayed_ssl_server_test DelayedSSLServerTest.cc) +add_executable(delayed_ssl_client_test DelayedSSLClientTest.cc) +add_executable(run_on_quit_test RunOnQuitTest.cc) +set(targets_list + ssl_server_test + ssl_client_test + serial_task_queue_test1 + serial_task_queue_test2 + timer_test + timer_test1 + run_in_loop_test1 + run_in_loop_test2 + logger_test + async_file_logger_test + tcp_server_test + concurrent_task_queue_test + tcp_client_test + async_file_logger_test1 + sendfile_test + timing_wheel_test + kickoff_test + dns_test + delayed_ssl_server_test + delayed_ssl_client_test + run_on_quit_test) + +set_property(TARGET ${targets_list} PROPERTY CXX_STANDARD 14) +set_property(TARGET ${targets_list} PROPERTY CXX_STANDARD_REQUIRED ON) +set_property(TARGET ${targets_list} PROPERTY CXX_EXTENSIONS OFF) + +foreach(T ${targets_list}) + target_link_libraries(${T} PRIVATE trantor) +endforeach() diff --git a/web_backends/drogon/trantor/tests/ConcurrentTaskQueueTest.cc b/web_backends/drogon/trantor/tests/ConcurrentTaskQueueTest.cc new file mode 100644 index 0000000..cd62795 --- /dev/null +++ b/web_backends/drogon/trantor/tests/ConcurrentTaskQueueTest.cc @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include +#include +#include +#include +using namespace std::chrono_literals; + +int main() +{ + trantor::ConcurrentTaskQueue queue(5, "concurrT"); + std::atomic_int sum; + sum = 0; + for (int i = 0; i < 4; ++i) + { + queue.runTaskInQueue([&sum]() { + LOG_DEBUG << "add sum"; + for (int i = 0; i < 10000; ++i) + { + ++sum; + } + }); + } + + queue.runTaskInQueue([&sum]() { + for (int i = 0; i < 20; ++i) + { + LOG_DEBUG << "sum=" << sum; + std::this_thread::sleep_for(100us); + } + }); + + getc(stdin); + LOG_DEBUG << "sum=" << sum; +} diff --git a/web_backends/drogon/trantor/tests/DelayedSSLClientTest.cc b/web_backends/drogon/trantor/tests/DelayedSSLClientTest.cc new file mode 100644 index 0000000..72c5530 --- /dev/null +++ b/web_backends/drogon/trantor/tests/DelayedSSLClientTest.cc @@ -0,0 +1,64 @@ +#include +#include +#include +#include +#include +#include +using namespace trantor; +#define USE_IPV6 0 +int main() +{ + trantor::Logger::setLogLevel(trantor::Logger::kTrace); + LOG_DEBUG << "TcpClient class test!"; + EventLoop loop; +#if USE_IPV6 + InetAddress serverAddr("::1", 8888, true); +#else + InetAddress serverAddr("127.0.0.1", 8888); +#endif + std::shared_ptr client[10]; + std::atomic_int connCount; + connCount = 10; + for (int i = 0; i < 10; ++i) + { + client[i] = std::make_shared(&loop, + serverAddr, + "tcpclienttest"); + client[i]->setConnectionCallback( + [i, &loop, &connCount](const TcpConnectionPtr &conn) { + if (conn->connected()) + { + } + else + { + LOG_DEBUG << i << " disconnected"; + --connCount; + if (connCount == 0) + loop.quit(); + } + }); + client[i]->setMessageCallback( + [](const TcpConnectionPtr &conn, MsgBuffer *buf) { + auto msg = std::string(buf->peek(), buf->readableBytes()); + + LOG_INFO << msg; + if (msg == "hello") + { + buf->retrieveAll(); + conn->startClientEncryption( + [conn]() { + LOG_INFO << "SSL established"; + conn->send("Hello"); + }, + false, + false); + } + if (conn->isSSLConnection()) + { + buf->retrieveAll(); + } + }); + client[i]->connect(); + } + loop.loop(); +} diff --git a/web_backends/drogon/trantor/tests/DelayedSSLServerTest.cc b/web_backends/drogon/trantor/tests/DelayedSSLServerTest.cc new file mode 100644 index 0000000..466b7ad --- /dev/null +++ b/web_backends/drogon/trantor/tests/DelayedSSLServerTest.cc @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include +using namespace trantor; +#define USE_IPV6 0 +int main() +{ + LOG_DEBUG << "test start"; + Logger::setLogLevel(Logger::kTrace); + EventLoopThread loopThread; + loopThread.run(); +#if USE_IPV6 + InetAddress addr(8888, true, true); +#else + InetAddress addr(8888); +#endif + TcpServer server(loopThread.getLoop(), addr, "test"); + auto ctx = newSSLServerContext("server.pem", "server.pem", {}); + LOG_INFO << "start"; + server.setRecvMessageCallback( + [](const TcpConnectionPtr &connectionPtr, MsgBuffer *buffer) { + LOG_DEBUG << std::string{buffer->peek(), buffer->readableBytes()}; + connectionPtr->send(*buffer); + buffer->retrieveAll(); + connectionPtr->shutdown(); + }); + server.setConnectionCallback([ctx](const TcpConnectionPtr &connPtr) { + if (connPtr->connected()) + { + LOG_DEBUG << "New connection"; + connPtr->send("hello"); + connPtr->startServerEncryption(ctx, [] { + LOG_INFO << "SSL established"; + }); + } + else if (connPtr->disconnected()) + { + LOG_DEBUG << "connection disconnected"; + } + }); + server.setIoLoopNum(3); + server.start(); + loopThread.wait(); +} diff --git a/web_backends/drogon/trantor/tests/DnsTest.cc b/web_backends/drogon/trantor/tests/DnsTest.cc new file mode 100644 index 0000000..1a71f53 --- /dev/null +++ b/web_backends/drogon/trantor/tests/DnsTest.cc @@ -0,0 +1,48 @@ +#include +#include +void dns(const std::shared_ptr &resolver) +{ + auto now = trantor::Date::now(); + resolver->resolve("www.baidu.com", [now](const trantor::InetAddress &addr) { + auto interval = trantor::Date::now().microSecondsSinceEpoch() - + now.microSecondsSinceEpoch(); + std::cout << "baidu:" << addr.toIp() << " " << interval / 1000 << "ms" + << std::endl; + }); + resolver->resolve("www.google.com", + [now](const trantor::InetAddress &addr) { + auto interval = + trantor::Date::now().microSecondsSinceEpoch() - + now.microSecondsSinceEpoch(); + std::cout << "google:" << addr.toIp() << " " + << interval / 1000 << "ms" << std::endl; + }); + resolver->resolve("www.sina.com", [now](const trantor::InetAddress &addr) { + auto interval = trantor::Date::now().microSecondsSinceEpoch() - + now.microSecondsSinceEpoch(); + std::cout << "sina:" << addr.toIp() << " " << interval / 1000 << "ms" + << std::endl; + }); + resolver->resolve("www.xjfisfjaskfeiakdjfg.com", + [now](const trantor::InetAddress &addr) { + auto interval = + trantor::Date::now().microSecondsSinceEpoch() - + now.microSecondsSinceEpoch(); + std::cout << "bad address:" << addr.toIp() << " " + << interval / 1000 << "ms" << std::endl; + }); + resolver->resolve("localhost", [now](const trantor::InetAddress &addr) { + auto interval = trantor::Date::now().microSecondsSinceEpoch() - + now.microSecondsSinceEpoch(); + std::cout << "localhost:" << addr.toIp() << " " << interval / 1000 + << "ms" << std::endl; + }); +} +int main() +{ + trantor::EventLoop loop; + auto resolver = trantor::Resolver::newResolver(&loop); + dns(resolver); + loop.runAfter(1.0, [resolver]() { dns(resolver); }); + loop.loop(); +} diff --git a/web_backends/drogon/trantor/tests/KickoffTest.cc b/web_backends/drogon/trantor/tests/KickoffTest.cc new file mode 100644 index 0000000..1103822 --- /dev/null +++ b/web_backends/drogon/trantor/tests/KickoffTest.cc @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include +using namespace trantor; +#define USE_IPV6 0 +int main() +{ + LOG_DEBUG << "test start"; + Logger::setLogLevel(Logger::kTrace); + EventLoop loop; +#if USE_IPV6 + InetAddress addr(8888, true, true); +#else + InetAddress addr(8888); +#endif + TcpServer server(&loop, addr, "test"); + server.kickoffIdleConnections(10); + server.setRecvMessageCallback( + [](const TcpConnectionPtr &connectionPtr, MsgBuffer *buffer) { + // LOG_DEBUG<<"recv callback!"; + std::cout << std::string(buffer->peek(), buffer->readableBytes()); + connectionPtr->send(buffer->peek(), buffer->readableBytes()); + buffer->retrieveAll(); + }); + int n = 0; + server.setConnectionCallback([&n](const TcpConnectionPtr &connPtr) { + if (connPtr->connected()) + { + ++n; + if (n % 2 == 0) + { + connPtr->keepAlive(); + } + LOG_DEBUG << "New connection"; + } + else if (connPtr->disconnected()) + { + LOG_DEBUG << "connection disconnected"; + } + }); + server.setIoLoopNum(3); + server.start(); + loop.loop(); +} diff --git a/web_backends/drogon/trantor/tests/LoggerTest.cc b/web_backends/drogon/trantor/tests/LoggerTest.cc new file mode 100644 index 0000000..408fcb7 --- /dev/null +++ b/web_backends/drogon/trantor/tests/LoggerTest.cc @@ -0,0 +1,1139 @@ +#include +#include +#include +int main() +{ + int i; + LOG_DEBUG << (float)3.14; + LOG_DEBUG << (const char)'8'; + LOG_DEBUG << &i; + LOG_DEBUG << (long double)3.1415; + LOG_DEBUG << trantor::Fmt("%.3g", 3.1415926); + LOG_DEBUG << "debug log!" << 1; + LOG_TRACE << "trace log!" << 2; + LOG_INFO << "info log!" << 3; + LOG_WARN << "warning log!" << 4; + if (1) + LOG_ERROR << "error log!" << 5; + std::thread thread_([]() { LOG_FATAL << "fatal log!" << 6; }); + + FILE *fp = fopen("/notexistfile", "rb"); + if (fp == NULL) + { + LOG_SYSERR << "syserr log!" << 7; + } + LOG_DEBUG << "long message test:"; + LOG_DEBUG + << "Applications\n" + "Developer\n" + "Library\n" + "Network\n" + "System\n" + "Users\n" + "Volumes\n" + "bin\n" + "cores\n" + "dev\n" + "etc\n" + "home\n" + "installer.failurerequests\n" + "net\n" + "opt\n" + "private\n" + "sbin\n" + "tmp\n" + "usr\n" + "var\n" + "vm\n" + "\n" + "/Applications:\n" + "Adobe\n" + "Adobe Creative Cloud\n" + "Adobe Photoshop CC\n" + "AirPlayer Pro.app\n" + "AliWangwang.app\n" + "Android Studio.app\n" + "App Store.app\n" + "Autodesk\n" + "Automator.app\n" + "Axure RP Pro 7.0.app\n" + "BaiduNetdisk_mac.app\n" + "CLion.app\n" + "Calculator.app\n" + "Calendar.app\n" + "Chess.app\n" + "CleanApp.app\n" + "Cocos\n" + "Contacts.app\n" + "DVD Player.app\n" + "Dashboard.app\n" + "Dictionary.app\n" + "Docs for Xcode.app\n" + "FaceTime.app\n" + "FinalShell\n" + "Firefox.app\n" + "Font Book.app\n" + "GitHub.app\n" + "Google Chrome.app\n" + "Image Capture.app\n" + "Lantern.app\n" + "Launchpad.app\n" + "License.rtf\n" + "MacPorts\n" + "Mail.app\n" + "Maps.app\n" + "Messages.app\n" + "Microsoft Excel.app\n" + "Microsoft Office 2011\n" + "Microsoft OneNote.app\n" + "Microsoft Outlook.app\n" + "Microsoft PowerPoint.app\n" + "Microsoft Word.app\n" + "Mindjet MindManager.app\n" + "Mission Control.app\n" + "Mockplus.app\n" + "MyEclipse 2015\n" + "Notes.app\n" + "Numbers.app\n" + "OmniGraffle.app\n" + "Pages.app\n" + "Photo Booth.app\n" + "Photos.app\n" + "Preview.app\n" + "QJVPN.app\n" + "QQ.app\n" + "QQMusic.app\n" + "QuickTime Player.app\n" + "RAR Extractor Lite.app\n" + "Reminders.app\n" + "Remote Desktop Connection.app\n" + "Renee Undeleter.app\n" + "Sabaki.app\n" + "Safari.app\n" + "ShadowsocksX.app\n" + "Siri.app\n" + "SogouCharacterViewer.app\n" + "SogouInputPad.app\n" + "Stickies.app\n" + "SupremePlayer Lite.app\n" + "System Preferences.app\n" + "TeX\n" + "Telegram.app\n" + "Telnet Lite.app\n" + "Termius.app\n" + "Tesumego - How to Make a Professional Go Player.app\n" + "TextEdit.app\n" + "Thunder.app\n" + "Time Machine.app\n" + "Tunnelblick.app\n" + "Utilities\n" + "VPN Shield.appdownload\n" + "WeChat.app\n" + "WinOnX2.app\n" + "Wireshark.app\n" + "Xcode.app\n" + "Yose.app\n" + "YoudaoNote.localized\n" + "finalshelldata\n" + "iBooks.app\n" + "iHex.app\n" + "iPhoto.app\n" + "iTools.app\n" + "iTunes.app\n" + "pgAdmin 4.app\n" + "vSSH Lite.app\n" + "wechatwebdevtools.app\n" + "\n" + "/Applications/Adobe:\n" + "Flash Player\n" + "\n" + "/Applications/Adobe/Flash Player:\n" + "AddIns\n" + "\n" + "/Applications/Adobe/Flash Player/AddIns:\n" + "airappinstaller\n" + "\n" + "/Applications/Adobe/Flash Player/AddIns/airappinstaller:\n" + "airappinstaller\n" + "digest.s\n" + "\n" + "/Applications/Adobe Creative Cloud:\n" + "Adobe Creative Cloud\n" + "Icon\n" + "Uninstall Adobe Creative Cloud\n" + "\n" + "/Applications/Adobe Photoshop CC:\n" + "Adobe Photoshop CC.app\n" + "Configuration\n" + "Icon\n" + "Legal\n" + "LegalNotices.pdf\n" + "Locales\n" + "Plug-ins\n" + "Presets\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop CC.app:\n" + "Contents\n" + "Linguistics\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop CC.app/Contents:\n" + "Application Data\n" + "Frameworks\n" + "Info.plist\n" + "MacOS\n" + "PkgInfo\n" + "Required\n" + "Resources\n" + "_CodeSignature\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data:\n" + "Custom File Info Panels\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info Panels:\n" + "4.0\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info Panels/4.0:\n" + "bin\n" + "custom\n" + "panels\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/bin:\n" + "FileInfoFoundation.swf\n" + "FileInfoUI.swf\n" + "framework.swf\n" + "loc\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/bin/loc:\n" + "FileInfo_ar_AE.dat\n" + "FileInfo_bg_BG.dat\n" + "FileInfo_cs_CZ.dat\n" + "FileInfo_da_DK.dat\n" + "FileInfo_de_DE.dat\n" + "FileInfo_el_GR.dat\n" + "FileInfo_en_US.dat\n" + "FileInfo_es_ES.dat\n" + "FileInfo_et_EE.dat\n" + "FileInfo_fi_FI.dat\n" + "FileInfo_fr_FR.dat\n" + "FileInfo_he_IL.dat\n" + "FileInfo_hr_HR.dat\n" + "FileInfo_hu_HU.dat\n" + "FileInfo_it_IT.dat\n" + "FileInfo_ja_JP.dat\n" + "FileInfo_ko_KR.dat\n" + "FileInfo_lt_LT.dat\n" + "FileInfo_lv_LV.dat\n" + "FileInfo_nb_NO.dat\n" + "FileInfo_nl_NL.dat\n" + "FileInfo_pl_PL.dat\n" + "FileInfo_pt_BR.dat\n" + "FileInfo_ro_RO.dat\n" + "FileInfo_ru_RU.dat\n" + "FileInfo_sk_SK.dat\n" + "FileInfo_sl_SI.dat\n" + "FileInfo_sv_SE.dat\n" + "FileInfo_tr_TR.dat\n" + "FileInfo_uk_UA.dat\n" + "FileInfo_zh_CN.dat\n" + "FileInfo_zh_TW.dat\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/custom:\n" + "DICOM.xml\n" + "Mobile.xml\n" + "loc\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/custom/loc:\n" + "DICOM_ar_AE.dat\n" + "DICOM_bg_BG.dat\n" + "DICOM_cs_CZ.dat\n" + "DICOM_da_DK.dat\n" + "DICOM_de_DE.dat\n" + "DICOM_el_GR.dat\n" + "DICOM_en_US.dat\n" + "DICOM_es_ES.dat\n" + "DICOM_et_EE.dat\n" + "DICOM_fi_FI.dat\n" + "DICOM_fr_FR.dat\n" + "DICOM_he_IL.dat\n" + "DICOM_hr_HR.dat\n" + "DICOM_hu_HU.dat\n" + "DICOM_it_IT.dat\n" + "DICOM_ja_JP.dat\n" + "DICOM_ko_KR.dat\n" + "DICOM_lt_LT.dat\n" + "DICOM_lv_LV.dat\n" + "DICOM_nb_NO.dat\n" + "DICOM_nl_NL.dat\n" + "DICOM_pl_PL.dat\n" + "DICOM_pt_BR.dat\n" + "DICOM_ro_RO.dat\n" + "DICOM_ru_RU.dat\n" + "DICOM_sk_SK.dat\n" + "DICOM_sl_SI.dat\n" + "DICOM_sv_SE.dat\n" + "DICOM_tr_TR.dat\n" + "DICOM_uk_UA.dat\n" + "DICOM_zh_CN.dat\n" + "DICOM_zh_TW.dat\n" + "Mobile_ar_AE.dat\n" + "Mobile_bg_BG.dat\n" + "Mobile_cs_CZ.dat\n" + "Mobile_da_DK.dat\n" + "Mobile_de_DE.dat\n" + "Mobile_el_GR.dat\n" + "Mobile_en_US.dat\n" + "Mobile_es_ES.dat\n" + "Mobile_et_EE.dat\n" + "Mobile_fi_FI.dat\n" + "Mobile_fr_FR.dat\n" + "Mobile_he_IL.dat\n" + "Mobile_hr_HR.dat\n" + "Mobile_hu_HU.dat\n" + "Mobile_it_IT.dat\n" + "Mobile_ja_JP.dat\n" + "Mobile_ko_KR.dat\n" + "Mobile_lt_LT.dat\n" + "Mobile_lv_LV.dat\n" + "Mobile_nb_NO.dat\n" + "Mobile_nl_NL.dat\n" + "Mobile_pl_PL.dat\n" + "Mobile_pt_BR.dat\n" + "Mobile_ro_RO.dat\n" + "Mobile_ru_RU.dat\n" + "Mobile_sk_SK.dat\n" + "Mobile_sl_SI.dat\n" + "Mobile_sv_SE.dat\n" + "Mobile_tr_TR.dat\n" + "Mobile_uk_UA.dat\n" + "Mobile_zh_CN.dat\n" + "Mobile_zh_TW.dat\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels:\n" + "IPTC\n" + "IPTCExt\n" + "advanced\n" + "audioData\n" + "camera\n" + "categories\n" + "description\n" + "dicom\n" + "gpsData\n" + "history\n" + "mobile\n" + "origin\n" + "rawpacket\n" + "videoData\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/IPTC:\n" + "bin\n" + "loc\n" + "manifest.xml\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/IPTC/bin:\n" + "iptc.swf\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/IPTC/loc:\n" + "IPTC_ar_AE.dat\n" + "IPTC_bg_BG.dat\n" + "IPTC_cs_CZ.dat\n" + "IPTC_da_DK.dat\n" + "IPTC_de_DE.dat\n" + "IPTC_el_GR.dat\n" + "IPTC_en_US.dat\n" + "IPTC_es_ES.dat\n" + "IPTC_et_EE.dat\n" + "IPTC_fi_FI.dat\n" + "IPTC_fr_FR.dat\n" + "IPTC_he_IL.dat\n" + "IPTC_hr_HR.dat\n" + "IPTC_hu_HU.dat\n" + "IPTC_it_IT.dat\n" + "IPTC_ja_JP.dat\n" + "IPTC_ko_KR.dat\n" + "IPTC_lt_LT.dat\n" + "IPTC_lv_LV.dat\n" + "IPTC_nb_NO.dat\n" + "IPTC_nl_NL.dat\n" + "IPTC_pl_PL.dat\n" + "IPTC_pt_BR.dat\n" + "IPTC_ro_RO.dat\n" + "IPTC_ru_RU.dat\n" + "IPTC_sk_SK.dat\n" + "IPTC_sl_SI.dat\n" + "IPTC_sv_SE.dat\n" + "IPTC_tr_TR.dat\n" + "IPTC_uk_UA.dat\n" + "IPTC_zh_CN.dat\n" + "IPTC_zh_TW.dat\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/IPTCExt:\n" + "bin\n" + "loc\n" + "manifest.xml\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/IPTCExt/bin:\n" + "iptcExt.swf\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/IPTCExt/loc:\n" + "IPTCExt_bg_BG.dat\n" + "IPTCExt_cs_CZ.dat\n" + "IPTCExt_da_DK.dat\n" + "IPTCExt_de_DE.dat\n" + "IPTCExt_en_US.dat\n" + "IPTCExt_es_ES.dat\n" + "IPTCExt_et_EE.dat\n" + "IPTCExt_fi_FI.dat\n" + "IPTCExt_fr_FR.dat\n" + "IPTCExt_hr_HR.dat\n" + "IPTCExt_hu_HU.dat\n" + "IPTCExt_it_IT.dat\n" + "IPTCExt_ja_JP.dat\n" + "IPTCExt_ko_KR.dat\n" + "IPTCExt_lt_LT.dat\n" + "IPTCExt_lv_LV.dat\n" + "IPTCExt_nb_NO.dat\n" + "IPTCExt_nl_NL.dat\n" + "IPTCExt_pl_PL.dat\n" + "IPTCExt_pt_BR.dat\n" + "IPTCExt_ro_RO.dat\n" + "IPTCExt_ru_RU.dat\n" + "IPTCExt_sk_SK.dat\n" + "IPTCExt_sl_SI.dat\n" + "IPTCExt_sv_SE.dat\n" + "IPTCExt_tr_TR.dat\n" + "IPTCExt_uk_UA.dat\n" + "IPTCExt_zh_CN.dat\n" + "IPTCExt_zh_TW.dat\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/advanced:\n" + "bin\n" + "loc\n" + "manifest.xml\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/advanced/bin:\n" + "advanced.swf\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/advanced/loc:\n" + "Advanced_ar_AE.dat\n" + "Advanced_bg_BG.dat\n" + "Advanced_cs_CZ.dat\n" + "Advanced_da_DK.dat\n" + "Advanced_de_DE.dat\n" + "Advanced_el_GR.dat\n" + "Advanced_en_US.dat\n" + "Advanced_es_ES.dat\n" + "Advanced_et_EE.dat\n" + "Advanced_fi_FI.dat\n" + "Advanced_fr_FR.dat\n" + "Advanced_he_IL.dat\n" + "Advanced_hr_HR.dat\n" + "Advanced_hu_HU.dat\n" + "Advanced_it_IT.dat\n" + "Advanced_ja_JP.dat\n" + "Advanced_ko_KR.dat\n" + "Advanced_lt_LT.dat\n" + "Advanced_lv_LV.dat\n" + "Advanced_nb_NO.dat\n" + "Advanced_nl_NL.dat\n" + "Advanced_pl_PL.dat\n" + "Advanced_pt_BR.dat\n" + "Advanced_ro_RO.dat\n" + "Advanced_ru_RU.dat\n" + "Advanced_sk_SK.dat\n" + "Advanced_sl_SI.dat\n" + "Advanced_sv_SE.dat\n" + "Advanced_tr_TR.dat\n" + "Advanced_uk_UA.dat\n" + "Advanced_zh_CN.dat\n" + "Advanced_zh_TW.dat\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/audioData:\n" + "bin\n" + "loc\n" + "manifest.xml\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/audioData/bin:\n" + "audioData.swf\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/audioData/loc:\n" + "AudioData_ar_AE.dat\n" + "AudioData_bg_BG.dat\n" + "AudioData_cs_CZ.dat\n" + "AudioData_da_DK.dat\n" + "AudioData_de_DE.dat\n" + "AudioData_el_GR.dat\n" + "AudioData_en_US.dat\n" + "AudioData_es_ES.dat\n" + "AudioData_et_EE.dat\n" + "AudioData_fi_FI.dat\n" + "AudioData_fr_FR.dat\n" + "AudioData_he_IL.dat\n" + "AudioData_hr_HR.dat\n" + "AudioData_hu_HU.dat\n" + "AudioData_it_IT.dat\n" + "AudioData_ja_JP.dat\n" + "AudioData_ko_KR.dat\n" + "AudioData_lt_LT.dat\n" + "AudioData_lv_LV.dat\n" + "AudioData_nb_NO.dat\n" + "AudioData_nl_NL.dat\n" + "AudioData_pl_PL.dat\n" + "AudioData_pt_BR.dat\n" + "AudioData_ro_RO.dat\n" + "AudioData_ru_RU.dat\n" + "AudioData_sk_SK.dat\n" + "AudioData_sl_SI.dat\n" + "AudioData_sv_SE.dat\n" + "AudioData_tr_TR.dat\n" + "AudioData_uk_UA.dat\n" + "AudioData_zh_CN.dat\n" + "AudioData_zh_TW.dat\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/camera:\n" + "bin\n" + "loc\n" + "manifest.xml\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/camera/bin:\n" + "camera.swf\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/camera/loc:\n" + "Camera_ar_AE.dat\n" + "Camera_bg_BG.dat\n" + "Camera_cs_CZ.dat\n" + "Camera_da_DK.dat\n" + "Camera_de_DE.dat\n" + "Camera_el_GR.dat\n" + "Camera_en_US.dat\n" + "Camera_es_ES.dat\n" + "Camera_et_EE.dat\n" + "Camera_fi_FI.dat\n" + "Camera_fr_FR.dat\n" + "Camera_he_IL.dat\n" + "Camera_hr_HR.dat\n" + "Camera_hu_HU.dat\n" + "Camera_it_IT.dat\n" + "Camera_ja_JP.dat\n" + "Camera_ko_KR.dat\n" + "Camera_lt_LT.dat\n" + "Camera_lv_LV.dat\n" + "Camera_nb_NO.dat\n" + "Camera_nl_NL.dat\n" + "Camera_pl_PL.dat\n" + "Camera_pt_BR.dat\n" + "Camera_ro_RO.dat\n" + "Camera_ru_RU.dat\n" + "Camera_sk_SK.dat\n" + "Camera_sl_SI.dat\n" + "Camera_sv_SE.dat\n" + "Camera_tr_TR.dat\n" + "Camera_uk_UA.dat\n" + "Camera_zh_CN.dat\n" + "Camera_zh_TW.dat\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/categories:\n" + "bin\n" + "loc\n" + "manifest.xml\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/categories/bin:\n" + "categories.swf\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/categories/loc:\n" + "Categories_ar_AE.dat\n" + "Categories_bg_BG.dat\n" + "Categories_cs_CZ.dat\n" + "Categories_da_DK.dat\n" + "Categories_de_DE.dat\n" + "Categories_el_GR.dat\n" + "Categories_en_US.dat\n" + "Categories_es_ES.dat\n" + "Categories_et_EE.dat\n" + "Categories_fi_FI.dat\n" + "Categories_fr_FR.dat\n" + "Categories_he_IL.dat\n" + "Categories_hr_HR.dat\n" + "Categories_hu_HU.dat\n" + "Categories_it_IT.dat\n" + "Categories_ja_JP.dat\n" + "Categories_ko_KR.dat\n" + "Categories_lt_LT.dat\n" + "Categories_lv_LV.dat\n" + "Categories_nb_NO.dat\n" + "Categories_nl_NL.dat\n" + "Categories_pl_PL.dat\n" + "Categories_pt_BR.dat\n" + "Categories_ro_RO.dat\n" + "Categories_ru_RU.dat\n" + "Categories_sk_SK.dat\n" + "Categories_sl_SI.dat\n" + "Categories_sv_SE.dat\n" + "Categories_tr_TR.dat\n" + "Categories_uk_UA.dat\n" + "Categories_zh_CN.dat\n" + "Categories_zh_TW.dat\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/description:\n" + "bin\n" + "loc\n" + "manifest.xml\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/description/bin:\n" + "description.swf\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/description/loc:\n" + "description_ar_AE.dat\n" + "description_bg_BG.dat\n" + "description_cs_CZ.dat\n" + "description_da_DK.dat\n" + "description_de_DE.dat\n" + "description_el_GR.dat\n" + "description_en_US.dat\n" + "description_es_ES.dat\n" + "description_et_EE.dat\n" + "description_fi_FI.dat\n" + "description_fr_FR.dat\n" + "description_he_IL.dat\n" + "description_hr_HR.dat\n" + "description_hu_HU.dat\n" + "description_it_IT.dat\n" + "description_ja_JP.dat\n" + "description_ko_KR.dat\n" + "description_lt_LT.dat\n" + "description_lv_LV.dat\n" + "description_nb_NO.dat\n" + "description_nl_NL.dat\n" + "description_pl_PL.dat\n" + "description_pt_BR.dat\n" + "description_ro_RO.dat\n" + "description_ru_RU.dat\n" + "description_sk_SK.dat\n" + "description_sl_SI.dat\n" + "description_sv_SE.dat\n" + "description_tr_TR.dat\n" + "description_uk_UA.dat\n" + "description_zh_CN.dat\n" + "description_zh_TW.dat\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/dicom:\n" + "bin\n" + "loc\n" + "manifest.xml\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/dicom/bin:\n" + "dicom.swf\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/dicom/loc:\n" + "DICOM_ar_AE.dat\n" + "DICOM_bg_BG.dat\n" + "DICOM_cs_CZ.dat\n" + "DICOM_da_DK.dat\n" + "DICOM_de_DE.dat\n" + "DICOM_el_GR.dat\n" + "DICOM_en_US.dat\n" + "DICOM_es_ES.dat\n" + "DICOM_et_EE.dat\n" + "DICOM_fi_FI.dat\n" + "DICOM_fr_FR.dat\n" + "DICOM_he_IL.dat\n" + "DICOM_hr_HR.dat\n" + "DICOM_hu_HU.dat\n" + "DICOM_it_IT.dat\n" + "DICOM_ja_JP.dat\n" + "DICOM_ko_KR.dat\n" + "DICOM_lt_LT.dat\n" + "DICOM_lv_LV.dat\n" + "DICOM_nb_NO.dat\n" + "DICOM_nl_NL.dat\n" + "DICOM_pl_PL.dat\n" + "DICOM_pt_BR.dat\n" + "DICOM_ro_RO.dat\n" + "DICOM_ru_RU.dat\n" + "DICOM_sk_SK.dat\n" + "DICOM_sl_SI.dat\n" + "DICOM_sv_SE.dat\n" + "DICOM_tr_TR.dat\n" + "DICOM_uk_UA.dat\n" + "DICOM_zh_CN.dat\n" + "DICOM_zh_TW.dat\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/gpsData:\n" + "bin\n" + "loc\n" + "manifest.xml\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/gpsData/bin:\n" + "gpsData.swf\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/gpsData/loc:\n" + "GPSData_ar_AE.dat\n" + "GPSData_bg_BG.dat\n" + "GPSData_cs_CZ.dat\n" + "GPSData_da_DK.dat\n" + "GPSData_de_DE.dat\n" + "GPSData_el_GR.dat\n" + "GPSData_en_US.dat\n" + "GPSData_es_ES.dat\n" + "GPSData_et_EE.dat\n" + "GPSData_fi_FI.dat\n" + "GPSData_fr_FR.dat\n" + "GPSData_he_IL.dat\n" + "GPSData_hr_HR.dat\n" + "GPSData_hu_HU.dat\n" + "GPSData_it_IT.dat\n" + "GPSData_ja_JP.dat\n" + "GPSData_ko_KR.dat\n" + "GPSData_lt_LT.dat\n" + "GPSData_lv_LV.dat\n" + "GPSData_nb_NO.dat\n" + "GPSData_nl_NL.dat\n" + "GPSData_pl_PL.dat\n" + "GPSData_pt_BR.dat\n" + "GPSData_ro_RO.dat\n" + "GPSData_ru_RU.dat\n" + "GPSData_sk_SK.dat\n" + "GPSData_sl_SI.dat\n" + "GPSData_sv_SE.dat\n" + "GPSData_tr_TR.dat\n" + "GPSData_uk_UA.dat\n" + "GPSData_zh_CN.dat\n" + "GPSData_zh_TW.dat\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/history:\n" + "bin\n" + "loc\n" + "manifest.xml\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/history/bin:\n" + "history.swf\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/history/loc:\n" + "History_ar_AE.dat\n" + "History_bg_BG.dat\n" + "History_cs_CZ.dat\n" + "History_da_DK.dat\n" + "History_de_DE.dat\n" + "History_el_GR.dat\n" + "History_en_US.dat\n" + "History_es_ES.dat\n" + "History_et_EE.dat\n" + "History_fi_FI.dat\n" + "History_fr_FR.dat\n" + "History_he_IL.dat\n" + "History_hr_HR.dat\n" + "History_hu_HU.dat\n" + "History_it_IT.dat\n" + "History_ja_JP.dat\n" + "History_ko_KR.dat\n" + "History_lt_LT.dat\n" + "History_lv_LV.dat\n" + "History_nb_NO.dat\n" + "History_nl_NL.dat\n" + "History_pl_PL.dat\n" + "History_pt_BR.dat\n" + "History_ro_RO.dat\n" + "History_ru_RU.dat\n" + "History_sk_SK.dat\n" + "History_sl_SI.dat\n" + "History_sv_SE.dat\n" + "History_tr_TR.dat\n" + "History_uk_UA.dat\n" + "History_zh_CN.dat\n" + "History_zh_TW.dat\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/mobile:\n" + "bin\n" + "loc\n" + "manifest.xml\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/mobile/bin:\n" + "mobile.swf\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/mobile/loc:\n" + "Mobile_ar_AE.dat\n" + "Mobile_bg_BG.dat\n" + "Mobile_cs_CZ.dat\n" + "Mobile_da_DK.dat\n" + "Mobile_de_DE.dat\n" + "Mobile_el_GR.dat\n" + "Mobile_en_US.dat\n" + "Mobile_es_ES.dat\n" + "Mobile_et_EE.dat\n" + "Mobile_fi_FI.dat\n" + "Mobile_fr_FR.dat\n" + "Mobile_he_IL.dat\n" + "Mobile_hr_HR.dat\n" + "Mobile_hu_HU.dat\n" + "Mobile_it_IT.dat\n" + "Mobile_ja_JP.dat\n" + "Mobile_ko_KR.dat\n" + "Mobile_lt_LT.dat\n" + "Mobile_lv_LV.dat\n" + "Mobile_nb_NO.dat\n" + "Mobile_nl_NL.dat\n" + "Mobile_pl_PL.dat\n" + "Mobile_pt_BR.dat\n" + "Mobile_ro_RO.dat\n" + "Mobile_ru_RU.dat\n" + "Mobile_sk_SK.dat\n" + "Mobile_sl_SI.dat\n" + "Mobile_sv_SE.dat\n" + "Mobile_tr_TR.dat\n" + "Mobile_uk_UA.dat\n" + "Mobile_zh_CN.dat\n" + "Mobile_zh_TW.dat\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/origin:\n" + "bin\n" + "loc\n" + "manifest.xml\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/origin/bin:\n" + "origin.swf\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/origin/loc:\n" + "origin_ar_AE.dat\n" + "origin_bg_BG.dat\n" + "origin_cs_CZ.dat\n" + "origin_da_DK.dat\n" + "origin_de_DE.dat\n" + "origin_el_GR.dat\n" + "origin_en_US.dat\n" + "origin_es_ES.dat\n" + "origin_et_EE.dat\n" + "origin_fi_FI.dat\n" + "origin_fr_FR.dat\n" + "origin_he_IL.dat\n" + "origin_hr_HR.dat\n" + "origin_hu_HU.dat\n" + "origin_it_IT.dat\n" + "origin_ja_JP.dat\n" + "origin_ko_KR.dat\n" + "origin_lt_LT.dat\n" + "origin_lv_LV.dat\n" + "origin_nb_NO.dat\n" + "origin_nl_NL.dat\n" + "origin_pl_PL.dat\n" + "origin_pt_BR.dat\n" + "origin_ro_RO.dat\n" + "origin_ru_RU.dat\n" + "origin_sk_SK.dat\n" + "origin_sl_SI.dat\n" + "origin_sv_SE.dat\n" + "origin_tr_TR.dat\n" + "origin_uk_UA.dat\n" + "origin_zh_CN.dat\n" + "origin_zh_TW.dat\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/rawpacket:\n" + "bin\n" + "loc\n" + "manifest.xml\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/rawpacket/bin:\n" + "rawpacket.swf\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/rawpacket/loc:\n" + "Rawpacket_ar_AE.dat\n" + "Rawpacket_bg_BG.dat\n" + "Rawpacket_cs_CZ.dat\n" + "Rawpacket_da_DK.dat\n" + "Rawpacket_de_DE.dat\n" + "Rawpacket_el_GR.dat\n" + "Rawpacket_en_US.dat\n" + "Rawpacket_es_ES.dat\n" + "Rawpacket_et_EE.dat\n" + "Rawpacket_fi_FI.dat\n" + "Rawpacket_fr_FR.dat\n" + "Rawpacket_he_IL.dat\n" + "Rawpacket_hr_HR.dat\n" + "Rawpacket_hu_HU.dat\n" + "Rawpacket_it_IT.dat\n" + "Rawpacket_ja_JP.dat\n" + "Rawpacket_ko_KR.dat\n" + "Rawpacket_lt_LT.dat\n" + "Rawpacket_lv_LV.dat\n" + "Rawpacket_nb_NO.dat\n" + "Rawpacket_nl_NL.dat\n" + "Rawpacket_pl_PL.dat\n" + "Rawpacket_pt_BR.dat\n" + "Rawpacket_ro_RO.dat\n" + "Rawpacket_ru_RU.dat\n" + "Rawpacket_sk_SK.dat\n" + "Rawpacket_sl_SI.dat\n" + "Rawpacket_sv_SE.dat\n" + "Rawpacket_tr_TR.dat\n" + "Rawpacket_uk_UA.dat\n" + "Rawpacket_zh_CN.dat\n" + "Rawpacket_zh_TW.dat\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/videoData:\n" + "bin\n" + "loc\n" + "manifest.xml\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/videoData/bin:\n" + "videoData.swf\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Application Data/Custom File Info " + "Panels/4.0/panels/videoData/loc:\n" + "VideoData_ar_AE.dat\n" + "VideoData_bg_BG.dat\n" + "VideoData_cs_CZ.dat\n" + "VideoData_da_DK.dat\n" + "VideoData_de_DE.dat\n" + "VideoData_el_GR.dat\n" + "VideoData_en_US.dat\n" + "VideoData_es_ES.dat\n" + "VideoData_et_EE.dat\n" + "VideoData_fi_FI.dat\n" + "VideoData_fr_FR.dat\n" + "VideoData_he_IL.dat\n" + "VideoData_hr_HR.dat\n" + "VideoData_hu_HU.dat\n" + "VideoData_it_IT.dat\n" + "VideoData_ja_JP.dat\n" + "VideoData_ko_KR.dat\n" + "VideoData_lt_LT.dat\n" + "VideoData_lv_LV.dat\n" + "VideoData_nb_NO.dat\n" + "VideoData_nl_NL.dat\n" + "VideoData_pl_PL.dat\n" + "VideoData_pt_BR.dat\n" + "VideoData_ro_RO.dat\n" + "VideoData_ru_RU.dat\n" + "VideoData_sk_SK.dat\n" + "VideoData_sl_SI.dat\n" + "VideoData_sv_SE.dat\n" + "VideoData_tr_TR.dat\n" + "VideoData_uk_UA.dat\n" + "VideoData_zh_CN.dat\n" + "VideoData_zh_TW.dat\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Frameworks:\n" + "AdbeScriptUIFlex.framework\n" + "AdobeACE.framework\n" + "AdobeAGM.framework\n" + "AdobeAXE8SharedExpat.framework\n" + "AdobeAXEDOMCore.framework\n" + "AdobeBIB.framework\n" + "AdobeBIBUtils.framework\n" + "AdobeCoolType.framework\n" + "AdobeCrashReporter.framework\n" + "AdobeExtendScript.framework\n" + "AdobeLinguistic.framework\n" + "AdobeMPS.framework\n" + "AdobeOwl.framework\n" + "AdobePDFSettings.framework\n" + "AdobePIP.framework\n" + "AdobeScCore.framework\n" + "AdobeUpdater.framework\n" + "AdobeXMP.framework\n" + "AdobeXMPFiles.framework\n" + "AdobeXMPScript.framework\n" + "AlignmentLib.framework\n" + "CIT\n" + "CIT.framework\n" + "CITThreading.framework\n" + "Cg.framework\n" + "FileInfo.framework\n" + "ICUConverter.framework\n" + "ICUData.framework\n" + "IMSLib.dylib\n" + "LogSession.framework\n" + "PlugPlugOwl.framework\n" + "WRServices.framework\n" + "adbeape.framework\n" + "adobe_caps.framework\n" + "adobejp2k.framework\n" + "adobepdfl.framework\n" + "ahclient.framework\n" + "aif_core.framework\n" + "aif_ocl.framework\n" + "aif_ogl.framework\n" + "amtlib.framework\n" + "boost_date_time.framework\n" + "boost_signals.framework\n" + "boost_system.framework\n" + "boost_threads.framework\n" + "dvaaudiodevice.framework\n" + "dvacore.framework\n" + "dvamarshal.framework\n" + "dvamediatypes.framework\n" + "dvaplayer.framework\n" + "dvatransport.framework\n" + "dvaunittesting.framework\n" + "dynamiclink.framework\n" + "filter_graph.framework\n" + "libtbb.dylib\n" + "libtbbmalloc.dylib\n" + "mediacoreif.framework\n" + "patchmatch.framework\n" + "updaternotifications.framework\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Frameworks/AdbeScriptUIFlex.framework:\n" + "AdbeScriptUIFlex\n" + "Resources\n" + "Versions\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Frameworks/AdbeScriptUIFlex.framework/Versions:\n" + "A\n" + "Current\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Frameworks/AdbeScriptUIFlex.framework/Versions/A:\n" + "AdbeScriptUIFlex\n" + "CodeResources\n" + "_CodeSignature\n" + "resources\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Frameworks/AdbeScriptUIFlex.framework/Versions/A/" + "_CodeSignature:\n" + "CodeResources\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Frameworks/AdbeScriptUIFlex.framework/Versions/A/" + "resources:\n" + "Info.plist\n" + "english.lproj\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Frameworks/AdbeScriptUIFlex.framework/Versions/A/" + "resources/english.lproj:\n" + "InfoPlist.strings\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Frameworks/AdobeACE.framework:\n" + "AdobeACE\n" + "Versions\n" + "resources\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Frameworks/AdobeACE.framework/Versions:\n" + "A\n" + "current\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Frameworks/AdobeACE.framework/Versions/A:\n" + "AdobeACE\n" + "CodeResources\n" + "_CodeSignature\n" + "resources\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Frameworks/AdobeACE.framework/Versions/A/" + "_CodeSignature:\n" + "CodeResources\n" + "\n" + "/Applications/Adobe Photoshop CC/Adobe Photoshop " + "CC.app/Contents/Frameworks/AdobeACE.framework/Versions/A/" + "resources:\n" + "Info.plist\n" + "english.lproj\n" + "" + << 123 << 123.123 << "haha" << '\n' + << std::string("12356"); + LOG_RAW << "Testing finished\n"; + LOG_RAW_TO(5) << "Testing finished\n"; + thread_.join(); +} diff --git a/web_backends/drogon/trantor/tests/RunInLoopTest1.cc b/web_backends/drogon/trantor/tests/RunInLoopTest1.cc new file mode 100644 index 0000000..d5c6951 --- /dev/null +++ b/web_backends/drogon/trantor/tests/RunInLoopTest1.cc @@ -0,0 +1,30 @@ +// +// Created by antao on 1/14/17. +// + +#include +#ifndef _WIN32 +#include +#endif + +#include +#include +#include +using namespace std::chrono_literals; +int main() +{ + trantor::EventLoop loop; + std::thread thread([&loop]() { + std::this_thread::sleep_for(3s); + loop.runInLoop([&loop]() { + std::cout << "runInLoop called in other thread" << std::endl; + loop.queueInLoop( + []() { std::cout << "queueInLoop in runInLoop" << std::endl; }); + }); + }); + loop.runInLoop([]() { std::cout << "runInLoop 1" << std::endl; }); + loop.runInLoop([]() { std::cout << "runInLoop 2" << std::endl; }); + loop.queueInLoop([]() { std::cout << "queueInLoop 1" << std::endl; }); + loop.runAfter(1.5, []() { std::cout << "run after 1.5" << std::endl; }); + loop.loop(); +} diff --git a/web_backends/drogon/trantor/tests/RunInLoopTest2.cc b/web_backends/drogon/trantor/tests/RunInLoopTest2.cc new file mode 100644 index 0000000..ce969a3 --- /dev/null +++ b/web_backends/drogon/trantor/tests/RunInLoopTest2.cc @@ -0,0 +1,44 @@ +#include +#include +#include +#include +#ifndef _WIN32 +#include +#endif + +int main() +{ + std::atomic counter; + counter = 0; + std::promise pro; + auto ft = pro.get_future(); + trantor::EventLoopThread loopThread; + + auto loop = loopThread.getLoop(); + loop->runInLoop([&counter, &pro, loop]() { + for (int i = 0; i < 10000; ++i) + { + loop->queueInLoop([&counter, &pro]() { + ++counter; + if (counter.load() == 110000) + pro.set_value(1); + }); + } + }); + for (int i = 0; i < 10; ++i) + { + std::thread([&counter, loop, &pro]() { + for (int i = 0; i < 10000; ++i) + { + loop->runInLoop([&counter, &pro]() { + ++counter; + if (counter.load() == 110000) + pro.set_value(1); + }); + } + }).detach(); + } + loopThread.run(); + ft.get(); + std::cout << "counter=" << counter.load() << std::endl; +} diff --git a/web_backends/drogon/trantor/tests/RunOnQuitTest.cc b/web_backends/drogon/trantor/tests/RunOnQuitTest.cc new file mode 100644 index 0000000..37f9572 --- /dev/null +++ b/web_backends/drogon/trantor/tests/RunOnQuitTest.cc @@ -0,0 +1,27 @@ +#include +#include +#include +#include +#ifndef _WIN32 +#include +#endif + +int main() +{ + std::atomic flag(false); + { + trantor::EventLoopThread thr; + thr.getLoop()->runOnQuit([&]() { flag = true; }); + thr.run(); + thr.getLoop()->quit(); + } + + if (flag == false) + { + std::cerr << "Test failed\n"; + } + else + { + std::cout << "Success\n"; + } +} diff --git a/web_backends/drogon/trantor/tests/SSLClientTest.cc b/web_backends/drogon/trantor/tests/SSLClientTest.cc new file mode 100644 index 0000000..f38a0f3 --- /dev/null +++ b/web_backends/drogon/trantor/tests/SSLClientTest.cc @@ -0,0 +1,54 @@ +#include +#include +#include +#include +#include +#include +using namespace trantor; +#define USE_IPV6 0 +int main() +{ + trantor::Logger::setLogLevel(trantor::Logger::kTrace); + LOG_DEBUG << "TcpClient class test!"; + EventLoop loop; +#if USE_IPV6 + InetAddress serverAddr("::1", 8888, true); +#else + InetAddress serverAddr("127.0.0.1", 8888); +#endif + std::shared_ptr client[10]; + std::atomic_int connCount; + connCount = 1; + for (int i = 0; i < connCount; ++i) + { + client[i] = std::make_shared(&loop, + serverAddr, + "tcpclienttest"); + client[i]->enableSSL(false, false); + client[i]->setConnectionCallback( + [i, &loop, &connCount](const TcpConnectionPtr &conn) { + if (conn->connected()) + { + LOG_DEBUG << i << " connected!"; + char tmp[20]; + sprintf(tmp, "%d client!!", i); + conn->send(tmp); + } + else + { + LOG_DEBUG << i << " disconnected"; + --connCount; + if (connCount == 0) + loop.quit(); + } + }); + client[i]->setMessageCallback( + [](const TcpConnectionPtr &conn, MsgBuffer *buf) { + LOG_DEBUG << std::string(buf->peek(), buf->readableBytes()); + buf->retrieveAll(); + conn->shutdown(); + }); + client[i]->connect(); + } + loop.loop(); +} diff --git a/web_backends/drogon/trantor/tests/SSLServerTest.cc b/web_backends/drogon/trantor/tests/SSLServerTest.cc new file mode 100644 index 0000000..3cf5213 --- /dev/null +++ b/web_backends/drogon/trantor/tests/SSLServerTest.cc @@ -0,0 +1,43 @@ +#include +#include +#include +#include +#include +using namespace trantor; +#define USE_IPV6 0 +int main() +{ + LOG_DEBUG << "test start"; + Logger::setLogLevel(Logger::kTrace); + EventLoopThread loopThread; + loopThread.run(); +#if USE_IPV6 + InetAddress addr(8888, true, true); +#else + InetAddress addr(8888); +#endif + TcpServer server(loopThread.getLoop(), addr, "test"); + server.enableSSL("server.pem", "server.pem"); + server.setRecvMessageCallback( + [](const TcpConnectionPtr &connectionPtr, MsgBuffer *buffer) { + // LOG_DEBUG<<"recv callback!"; + std::cout << std::string(buffer->peek(), buffer->readableBytes()); + connectionPtr->send(buffer->peek(), buffer->readableBytes()); + buffer->retrieveAll(); + connectionPtr->forceClose(); + }); + server.setConnectionCallback([](const TcpConnectionPtr &connPtr) { + if (connPtr->connected()) + { + LOG_DEBUG << "New connection"; + connPtr->send("Hello world\r\n"); + } + else if (connPtr->disconnected()) + { + LOG_DEBUG << "connection disconnected"; + } + }); + server.setIoLoopNum(3); + server.start(); + loopThread.wait(); +} diff --git a/web_backends/drogon/trantor/tests/SendfileTest.cc b/web_backends/drogon/trantor/tests/SendfileTest.cc new file mode 100644 index 0000000..c0abb5b --- /dev/null +++ b/web_backends/drogon/trantor/tests/SendfileTest.cc @@ -0,0 +1,91 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef _WIN32 +#include +#endif + +using namespace trantor; +#define USE_IPV6 0 +int main(int argc, char *argv[]) +{ + if (argc < 2) + { + std::cout << "usage:" << argv[0] << " filename" << std::endl; + return 1; + } + std::cout << "filename:" << argv[1] << std::endl; + struct stat filestat; + if (stat(argv[1], &filestat) < 0) + { + perror(""); + exit(1); + } + std::cout << "file len=" << filestat.st_size << std::endl; + + auto fp = fopen(argv[1], "rb"); + + if (fp == nullptr) + { + perror(""); + exit(1); + } + fclose(fp); + + LOG_DEBUG << "test start"; + + Logger::setLogLevel(Logger::kTrace); + EventLoopThread loopThread; + loopThread.run(); + +#if USE_IPV6 + InetAddress addr(1207, true, true); +#else + InetAddress addr(1207); +#endif + TcpServer server(loopThread.getLoop(), addr, "test"); + server.setRecvMessageCallback( + [](const TcpConnectionPtr &connectionPtr, MsgBuffer *buffer) { + // LOG_DEBUG<<"recv callback!"; + }); + int counter = 0; + server.setConnectionCallback( + [argv, &counter](const TcpConnectionPtr &connPtr) { + if (connPtr->connected()) + { + LOG_DEBUG << "New connection"; + std::thread t([connPtr, argv, &counter]() { + for (int i = 0; i < 5; ++i) + { + connPtr->sendFile(argv[1]); + char str[64]; + ++counter; + sprintf(str, "\n%d files sent!\n", counter); + connPtr->send(str, strlen(str)); + } + }); + t.detach(); + + for (int i = 0; i < 3; ++i) + { + connPtr->sendFile(argv[1]); + char str[64]; + ++counter; + sprintf(str, "\n%d files sent!\n", counter); + connPtr->send(str, strlen(str)); + } + } + else if (connPtr->disconnected()) + { + LOG_DEBUG << "connection disconnected"; + } + }); + server.setIoLoopNum(3); + server.start(); + loopThread.wait(); +} diff --git a/web_backends/drogon/trantor/tests/SerialTaskQueueTest1.cc b/web_backends/drogon/trantor/tests/SerialTaskQueueTest1.cc new file mode 100755 index 0000000..b989d32 --- /dev/null +++ b/web_backends/drogon/trantor/tests/SerialTaskQueueTest1.cc @@ -0,0 +1,29 @@ +#include +#include +#include +#include +#include + +using namespace std::chrono_literals; +int main() +{ + trantor::Logger::setLogLevel(trantor::Logger::kTrace); + trantor::SerialTaskQueue queue1("test queue1"); + trantor::SerialTaskQueue queue2(""); + queue1.runTaskInQueue([&]() { + for (int i = 0; i < 5; ++i) + { + std::this_thread::sleep_for(1s); + printf("task(%s) i=%d\n", queue1.getName().c_str(), i); + } + }); + queue2.runTaskInQueue([&]() { + for (int i = 0; i < 5; ++i) + { + std::this_thread::sleep_for(1s); + printf("task(%s) i=%d\n", queue2.getName().c_str(), i); + } + }); + queue1.waitAllTasksFinished(); + queue2.waitAllTasksFinished(); +} diff --git a/web_backends/drogon/trantor/tests/SerialTaskQueueTest2.cc b/web_backends/drogon/trantor/tests/SerialTaskQueueTest2.cc new file mode 100644 index 0000000..59068fe --- /dev/null +++ b/web_backends/drogon/trantor/tests/SerialTaskQueueTest2.cc @@ -0,0 +1,42 @@ +#include +#include +#include +#include +#ifndef _WIN32 +#include +#endif + +int main() +{ + std::atomic counter; + counter = 0; + std::promise pro; + auto ft = pro.get_future(); + trantor::SerialTaskQueue queue(""); + queue.runTaskInQueue([&counter, &pro, &queue]() { + for (int i = 0; i < 10000; ++i) + { + queue.runTaskInQueue([&counter, &pro]() { + ++counter; + if (counter.load() == 110000) + pro.set_value(1); + }); + } + }); + for (int i = 0; i < 10; ++i) + { + std::thread([&counter, &queue, &pro]() { + for (int i = 0; i < 10000; ++i) + { + queue.runTaskInQueue([&counter, &pro]() { + ++counter; + if (counter.load() == 110000) + pro.set_value(1); + }); + } + }).detach(); + } + + ft.get(); + std::cout << "counter=" << counter.load() << std::endl; +} \ No newline at end of file diff --git a/web_backends/drogon/trantor/tests/TcpClientTest.cc b/web_backends/drogon/trantor/tests/TcpClientTest.cc new file mode 100644 index 0000000..68d6f89 --- /dev/null +++ b/web_backends/drogon/trantor/tests/TcpClientTest.cc @@ -0,0 +1,53 @@ +#include +#include +#include +#include +#include +#include +using namespace trantor; +#define USE_IPV6 0 +int main() +{ + trantor::Logger::setLogLevel(trantor::Logger::kTrace); + LOG_DEBUG << "TcpClient class test!"; + EventLoop loop; +#if USE_IPV6 + InetAddress serverAddr("::1", 8888, true); +#else + InetAddress serverAddr("127.0.0.1", 8888); +#endif + std::shared_ptr client[10]; + std::atomic_int connCount; + connCount = 10; + for (int i = 0; i < 10; ++i) + { + client[i] = std::make_shared(&loop, + serverAddr, + "tcpclienttest"); + client[i]->setConnectionCallback( + [i, &loop, &connCount](const TcpConnectionPtr &conn) { + if (conn->connected()) + { + LOG_DEBUG << i << " connected!"; + char tmp[20]; + sprintf(tmp, "%d client!!", i); + conn->send(tmp); + } + else + { + LOG_DEBUG << i << " disconnected"; + --connCount; + if (connCount == 0) + loop.quit(); + } + }); + client[i]->setMessageCallback( + [](const TcpConnectionPtr &conn, MsgBuffer *buf) { + LOG_DEBUG << std::string(buf->peek(), buf->readableBytes()); + buf->retrieveAll(); + conn->shutdown(); + }); + client[i]->connect(); + } + loop.loop(); +} diff --git a/web_backends/drogon/trantor/tests/TcpServerTest.cc b/web_backends/drogon/trantor/tests/TcpServerTest.cc new file mode 100644 index 0000000..dbd8b7c --- /dev/null +++ b/web_backends/drogon/trantor/tests/TcpServerTest.cc @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include +using namespace trantor; +#define USE_IPV6 0 +int main() +{ + LOG_DEBUG << "test start"; + Logger::setLogLevel(Logger::kTrace); + EventLoopThread loopThread; + loopThread.run(); +#if USE_IPV6 + InetAddress addr(8888, true, true); +#else + InetAddress addr(8888); +#endif + TcpServer server(loopThread.getLoop(), addr, "test"); + server.setRecvMessageCallback( + [](const TcpConnectionPtr &connectionPtr, MsgBuffer *buffer) { + // LOG_DEBUG<<"recv callback!"; + std::cout << std::string(buffer->peek(), buffer->readableBytes()); + connectionPtr->send(buffer->peek(), buffer->readableBytes()); + buffer->retrieveAll(); + // connectionPtr->forceClose(); + }); + server.setConnectionCallback([](const TcpConnectionPtr &connPtr) { + if (connPtr->connected()) + { + LOG_DEBUG << "New connection"; + } + else if (connPtr->disconnected()) + { + LOG_DEBUG << "connection disconnected"; + } + }); + server.setIoLoopNum(3); + server.start(); + loopThread.wait(); +} diff --git a/web_backends/drogon/trantor/tests/TimerTest.cc b/web_backends/drogon/trantor/tests/TimerTest.cc new file mode 100644 index 0000000..606c45e --- /dev/null +++ b/web_backends/drogon/trantor/tests/TimerTest.cc @@ -0,0 +1,33 @@ +#include +#include +#include +#include +#include +using namespace std::literals; + +int main() +{ + trantor::Logger::setLogLevel(trantor::Logger::kTrace); + trantor::EventLoop loop; + auto id1 = loop.runAfter(1s, []() { + LOG_ERROR << "This info shouldn't be displayed!"; + }); + loop.invalidateTimer(id1); + auto id2 = loop.runEvery(0.3s, []() { + LOG_ERROR << "This timer will be invalidated after 3 second;"; + }); + std::thread thread([id2, &loop]() { + std::this_thread::sleep_for(3s); + loop.invalidateTimer(id2); + }); + thread.detach(); + loop.runEvery(3, []() { LOG_DEBUG << " runEvery 3s"; }); + loop.runAt(trantor::Date::date().after(10), + []() { LOG_DEBUG << "runAt 10s later"; }); + loop.runAfter(5, []() { std::cout << "runAt 5s later" << std::endl; }); + loop.runEvery(1, []() { std::cout << "runEvery 1s" << std::endl; }); + loop.runAfter(4, []() { std::cout << "runAfter 4s" << std::endl; }); + loop.runAfter(10min, + []() { std::cout << "*********** run after 10 min\n"; }); + loop.loop(); +} diff --git a/web_backends/drogon/trantor/tests/TimerTest1.cc b/web_backends/drogon/trantor/tests/TimerTest1.cc new file mode 100644 index 0000000..09884c5 --- /dev/null +++ b/web_backends/drogon/trantor/tests/TimerTest1.cc @@ -0,0 +1,23 @@ +#include +#include +#include +int main() +{ + trantor::EventLoop loop; + LOG_FATAL << trantor::Date::date().roundDay().microSecondsSinceEpoch(); + trantor::Date begin = trantor::Date::date().roundSecond().after(2); + auto id = loop.runAt(begin, [begin, &loop]() { + LOG_DEBUG << "test begin:"; + srand((unsigned int)time(NULL)); + for (int i = 0; i < 10000; ++i) + { + int aa = rand() % 10000; + double s = (double)aa / 1000.0 + 1; + loop.runAt(begin.after(s), + [s]() { LOG_ERROR << "run After:" << s; }); + } + LOG_DEBUG << "timer created!"; + }); + std::cout << "id=" << id << std::endl; + loop.loop(); +} diff --git a/web_backends/drogon/trantor/tests/TimingWheelTest.cc b/web_backends/drogon/trantor/tests/TimingWheelTest.cc new file mode 100644 index 0000000..c9ae1b5 --- /dev/null +++ b/web_backends/drogon/trantor/tests/TimingWheelTest.cc @@ -0,0 +1,48 @@ +#include +#include +#include +class MyClass +{ + public: + MyClass(); + MyClass(MyClass &&) = default; + MyClass(const MyClass &) = default; + MyClass &operator=(MyClass &&) = default; + MyClass &operator=(const MyClass &) = default; + ~MyClass(); + + private: +}; + +MyClass::MyClass() +{ +} + +MyClass::~MyClass() +{ + LOG_DEBUG << "MyClass destructed!"; +} + +int main() +{ + LOG_DEBUG << "start"; + trantor::EventLoop loop; + std::weak_ptr weakEntry; + trantor::TimingWheel wheel(&loop, 75, 0.1, 100); + { + auto entry = std::shared_ptr(new MyClass); + + wheel.insertEntry(75, entry); + weakEntry = entry; + } + // loop.runAfter(5.0, [&]() { + // wheel.insertEntry(10, weakEntry.lock()); + // }); + // loop.runAfter(0.5,[&](){ + // wheel.insertEntry(28,weakEntry.lock()); + // }); + // loop.runEvery(1.0,[](){ + // LOG_DEBUG<<"tick"; + // }); + loop.loop(); +} diff --git a/web_backends/drogon/trantor/tests/server.pem b/web_backends/drogon/trantor/tests/server.pem new file mode 100644 index 0000000..507f700 --- /dev/null +++ b/web_backends/drogon/trantor/tests/server.pem @@ -0,0 +1,49 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC/vLeZ4B80b22y +JSF9WoAEGo5D0GLlzSxL7rRZSd81h3YMKpsgFT4WkZxs9sqoRW/OTaqMGuEzGt6a +54RMwycQwJL+GGt/stZ+7AYHoLE6cQzP8iFcwy4mLFsX+gQjoE0UHr0RykKRl3Vw +qZST74AhAMlFvEDCfoMxTy9dy5ZjbLTFrH1kvo5CT9MEbyBLpxYrYYFjBAMIZdvV +82Mz3JftDLbx7t+96PaGLpDMLk9NgrV1kbUpzck/aCbZ5DgV7enTU33tVIcfMU5e +fZii044OkOvFNXibi6tdPORP8TBnrmEZjmDnFAgEijzpIcJ4VVPTrlCuxLUKcSDY +wYLro7gbAgMBAAECggEAesztcnoewkCTq0MovdZWo0o2z6wJi1DrC/7oNz+e2/PU +YVpwXA3+5AmCfC9cAIXoY+NOVclpbofJBsE89MUQoiQUgPU29GSgCE42VnBO0jVR +lWVohLblOcGy3hpcyEyE0VwWj+xQ0lqE9xFFfbIpB/ou7qDxgR/x+oTSu2oG+cmr +xv+Dj+k46QW0X2A3XHnlZkk0fQGb+Tf3fIJ4BBwF/UFQTDyZPZrsZfbpoEk1BnIf +VPcfM1/ca6h1t/oEnpD66H2TjxYzZC58mqZSZIZ+Pk+wocSsF5UcQLedcM137LDH +OR+fdscinr1xgMhV30RmAUP5tug9Km3oq8wf4Xl1IQKBgQDmDtYbwN7V1eA6Dbeq +HCk07t/llK+j4mvyuU+pVKfNHmnUUd+NPpDwREFrfoR6ilrZMJ4Obl7z53rja+9s +JqECBThhRzHxnUQgsu3DQeY7e2KxBBGGvhQBjRGtVRID3aFTTyMKvaOkTc7kL+x1 +5DbtoVAA1kbYnjgZJyZosx+bmQKBgQDVW6lXxoLzC7npXdXOTMJifExcCIzXskc9 +5b+rJTXgkqaPQSQ7nNmRReUY9r9UBsZKLduuYJZ3TLMCaU91/wBwc1ygkQvRz+8A +2QGMovlVOqwPAOEc1lMCXzQki9PcqmVX/e0oFmTtUgyF4RKEwL/q8A9fWy587rkQ +57MDNJ3h0wKBgQDNJgPFweq0EsGd4yeZuP0B59Wee0VYxgru6lLgM85iujEzFUNd +R6KlrqgLvElUoNW8gX8gbUmdBBlwfYqGDbhb/d212W/u/geHhSdCjBxLhI6QPYmH +dy6N54cQ4yBqdBNtH8+mv08SsBPDJf0db8GPi960sF+CwSxTObclfD2+WQKBgBgi +HxyLmsJNIEFSWN3V9uLW9ngui2fWhZJty2lbcyWs0ORBVQzdKArzof9Z4bhqb8Fy +QHgP+tURuunZ6aAKMQ2HLwIGhhS8dWdeJHu474UBdvbXfZ8aaxdIl4hOvK8oIwB5 ++3peVho1/q6iD8suVkcH0mVR1gdRpWNRIgGJ0RX7AoGBAMzp0u3X3SEMWTlqFR7D +BJqmpiMvJJJSqex1i4PJoy+uJpqfl3b1jUMnFIS4GiscVCIEJkPpZaz3eSTt7aVQ ++7v0b/Cusv1qYX2c5v9j9x7nmUlfdwT5rY2g6RXI/xlhPD9elb1dxlzmhiO4VQtr +AdiFmu0poyPpEGwjpcLEZq6K +-----END PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIDajCCAlICCQCXmD7IkkDArzANBgkqhkiG9w0BAQsFADB3MQswCQYDVQQGEwJD +TjEQMA4GA1UECAwHQmVpamluZzEQMA4GA1UEBwwHQmVpamluZzEPMA0GA1UECgwG +YW4tdGFvMQ8wDQYDVQQLDAZhbi10YW8xIjAgBgkqhkiG9w0BCQEWE2FudGFvMjAw +MkBnbWFpbC5jb20wHhcNMTgwNzIxMDEyMjEyWhcNMTkwNzIxMDEyMjEyWjB3MQsw +CQYDVQQGEwJDTjEQMA4GA1UECAwHQmVpamluZzEQMA4GA1UEBwwHQmVpamluZzEP +MA0GA1UECgwGYW4tdGFvMQ8wDQYDVQQLDAZhbi10YW8xIjAgBgkqhkiG9w0BCQEW +E2FudGFvMjAwMkBnbWFpbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQC/vLeZ4B80b22yJSF9WoAEGo5D0GLlzSxL7rRZSd81h3YMKpsgFT4WkZxs +9sqoRW/OTaqMGuEzGt6a54RMwycQwJL+GGt/stZ+7AYHoLE6cQzP8iFcwy4mLFsX ++gQjoE0UHr0RykKRl3VwqZST74AhAMlFvEDCfoMxTy9dy5ZjbLTFrH1kvo5CT9ME +byBLpxYrYYFjBAMIZdvV82Mz3JftDLbx7t+96PaGLpDMLk9NgrV1kbUpzck/aCbZ +5DgV7enTU33tVIcfMU5efZii044OkOvFNXibi6tdPORP8TBnrmEZjmDnFAgEijzp +IcJ4VVPTrlCuxLUKcSDYwYLro7gbAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAClA +Z6JHessY1mo0ObCp8Sh83gIiGu9M77xz6Gy2vUpUGE9N1hJwYH3uZPLbpnIuxZU0 +uDXd9w5vCJmtqo/4X6sedqKA6Upi8DROawtCUJaGrHrb2vJONyL7A3OWpHyYgOAa +z+sl4jbrGGv4azSg9ef1mQZTDcEcdsYiKj9U4zoyDXteyt6NQK3x5BtziB0mJfeM +gjrltVcc59s8Z2jf3PI3qmWtMuJm7KGHlan2DUz12AZxY3sJrFyew3Vi1V2uvIZB +YwgcXbVa3r6PQU3RwFwkazxAe80ZgiQlVsEiBl8mre4zznt5XHF6mzAqvpHyXPCI +LfEO3waLkgB94mFha5A= +-----END CERTIFICATE----- diff --git a/core/polling/poller/wepoll/LICENSE b/web_backends/drogon/trantor/third_party/wepoll/LICENSE similarity index 100% rename from core/polling/poller/wepoll/LICENSE rename to web_backends/drogon/trantor/third_party/wepoll/LICENSE diff --git a/core/polling/poller/wepoll/README.md b/web_backends/drogon/trantor/third_party/wepoll/README.md similarity index 93% rename from core/polling/poller/wepoll/README.md rename to web_backends/drogon/trantor/third_party/wepoll/README.md index f8b86a3..fc9ce85 100644 --- a/core/polling/poller/wepoll/README.md +++ b/web_backends/drogon/trantor/third_party/wepoll/README.md @@ -2,7 +2,7 @@ This library is based on [wepoll v1.5.8](https://github.com/piscisaureus/wepoll/commit/0598a791bf9cbbf480793d778930fc635b044980). -An eventfd-like mechanism is added to it. After making the changes, we can wake up `EventLoop` from the epoll_wait() function. +An eventfd-like mechanism is added to it. After making the changes, we can wake up `trantor::EventLoop` from the epoll_wait() function. ## Modifications diff --git a/core/polling/poller/wepoll/Wepoll.c b/web_backends/drogon/trantor/third_party/wepoll/Wepoll.c similarity index 100% rename from core/polling/poller/wepoll/Wepoll.c rename to web_backends/drogon/trantor/third_party/wepoll/Wepoll.c diff --git a/core/polling/poller/wepoll/Wepoll.h b/web_backends/drogon/trantor/third_party/wepoll/Wepoll.h similarity index 100% rename from core/polling/poller/wepoll/Wepoll.h rename to web_backends/drogon/trantor/third_party/wepoll/Wepoll.h diff --git a/web_backends/drogon/trantor/unittests/CMakeLists.txt b/web_backends/drogon/trantor/unittests/CMakeLists.txt new file mode 100644 index 0000000..4c7f492 --- /dev/null +++ b/web_backends/drogon/trantor/unittests/CMakeLists.txt @@ -0,0 +1,19 @@ +find_package(GTest REQUIRED) +add_executable(msgbuffer_unittest MsgBufferUnittest.cc) +add_executable(inetaddress_unittest InetAddressUnittest.cc) +add_executable(date_unittest DateUnittest.cc) +add_executable(split_string_unittest splitStringUnittest.cc) +set(UNITTEST_TARGETS + msgbuffer_unittest + inetaddress_unittest + date_unittest + split_string_unittest) +set_property(TARGET ${UNITTEST_TARGETS} PROPERTY CXX_STANDARD 14) +set_property(TARGET ${UNITTEST_TARGETS} PROPERTY CXX_STANDARD_REQUIRED ON) +set_property(TARGET ${UNITTEST_TARGETS} PROPERTY CXX_EXTENSIONS OFF) + +include(GoogleTest) +foreach(T ${UNITTEST_TARGETS}) + target_link_libraries(${T} PRIVATE trantor GTest::GTest) + gtest_discover_tests(${T}) +endforeach() diff --git a/web_backends/drogon/trantor/unittests/DateUnittest.cc b/web_backends/drogon/trantor/unittests/DateUnittest.cc new file mode 100644 index 0000000..255ce28 --- /dev/null +++ b/web_backends/drogon/trantor/unittests/DateUnittest.cc @@ -0,0 +1,43 @@ +#include +#include +#include +#include +using namespace trantor; +TEST(Date, constructorTest) +{ + EXPECT_STREQ("1985-01-01 00:00:00", + trantor::Date(1985, 1, 1) + .toCustomedFormattedStringLocal("%Y-%m-%d %H:%M:%S") + .c_str()); + EXPECT_STREQ("2004-02-29 00:00:00.000000", + trantor::Date(2004, 2, 29) + .toCustomedFormattedStringLocal("%Y-%m-%d %H:%M:%S", true) + .c_str()); + EXPECT_STRNE("2001-02-29 00:00:00.000000", + trantor::Date(2001, 2, 29) + .toCustomedFormattedStringLocal("%Y-%m-%d %H:%M:%S", true) + .c_str()); + EXPECT_STREQ("2018-01-01 00:00:00.000000", + trantor::Date(2018, 1, 1, 12, 12, 12, 2321) + .roundDay() + .toCustomedFormattedStringLocal("%Y-%m-%d %H:%M:%S", true) + .c_str()); +} +TEST(Date, DatabaseStringTest) +{ + auto now = trantor::Date::now(); + EXPECT_EQ(now, trantor::Date::fromDbStringLocal(now.toDbStringLocal())); + std::string dbString = "2018-01-01 00:00:00.123"; + auto dbDate = trantor::Date::fromDbStringLocal(dbString); + auto ms = (dbDate.microSecondsSinceEpoch() % 1000000) / 1000; + EXPECT_EQ(ms, 123); + dbString = "2018-01-01 00:00:00"; + dbDate = trantor::Date::fromDbStringLocal(dbString); + ms = (dbDate.microSecondsSinceEpoch() % 1000000) / 1000; + EXPECT_EQ(ms, 0); +} +int main(int argc, char **argv) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/web_backends/drogon/trantor/unittests/InetAddressUnittest.cc b/web_backends/drogon/trantor/unittests/InetAddressUnittest.cc new file mode 100644 index 0000000..487ee37 --- /dev/null +++ b/web_backends/drogon/trantor/unittests/InetAddressUnittest.cc @@ -0,0 +1,22 @@ +#include +#include +#include +#include +using namespace trantor; +TEST(InetAddress, innerIpTest) +{ + EXPECT_EQ(true, InetAddress("192.168.0.1", 0).isIntranetIp()); + EXPECT_EQ(true, InetAddress("192.168.12.1", 0).isIntranetIp()); + EXPECT_EQ(true, InetAddress("10.168.0.1", 0).isIntranetIp()); + EXPECT_EQ(true, InetAddress("10.0.0.1", 0).isIntranetIp()); + EXPECT_EQ(true, InetAddress("172.31.10.1", 0).isIntranetIp()); + EXPECT_EQ(true, InetAddress("127.0.0.1", 0).isIntranetIp()); + EXPECT_EQ(true, InetAddress("example.com", 0).isUnspecified()); + EXPECT_EQ(false, InetAddress("127.0.0.2", 0).isUnspecified()); + EXPECT_EQ(false, InetAddress("0.0.0.0", 0).isUnspecified()); +} +int main(int argc, char **argv) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/web_backends/drogon/trantor/unittests/MsgBufferUnittest.cc b/web_backends/drogon/trantor/unittests/MsgBufferUnittest.cc new file mode 100644 index 0000000..9addd2c --- /dev/null +++ b/web_backends/drogon/trantor/unittests/MsgBufferUnittest.cc @@ -0,0 +1,78 @@ +#include +#include +#include +#include +using namespace trantor; +TEST(MsgBufferTest, readableTest) +{ + MsgBuffer buffer; + + EXPECT_EQ(0, buffer.readableBytes()); + buffer.append(std::string(128, 'a')); + EXPECT_EQ(128, buffer.readableBytes()); + buffer.retrieve(100); + EXPECT_EQ(28, buffer.readableBytes()); + EXPECT_EQ('a', buffer.peekInt8()); + buffer.retrieveAll(); + EXPECT_EQ(0, buffer.readableBytes()); +} +TEST(MsgBufferTest, writableTest) +{ + MsgBuffer buffer(100); + + EXPECT_EQ(100, buffer.writableBytes()); + buffer.append("abcde"); + EXPECT_EQ(95, buffer.writableBytes()); + buffer.append(std::string(100, 'x')); + EXPECT_EQ(111, buffer.writableBytes()); + buffer.retrieve(100); + EXPECT_EQ(111, buffer.writableBytes()); + buffer.append(std::string(112, 'c')); + EXPECT_EQ(99, buffer.writableBytes()); + buffer.retrieveAll(); + EXPECT_EQ(216, buffer.writableBytes()); +} + +TEST(MsgBufferTest, addInFrontTest) +{ + MsgBuffer buffer(100); + + EXPECT_EQ(100, buffer.writableBytes()); + buffer.addInFrontInt8('a'); + EXPECT_EQ(100, buffer.writableBytes()); + buffer.addInFrontInt64(123); + EXPECT_EQ(92, buffer.writableBytes()); + buffer.addInFrontInt64(100); + EXPECT_EQ(84, buffer.writableBytes()); + buffer.addInFrontInt8(1); + EXPECT_EQ(84, buffer.writableBytes()); +} + +TEST(MsgBuffer, MoveContrustor) +{ + MsgBuffer buf1(100); + const char *bufptr1 = buf1.peek(); + MsgBuffer buffnew1 = std::move(buf1); + EXPECT_EQ(bufptr1, buffnew1.peek()); + + MsgBuffer buf2(100); + const char *bufptr2 = buf2.peek(); + MsgBuffer buffnew2(std::move(buf2)); + EXPECT_EQ(bufptr2, buffnew2.peek()); +} + +TEST(Msgbuffer, MoveAssignmentOperator) +{ + MsgBuffer buf(100); + const char *bufptr = buf.peek(); + size_t writable = buf.writableBytes(); + MsgBuffer buffnew(1000); + buffnew = std::move(buf); + EXPECT_EQ(bufptr, buffnew.peek()); + EXPECT_EQ(writable, buffnew.writableBytes()); +} +int main(int argc, char **argv) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/web_backends/drogon/trantor/unittests/splitStringUnittest.cc b/web_backends/drogon/trantor/unittests/splitStringUnittest.cc new file mode 100644 index 0000000..efa64af --- /dev/null +++ b/web_backends/drogon/trantor/unittests/splitStringUnittest.cc @@ -0,0 +1,159 @@ +#include +#include +#include +#include +using namespace trantor; +TEST(splitString, ACCEPT_EMPTY_STRING1) +{ + std::string originString = "1,2,3"; + auto out = splitString(originString, ",", true); + EXPECT_EQ(out.size(), 3); +} +TEST(splitString, ACCEPT_EMPTY_STRING2) +{ + std::string originString = ",1,2,3"; + auto out = splitString(originString, ",", true); + EXPECT_EQ(out.size(), 4); + EXPECT_TRUE(out[0].empty()); +} +TEST(splitString, ACCEPT_EMPTY_STRING3) +{ + std::string originString = ",1,2,3,"; + auto out = splitString(originString, ",", true); + EXPECT_EQ(out.size(), 5); + EXPECT_TRUE(out[0].empty()); +} +TEST(splitString, ACCEPT_EMPTY_STRING4) +{ + std::string originString = ",1,2,3,"; + auto out = splitString(originString, ":", true); + EXPECT_EQ(out.size(), 1); + EXPECT_STREQ(out[0].data(), ",1,2,3,"); +} +TEST(splitString, ACCEPT_EMPTY_STRING5) +{ + std::string originString = "trantor::splitString"; + auto out = splitString(originString, "::", true); + EXPECT_EQ(out.size(), 2); + EXPECT_STREQ(out[0].data(), "trantor"); + EXPECT_STREQ(out[1].data(), "splitString"); +} +TEST(splitString, ACCEPT_EMPTY_STRING6) +{ + std::string originString = "trantor::::splitString"; + auto out = splitString(originString, "::", true); + EXPECT_EQ(out.size(), 3); + EXPECT_STREQ(out[0].data(), "trantor"); + EXPECT_STREQ(out[1].data(), ""); + EXPECT_STREQ(out[2].data(), "splitString"); +} +TEST(splitString, ACCEPT_EMPTY_STRING7) +{ + std::string originString = "trantor:::splitString"; + auto out = splitString(originString, "::", true); + EXPECT_EQ(out.size(), 2); + EXPECT_STREQ(out[0].data(), "trantor"); + EXPECT_STREQ(out[1].data(), ":splitString"); +} +TEST(splitString, ACCEPT_EMPTY_STRING8) +{ + std::string originString = "trantor:::splitString"; + auto out = splitString(originString, "trantor:::splitString", true); + EXPECT_EQ(out.size(), 2); + EXPECT_STREQ(out[0].data(), ""); + EXPECT_STREQ(out[1].data(), ""); +} +TEST(splitString, ACCEPT_EMPTY_STRING9) +{ + std::string originString = ""; + auto out = splitString(originString, ",", true); + EXPECT_EQ(out.size(), 1); + EXPECT_STREQ(out[0].data(), ""); +} +TEST(splitString, ACCEPT_EMPTY_STRING10) +{ + std::string originString = "trantor"; + auto out = splitString(originString, "", true); + EXPECT_EQ(out.size(), 0); +} +TEST(splitString, ACCEPT_EMPTY_STRING11) +{ + std::string originString = ""; + auto out = splitString(originString, "", true); + EXPECT_EQ(out.size(), 0); +} + +TEST(splitString, NO_ACCEPT_EMPTY_STRING1) +{ + std::string originString = ",1,2,3"; + auto out = splitString(originString, ","); + EXPECT_EQ(out.size(), 3); + EXPECT_STREQ(out[0].data(), "1"); +} +TEST(splitString, NO_ACCEPT_EMPTY_STRING2) +{ + std::string originString = ",1,2,3,"; + auto out = splitString(originString, ","); + EXPECT_EQ(out.size(), 3); + EXPECT_STREQ(out[0].data(), "1"); +} +TEST(splitString, NO_ACCEPT_EMPTY_STRING3) +{ + std::string originString = ",1,2,3,"; + auto out = splitString(originString, ":"); + EXPECT_EQ(out.size(), 1); + EXPECT_STREQ(out[0].data(), ",1,2,3,"); +} +TEST(splitString, NO_ACCEPT_EMPTY_STRING4) +{ + std::string originString = "trantor::splitString"; + auto out = splitString(originString, "::"); + EXPECT_EQ(out.size(), 2); + EXPECT_STREQ(out[0].data(), "trantor"); + EXPECT_STREQ(out[1].data(), "splitString"); +} +TEST(splitString, NO_ACCEPT_EMPTY_STRING5) +{ + std::string originString = "trantor::::splitString"; + auto out = splitString(originString, "::"); + EXPECT_EQ(out.size(), 2); + EXPECT_STREQ(out[0].data(), "trantor"); + EXPECT_STREQ(out[1].data(), "splitString"); +} +TEST(splitString, NO_ACCEPT_EMPTY_STRING6) +{ + std::string originString = "trantor:::splitString"; + auto out = splitString(originString, "::"); + EXPECT_EQ(out.size(), 2); + EXPECT_STREQ(out[0].data(), "trantor"); + EXPECT_STREQ(out[1].data(), ":splitString"); +} +TEST(splitString, NO_ACCEPT_EMPTY_STRING7) +{ + std::string originString = "trantor:::splitString"; + auto out = splitString(originString, "trantor:::splitString"); + EXPECT_EQ(out.size(), 0); +} +TEST(splitString, NO_ACCEPT_EMPTY_STRING8) +{ + std::string originString = ""; + auto out = splitString(originString, ","); + EXPECT_EQ(out.size(), 0); +} +TEST(splitString, NO_ACCEPT_EMPTY_STRING9) +{ + std::string originString = "trantor"; + auto out = splitString(originString, ""); + EXPECT_EQ(out.size(), 0); +} +TEST(splitString, NO_ACCEPT_EMPTY_STRING10) +{ + std::string originString = ""; + auto out = splitString(originString, ""); + EXPECT_EQ(out.size(), 0); +} +int main(int argc, char **argv) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/core/log/async_file_logger.cpp b/web_backends/drogon/trantor/utils/AsyncFileLogger.cc similarity index 75% rename from core/log/async_file_logger.cpp rename to web_backends/drogon/trantor/utils/AsyncFileLogger.cc index b7744ff..9b9b1d8 100644 --- a/core/log/async_file_logger.cpp +++ b/web_backends/drogon/trantor/utils/AsyncFileLogger.cc @@ -1,34 +1,18 @@ +/** + * + * AsyncFileLogger.cc + * An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ -// This file is originally from Trantor - AsyncFileLogger.cc - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "async_file_logger.h" +#include #ifndef _WIN32 #include #ifdef __linux__ @@ -40,9 +24,13 @@ #include #include +namespace trantor { static constexpr std::chrono::seconds kLogFlushTimeout{ 1 }; static constexpr size_t kMemBufferSize{ 4 * 1024 * 1024 }; extern const char *strerror_tl(int savedErrno); +} // namespace trantor + +using namespace trantor; AsyncFileLogger::AsyncFileLogger() : logBufferPtr_(new std::string), nextBufferPtr_(new std::string) { diff --git a/web_backends/drogon/trantor/utils/AsyncFileLogger.h b/web_backends/drogon/trantor/utils/AsyncFileLogger.h new file mode 100644 index 0000000..0f54c67 --- /dev/null +++ b/web_backends/drogon/trantor/utils/AsyncFileLogger.h @@ -0,0 +1,140 @@ +/** + * + * @file AsyncFileLogger.h + * @author An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace trantor +{ +using StringPtr = std::shared_ptr; +using StringPtrQueue = std::queue; + +/** + * @brief This class implements utility functions for writing logs to files + * asynchronously. + * + */ +class TRANTOR_EXPORT AsyncFileLogger : NonCopyable +{ + public: + /** + * @brief Write the message to the log file. + * + * @param msg + * @param len + */ + void output(const char *msg, const uint64_t len); + + /** + * @brief Flush data from memory buffer to the log file. + * + */ + void flush(); + + /** + * @brief Start writing log files. + * + */ + void startLogging(); + + /** + * @brief Set the size limit of log files. When the log file size reaches + * the limit, the log file is switched. + * + * @param limit + */ + void setFileSizeLimit(uint64_t limit) + { + sizeLimit_ = limit; + } + + /** + * @brief Set the log file name. + * + * @param baseName The base name of the log file. + * @param extName The extended name of the log file. + * @param path The location where the log file is stored. + */ + void setFileName(const std::string &baseName, + const std::string &extName = ".log", + const std::string &path = "./") + { + fileBaseName_ = baseName; + extName[0] == '.' ? fileExtName_ = extName + : fileExtName_ = std::string(".") + extName; + filePath_ = path; + if (filePath_.length() == 0) + filePath_ = "./"; + if (filePath_[filePath_.length() - 1] != '/') + filePath_ = filePath_ + "/"; + } + ~AsyncFileLogger(); + AsyncFileLogger(); + + protected: + std::mutex mutex_; + std::condition_variable cond_; + StringPtr logBufferPtr_; + StringPtr nextBufferPtr_; + StringPtrQueue writeBuffers_; + StringPtrQueue tmpBuffers_; + void writeLogToFile(const StringPtr buf); + std::unique_ptr threadPtr_; + bool stopFlag_{false}; + void logThreadFunc(); + std::string filePath_{"./"}; + std::string fileBaseName_{"trantor"}; + std::string fileExtName_{".log"}; + uint64_t sizeLimit_{20 * 1024 * 1024}; + class LoggerFile : NonCopyable + { + public: + LoggerFile(const std::string &filePath, + const std::string &fileBaseName, + const std::string &fileExtName); + ~LoggerFile(); + void writeLog(const StringPtr buf); + uint64_t getLength(); + explicit operator bool() const + { + return fp_ != nullptr; + } + void flush(); + + protected: + FILE *fp_{nullptr}; + Date creationDate_; + std::string fileFullName_; + std::string filePath_; + std::string fileBaseName_; + std::string fileExtName_; + static uint64_t fileSeq_; + }; + std::unique_ptr loggerFilePtr_; + + uint64_t lostCounter_{0}; + void swapBuffer(); +}; + +} // namespace trantor diff --git a/core/containers/concurrent_task_queue.cpp b/web_backends/drogon/trantor/utils/ConcurrentTaskQueue.cc similarity index 50% rename from core/containers/concurrent_task_queue.cpp rename to web_backends/drogon/trantor/utils/ConcurrentTaskQueue.cc index 0ceaa4a..3f44468 100644 --- a/core/containers/concurrent_task_queue.cpp +++ b/web_backends/drogon/trantor/utils/ConcurrentTaskQueue.cc @@ -1,40 +1,24 @@ +/** + * + * ConcurrentTaskQueue.cc + * An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ -// This file is originally from Trantor - ConcurrentTaskQueue.cc - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "concurrent_task_queue.h" -#include "core/log/logger.h" #include +#include +#include #ifdef __linux__ #include #endif - +using namespace trantor; ConcurrentTaskQueue::ConcurrentTaskQueue(size_t threadNum, const std::string &name) : queueCount_(threadNum), queueName_(name), stop_(false) { diff --git a/web_backends/drogon/trantor/utils/ConcurrentTaskQueue.h b/web_backends/drogon/trantor/utils/ConcurrentTaskQueue.h new file mode 100644 index 0000000..bcde18c --- /dev/null +++ b/web_backends/drogon/trantor/utils/ConcurrentTaskQueue.h @@ -0,0 +1,89 @@ +/** + * + * @file ConcurrentTaskQueue.h + * @author An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace trantor +{ +/** + * @brief This class implements a task queue running in parallel. Basically this + * can be called a threads pool. + * + */ +class TRANTOR_EXPORT ConcurrentTaskQueue : public TaskQueue +{ + public: + /** + * @brief Construct a new concurrent task queue instance. + * + * @param threadNum The number of threads in the queue. + * @param name The name of the queue. + */ + ConcurrentTaskQueue(size_t threadNum, const std::string &name); + + /** + * @brief Run a task in the queue. + * + * @param task + */ + virtual void runTaskInQueue(const std::function &task); + virtual void runTaskInQueue(std::function &&task); + + /** + * @brief Get the name of the queue. + * + * @return std::string + */ + virtual std::string getName() const + { + return queueName_; + }; + + /** + * @brief Get the number of tasks to be executed in the queue. + * + * @return size_t + */ + size_t getTaskCount(); + + /** + * @brief Stop all threads in the queue. + * + */ + void stop(); + + ~ConcurrentTaskQueue(); + + private: + size_t queueCount_; + std::string queueName_; + + std::queue> taskQueue_; + std::vector threads_; + + std::mutex taskMutex_; + std::condition_variable taskCond_; + std::atomic_bool stop_; + void queueFunc(int queueNum); +}; + +} // namespace trantor diff --git a/core/math/date.cpp b/web_backends/drogon/trantor/utils/Date.cc similarity index 79% rename from core/math/date.cpp rename to web_backends/drogon/trantor/utils/Date.cc index 70e7cc6..f025dec 100644 --- a/core/math/date.cpp +++ b/web_backends/drogon/trantor/utils/Date.cc @@ -1,35 +1,19 @@ +/** + * + * Date.cc + * An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ -// This file is originally from Trantor - Date.cc - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "date.h" -#include "core/utilities.h" +#include "Date.h" +#include "Funcs.h" #ifndef _WIN32 #include #endif @@ -41,6 +25,7 @@ #include #endif +namespace trantor { #ifdef _WIN32 int gettimeofday(timeval *tp, void *tzp) { time_t clock; @@ -268,19 +253,19 @@ std::string Date::toDbStringLocal() const { Date Date::fromDbStringLocal(const std::string &datetime) { unsigned int year = { 0 }, month = { 0 }, day = { 0 }, hour = { 0 }, minute = { 0 }, second = { 0 }, microSecond = { 0 }; - std::vector &&v = Utilities::splitString(datetime, " "); + std::vector &&v = splitString(datetime, " "); if (2 == v.size()) { // date - std::vector date = Utilities::splitString(v[0], "-"); + std::vector date = splitString(v[0], "-"); if (3 == date.size()) { year = std::stol(date[0]); month = std::stol(date[1]); day = std::stol(date[2]); - std::vector time = Utilities::splitString(v[1], ":"); + std::vector time = splitString(v[1], ":"); if (2 < time.size()) { hour = std::stol(time[0]); minute = std::stol(time[1]); - auto seconds = Utilities::splitString(time[2], "."); + auto seconds = splitString(time[2], "."); second = std::stol(seconds[0]); if (1 < seconds.size()) { if (seconds[1].length() > 6) { @@ -294,7 +279,7 @@ Date Date::fromDbStringLocal(const std::string &datetime) { } } return std::move( - Date(year, month, day, hour, minute, second, microSecond)); + trantor::Date(year, month, day, hour, minute, second, microSecond)); } std::string Date::toCustomedFormattedStringLocal(const std::string &fmtStr, bool showMicroseconds) const { @@ -336,3 +321,5 @@ Date::Date(unsigned int year, epoch = mktime(&tm); microSecondsSinceEpoch_ = epoch * MICRO_SECONDS_PRE_SEC + microSecond; } + +} // namespace trantor diff --git a/core/math/date.h b/web_backends/drogon/trantor/utils/Date.h similarity index 80% rename from core/math/date.h rename to web_backends/drogon/trantor/utils/Date.h index f99a01c..8543a2d 100644 --- a/core/math/date.h +++ b/web_backends/drogon/trantor/utils/Date.h @@ -1,45 +1,32 @@ - -// This file is originally from Trantor - Date.h - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/** + * + * @file Date.h + * @author An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ #pragma once +#include #include #include #define MICRO_SECONDS_PRE_SEC 1000000 +namespace trantor +{ /** * @brief This class represents a time point. * */ -class Date +class TRANTOR_EXPORT Date { public: Date() : microSecondsSinceEpoch_(0){}; @@ -291,3 +278,4 @@ class Date private: int64_t microSecondsSinceEpoch_{0}; }; +} // namespace trantor diff --git a/web_backends/drogon/trantor/utils/Funcs.h b/web_backends/drogon/trantor/utils/Funcs.h new file mode 100644 index 0000000..444fe27 --- /dev/null +++ b/web_backends/drogon/trantor/utils/Funcs.h @@ -0,0 +1,56 @@ +/** + * + * Funcs.h + * An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#pragma once +#include +#include +#include +#include + +namespace trantor +{ +inline uint64_t hton64(uint64_t n) +{ + static const int one = 1; + static const char sig = *(char *)&one; + if (sig == 0) + return n; // for big endian machine just return the input + char *ptr = reinterpret_cast(&n); + std::reverse(ptr, ptr + sizeof(uint64_t)); + return n; +} +inline uint64_t ntoh64(uint64_t n) +{ + return hton64(n); +} +inline std::vector splitString(const std::string &s, + const std::string &delimiter, + bool acceptEmptyString = false) +{ + if (delimiter.empty()) + return std::vector{}; + std::vector v; + size_t last = 0; + size_t next = 0; + while ((next = s.find(delimiter, last)) != std::string::npos) + { + if (next > last || acceptEmptyString) + v.push_back(s.substr(last, next - last)); + last = next + delimiter.length(); + } + if (s.length() > last || acceptEmptyString) + v.push_back(s.substr(last)); + return v; +} +} // namespace trantor diff --git a/web_backends/drogon/trantor/utils/LockFreeQueue.h b/web_backends/drogon/trantor/utils/LockFreeQueue.h new file mode 100644 index 0000000..f608a90 --- /dev/null +++ b/web_backends/drogon/trantor/utils/LockFreeQueue.h @@ -0,0 +1,114 @@ +/** + * + * @file LockFreeQueue.h + * @author An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#pragma once +#include +#include +#include +#include +#include +namespace trantor +{ +/** + * @brief This class template represents a lock-free multiple producers single + * consumer queue + * + * @tparam T The type of the items in the queue. + */ +template +class MpscQueue : public NonCopyable +{ + public: + MpscQueue() + : head_(new BufferNode), tail_(head_.load(std::memory_order_relaxed)) + { + } + ~MpscQueue() + { + T output; + while (this->dequeue(output)) + { + } + BufferNode *front = head_.load(std::memory_order_relaxed); + delete front; + } + + /** + * @brief Put a item into the queue. + * + * @param input + * @note This method can be called in multiple threads. + */ + void enqueue(T &&input) + { + BufferNode *node{new BufferNode(std::move(input))}; + BufferNode *prevhead{head_.exchange(node, std::memory_order_acq_rel)}; + prevhead->next_.store(node, std::memory_order_release); + } + void enqueue(const T &input) + { + BufferNode *node{new BufferNode(input)}; + BufferNode *prevhead{head_.exchange(node, std::memory_order_acq_rel)}; + prevhead->next_.store(node, std::memory_order_release); + } + + /** + * @brief Get a item from the queue. + * + * @param output + * @return false if the queue is empty. + * @note This method must be called in a single thread. + */ + bool dequeue(T &output) + { + BufferNode *tail = tail_.load(std::memory_order_relaxed); + BufferNode *next = tail->next_.load(std::memory_order_acquire); + + if (next == nullptr) + { + return false; + } + output = std::move(*(next->dataPtr_)); + delete next->dataPtr_; + tail_.store(next, std::memory_order_release); + delete tail; + return true; + } + + bool empty() + { + BufferNode *tail = tail_.load(std::memory_order_relaxed); + BufferNode *next = tail->next_.load(std::memory_order_acquire); + return next == nullptr; + } + + private: + struct BufferNode + { + BufferNode() = default; + BufferNode(const T &data) : dataPtr_(new T(data)) + { + } + BufferNode(T &&data) : dataPtr_(new T(std::move(data))) + { + } + T *dataPtr_; + std::atomic next_{nullptr}; + }; + + std::atomic head_; + std::atomic tail_; +}; + +} // namespace trantor diff --git a/core/log/log_stream.cpp b/web_backends/drogon/trantor/utils/LogStream.cc similarity index 67% rename from core/log/log_stream.cpp rename to web_backends/drogon/trantor/utils/LogStream.cc index 12afd16..4cef841 100644 --- a/core/log/log_stream.cpp +++ b/web_backends/drogon/trantor/utils/LogStream.cc @@ -1,45 +1,32 @@ +/** + * + * LogStream.cc + * An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ -// This file is originally from Moduo -> Trantor - LogStream.cc - -// Copyright (c) 2016-2021, Tao An. All rights reserved. -// Copyright (c) 2010, Shuo Chen. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// taken from muduo lib #include #include #include #include -#include "log_stream.h" +#include #include #include #include -using namespace detail; +using namespace trantor; +using namespace trantor::detail; +namespace trantor { namespace detail { const char digits[] = "9876543210123456789"; const char *zero = digits + 9; @@ -87,6 +74,7 @@ template class FixedBuffer; template class FixedBuffer; } // namespace detail +} // namespace trantor template const char *FixedBuffer::debugString() { @@ -231,16 +219,16 @@ Fmt::Fmt(const char *fmt, T val) { // Explicit instantiations -template Fmt::Fmt(const char *fmt, char); +template TRANTOR_EXPORT Fmt::Fmt(const char *fmt, char); -template Fmt::Fmt(const char *fmt, short); -template Fmt::Fmt(const char *fmt, unsigned short); -template Fmt::Fmt(const char *fmt, int); -template Fmt::Fmt(const char *fmt, unsigned int); -template Fmt::Fmt(const char *fmt, long); -template Fmt::Fmt(const char *fmt, unsigned long); -template Fmt::Fmt(const char *fmt, long long); -template Fmt::Fmt(const char *fmt, unsigned long long); +template TRANTOR_EXPORT Fmt::Fmt(const char *fmt, short); +template TRANTOR_EXPORT Fmt::Fmt(const char *fmt, unsigned short); +template TRANTOR_EXPORT Fmt::Fmt(const char *fmt, int); +template TRANTOR_EXPORT Fmt::Fmt(const char *fmt, unsigned int); +template TRANTOR_EXPORT Fmt::Fmt(const char *fmt, long); +template TRANTOR_EXPORT Fmt::Fmt(const char *fmt, unsigned long); +template TRANTOR_EXPORT Fmt::Fmt(const char *fmt, long long); +template TRANTOR_EXPORT Fmt::Fmt(const char *fmt, unsigned long long); -template Fmt::Fmt(const char *fmt, float); -template Fmt::Fmt(const char *fmt, double); +template TRANTOR_EXPORT Fmt::Fmt(const char *fmt, float); +template TRANTOR_EXPORT Fmt::Fmt(const char *fmt, double); diff --git a/web_backends/drogon/trantor/utils/LogStream.h b/web_backends/drogon/trantor/utils/LogStream.h new file mode 100644 index 0000000..d668434 --- /dev/null +++ b/web_backends/drogon/trantor/utils/LogStream.h @@ -0,0 +1,277 @@ +/** + * + * @file LogStream.h + * @author An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#pragma once + +// Taken from muduo lib and modified. Classes in this file are used internally. +#include +#include + +#include +#include // memcpy +#include + +namespace trantor +{ +namespace detail +{ +static constexpr size_t kSmallBuffer{4000}; +static constexpr size_t kLargeBuffer{4000 * 1000}; + +template +class TRANTOR_EXPORT FixedBuffer : NonCopyable +{ + public: + FixedBuffer() : cur_(data_) + { + setCookie(cookieStart); + } + + ~FixedBuffer() + { + setCookie(cookieEnd); + } + + bool append(const char * /*restrict*/ buf, size_t len) + { + if ((size_t)(avail()) > len) + { + memcpy(cur_, buf, len); + cur_ += len; + return true; + } + return false; + } + + const char *data() const + { + return data_; + } + int length() const + { + return static_cast(cur_ - data_); + } + + // write to data_ directly + char *current() + { + return cur_; + } + int avail() const + { + return static_cast(end() - cur_); + } + void add(size_t len) + { + cur_ += len; + } + + void reset() + { + cur_ = data_; + } + void zeroBuffer() + { + memset(data_, 0, sizeof(data_)); + } + + // for used by GDB + const char *debugString(); + void setCookie(void (*cookie)()) + { + cookie_ = cookie; + } + // for used by unit test + std::string toString() const + { + return std::string(data_, length()); + } + // StringPiece toStringPiece() const { return StringPiece(data_, length()); + // } + + private: + const char *end() const + { + return data_ + sizeof data_; + } + // Must be outline function for cookies. + static void cookieStart(); + static void cookieEnd(); + + void (*cookie_)(); + char data_[SIZE]; + char *cur_; +}; + +} // namespace detail + +class TRANTOR_EXPORT LogStream : NonCopyable +{ + using self = LogStream; + + public: + using Buffer = detail::FixedBuffer; + + self &operator<<(bool v) + { + append(v ? "1" : "0", 1); + return *this; + } + + self &operator<<(short); + self &operator<<(unsigned short); + self &operator<<(int); + self &operator<<(unsigned int); + self &operator<<(long); + self &operator<<(unsigned long); + self &operator<<(const long long &); + self &operator<<(const unsigned long long &); + + self &operator<<(const void *); + + self &operator<<(float &v) + { + *this << static_cast(v); + return *this; + } + self &operator<<(const double &); + self &operator<<(const long double &v); + + self &operator<<(char v) + { + append(&v, 1); + return *this; + } + + // self& operator<<(signed char); + // self& operator<<(unsigned char); + template + self &operator<<(const char (&buf)[N]) + { + assert(strnlen(buf, N) == N - 1); + append(buf, N - 1); + return *this; + } + + self &operator<<(char *str) + { + if (str) + { + append(str, strlen(str)); + } + else + { + append("(null)", 6); + } + return *this; + } + + self &operator<<(const char *str) + { + if (str) + { + append(str, strlen(str)); + } + else + { + append("(null)", 6); + } + return *this; + } + + self &operator<<(const unsigned char *str) + { + return operator<<(reinterpret_cast(str)); + } + + self &operator<<(const std::string &v) + { + append(v.c_str(), v.size()); + return *this; + } + + void append(const char *data, size_t len) + { + if (exBuffer_.empty()) + { + if (!buffer_.append(data, len)) + { + exBuffer_.append(buffer_.data(), buffer_.length()); + exBuffer_.append(data, len); + } + } + else + { + exBuffer_.append(data, len); + } + } + // const Buffer& buffer() const { return buffer_; } + const char *bufferData() const + { + if (!exBuffer_.empty()) + { + return exBuffer_.data(); + } + return buffer_.data(); + } + + size_t bufferLength() const + { + if (!exBuffer_.empty()) + { + return exBuffer_.length(); + } + return buffer_.length(); + } + void resetBuffer() + { + buffer_.reset(); + exBuffer_.clear(); + } + + private: + template + void formatInteger(T); + + Buffer buffer_; + std::string exBuffer_; +}; + +class TRANTOR_EXPORT Fmt // : boost::noncopyable +{ + public: + template + Fmt(const char *fmt, T val); + + const char *data() const + { + return buf_; + } + int length() const + { + return length_; + } + + private: + char buf_[48]; + int length_; +}; + +inline LogStream &operator<<(LogStream &s, const Fmt &fmt) +{ + s.append(fmt.data(), fmt.length()); + return s; +} + +} // namespace trantor diff --git a/web_backends/drogon/trantor/utils/Logger.cc b/web_backends/drogon/trantor/utils/Logger.cc new file mode 100644 index 0000000..90e30d3 --- /dev/null +++ b/web_backends/drogon/trantor/utils/Logger.cc @@ -0,0 +1,187 @@ +/** + * + * Logger.cc + * An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#include +#include +#include +#ifndef _WIN32 +#include +#include +#else +#include +#endif +#ifdef __FreeBSD__ +#include +#endif + +namespace trantor { +// helper class for known string length at compile time +class T { +public: + T(const char *str, unsigned len) : + str_(str), len_(len) { + assert(strlen(str) == len_); + } + + const char *str_; + const unsigned len_; +}; + +const char *strerror_tl(int savedErrno) { +#ifndef _MSC_VER + return strerror(savedErrno); +#else + static thread_local char errMsg[64]; + (void)strerror_s(errMsg, savedErrno); + return errMsg; +#endif +} + +inline LogStream &operator<<(LogStream &s, T v) { + s.append(v.str_, v.len_); + return s; +} + +inline LogStream &operator<<(LogStream &s, const Logger::SourceFile &v) { + s.append(v.data_, v.size_); + return s; +} +} // namespace trantor +using namespace trantor; + +static thread_local uint64_t lastSecond_{ 0 }; +static thread_local char lastTimeString_[32] = { 0 }; +#ifdef __linux__ +static thread_local pid_t threadId_{ 0 }; +#else +static thread_local uint64_t threadId_{ 0 }; +#endif +// static thread_local LogStream logStream_; + +void Logger::formatTime() { + uint64_t now = static_cast(date_.secondsSinceEpoch()); + uint64_t microSec = + static_cast(date_.microSecondsSinceEpoch() - + date_.roundSecond().microSecondsSinceEpoch()); + if (now != lastSecond_) { + lastSecond_ = now; +#ifndef _MSC_VER + strncpy(lastTimeString_, + date_.toFormattedString(false).c_str(), + sizeof(lastTimeString_) - 1); +#else + strncpy_s( + lastTimeString_, + date_.toFormattedString(false).c_str(), + sizeof(lastTimeString_) - 1); +#endif + } + logStream_ << T(lastTimeString_, 17); + char tmp[32]; + snprintf(tmp, + sizeof(tmp), + ".%06llu UTC ", + static_cast(microSec)); + logStream_ << T(tmp, 12); +#ifdef __linux__ + if (threadId_ == 0) + threadId_ = static_cast(::syscall(SYS_gettid)); +#elif defined __FreeBSD__ + if (threadId_ == 0) { + threadId_ = pthread_getthreadid_np(); + } +#elif defined __OpenBSD__ + if (threadId_ == 0) { + threadId_ = getthrid(); + } +#elif defined _WIN32 + if (threadId_ == 0) { + std::stringstream ss; + ss << std::this_thread::get_id(); + threadId_ = std::stoull(ss.str()); + } +#else + if (threadId_ == 0) { + pthread_threadid_np(NULL, &threadId_); + } +#endif + logStream_ << threadId_; +} +static const char *logLevelStr[Logger::LogLevel::kNumberOfLogLevels] = { + " TRACE ", + " DEBUG ", + " INFO ", + " WARN ", + " ERROR ", + " FATAL ", +}; +Logger::Logger(SourceFile file, int line) : + sourceFile_(file), fileLine_(line), level_(kInfo) { + formatTime(); + logStream_ << T(logLevelStr[level_], 7); +} +Logger::Logger(SourceFile file, int line, LogLevel level) : + sourceFile_(file), fileLine_(line), level_(level) { + formatTime(); + logStream_ << T(logLevelStr[level_], 7); +} +Logger::Logger(SourceFile file, int line, LogLevel level, const char *func) : + sourceFile_(file), fileLine_(line), level_(level) { + formatTime(); + logStream_ << T(logLevelStr[level_], 7) << "[" << func << "] "; +} +Logger::Logger(SourceFile file, int line, bool) : + sourceFile_(file), fileLine_(line), level_(kFatal) { + formatTime(); + logStream_ << T(logLevelStr[level_], 7); + if (errno != 0) { + logStream_ << strerror_tl(errno) << " (errno=" << errno << ") "; + } +} +RawLogger::~RawLogger() { + if (index_ < 0) { + auto &oFunc = Logger::outputFunc_(); + if (!oFunc) + return; + oFunc(logStream_.bufferData(), logStream_.bufferLength()); + } else { + auto &oFunc = Logger::outputFunc_(index_); + if (!oFunc) + return; + oFunc(logStream_.bufferData(), logStream_.bufferLength()); + } +} +Logger::~Logger() { + logStream_ << T(" - ", 3) << sourceFile_ << ':' << fileLine_ << '\n'; + if (index_ < 0) { + auto &oFunc = Logger::outputFunc_(); + if (!oFunc) + return; + oFunc(logStream_.bufferData(), logStream_.bufferLength()); + if (level_ >= kError) + Logger::flushFunc_()(); + } else { + auto &oFunc = Logger::outputFunc_(index_); + if (!oFunc) + return; + oFunc(logStream_.bufferData(), logStream_.bufferLength()); + if (level_ >= kError) + Logger::flushFunc_(index_)(); + } + + // logStream_.resetBuffer(); +} +LogStream &Logger::stream() { + return logStream_; +} diff --git a/web_backends/drogon/trantor/utils/Logger.h b/web_backends/drogon/trantor/utils/Logger.h new file mode 100644 index 0000000..ddb6100 --- /dev/null +++ b/web_backends/drogon/trantor/utils/Logger.h @@ -0,0 +1,383 @@ +/** + * + * @file Logger.h + * @author An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace trantor +{ +/** + * @brief This class implements log functions. + * + */ +class TRANTOR_EXPORT Logger : public NonCopyable +{ + public: + enum LogLevel + { + kTrace = 0, + kDebug, + kInfo, + kWarn, + kError, + kFatal, + kNumberOfLogLevels + }; + + /** + * @brief Calculate of basename of source files in compile time. + * + */ + class SourceFile + { + public: + template + inline SourceFile(const char (&arr)[N]) : data_(arr), size_(N - 1) + { + // std::cout<(data_ - arr); + } + } + + explicit SourceFile(const char *filename) : data_(filename) + { + const char *slash = strrchr(filename, '/'); + if (slash) + { + data_ = slash + 1; + } + size_ = static_cast(strlen(data_)); + } + + const char *data_; + int size_; + }; + Logger(SourceFile file, int line); + Logger(SourceFile file, int line, LogLevel level); + Logger(SourceFile file, int line, bool isSysErr); + Logger(SourceFile file, int line, LogLevel level, const char *func); + ~Logger(); + Logger &setIndex(int index) + { + index_ = index; + return *this; + } + LogStream &stream(); + + /** + * @brief Set the output function. + * + * @param outputFunc The function to output a log message. + * @param flushFunc The function to flush. + * @note Logs are output to the standard output by default. + */ + static void setOutputFunction( + std::function outputFunc, + std::function flushFunc, + int index = -1) + { + if (index < 0) + { + outputFunc_() = outputFunc; + flushFunc_() = flushFunc; + } + else + { + outputFunc_(index) = outputFunc; + flushFunc_(index) = flushFunc; + } + } + + /** + * @brief Set the log level. Logs below the level are not printed. + * + * @param level + */ + static void setLogLevel(LogLevel level) + { + logLevel_() = level; + } + + /** + * @brief Get the current log level. + * + * @return LogLevel + */ + static LogLevel logLevel() + { + return logLevel_(); + } + + protected: + static void defaultOutputFunction(const char *msg, const uint64_t len) + { + fwrite(msg, 1, len, stdout); + } + static void defaultFlushFunction() + { + fflush(stdout); + } + void formatTime(); + static LogLevel &logLevel_() + { +#ifdef RELEASE + static LogLevel logLevel = LogLevel::kInfo; +#else + static LogLevel logLevel = LogLevel::kDebug; +#endif + return logLevel; + } + static std::function + &outputFunc_() + { + static std::function + outputFunc = Logger::defaultOutputFunction; + return outputFunc; + } + static std::function &flushFunc_() + { + static std::function flushFunc = Logger::defaultFlushFunction; + return flushFunc; + } + static std::function + &outputFunc_(size_t index) + { + static std::vector< + std::function> + outputFuncs; + if (index < outputFuncs.size()) + { + return outputFuncs[index]; + } + while (index >= outputFuncs.size()) + { + outputFuncs.emplace_back(outputFunc_()); + } + return outputFuncs[index]; + } + static std::function &flushFunc_(size_t index) + { + static std::vector> flushFuncs; + if (index < flushFuncs.size()) + { + return flushFuncs[index]; + } + while (index >= flushFuncs.size()) + { + flushFuncs.emplace_back(flushFunc_()); + } + return flushFuncs[index]; + } + friend class RawLogger; + LogStream logStream_; + Date date_{Date::now()}; + SourceFile sourceFile_; + int fileLine_; + LogLevel level_; + int index_{-1}; +}; +class TRANTOR_EXPORT RawLogger : public NonCopyable +{ + public: + ~RawLogger(); + RawLogger &setIndex(int index) + { + index_ = index; + return *this; + } + LogStream &stream() + { + return logStream_; + } + + private: + LogStream logStream_; + int index_{-1}; +}; +#ifdef NDEBUG +#define LOG_TRACE \ + if (0) \ + trantor::Logger(__FILE__, __LINE__, trantor::Logger::kTrace, __func__) \ + .stream() +#else +#define LOG_TRACE \ + if (trantor::Logger::logLevel() <= trantor::Logger::kTrace) \ + trantor::Logger(__FILE__, __LINE__, trantor::Logger::kTrace, __func__) \ + .stream() +#define LOG_TRACE_TO(index) \ + if (trantor::Logger::logLevel() <= trantor::Logger::kTrace) \ + trantor::Logger(__FILE__, __LINE__, trantor::Logger::kTrace, __func__) \ + .setIndex(index) \ + .stream() + +#endif + +#define LOG_DEBUG \ + if (trantor::Logger::logLevel() <= trantor::Logger::kDebug) \ + trantor::Logger(__FILE__, __LINE__, trantor::Logger::kDebug, __func__) \ + .stream() +#define LOG_DEBUG_TO(index) \ + if (trantor::Logger::logLevel() <= trantor::Logger::kDebug) \ + trantor::Logger(__FILE__, __LINE__, trantor::Logger::kDebug, __func__) \ + .setIndex(index) \ + .stream() +#define LOG_INFO \ + if (trantor::Logger::logLevel() <= trantor::Logger::kInfo) \ + trantor::Logger(__FILE__, __LINE__).stream() +#define LOG_INFO_TO(index) \ + if (trantor::Logger::logLevel() <= trantor::Logger::kInfo) \ + trantor::Logger(__FILE__, __LINE__).setIndex(index).stream() +#define LOG_WARN \ + trantor::Logger(__FILE__, __LINE__, trantor::Logger::kWarn).stream() +#define LOG_WARN_TO(index) \ + trantor::Logger(__FILE__, __LINE__, trantor::Logger::kWarn) \ + .setIndex(index) \ + .stream() +#define LOG_ERROR \ + trantor::Logger(__FILE__, __LINE__, trantor::Logger::kError).stream() +#define LOG_ERROR_TO(index) \ + trantor::Logger(__FILE__, __LINE__, trantor::Logger::kError) \ + .setIndex(index) \ + .stream() +#define LOG_FATAL \ + trantor::Logger(__FILE__, __LINE__, trantor::Logger::kFatal).stream() +#define LOG_FATAL_TO(index) \ + trantor::Logger(__FILE__, __LINE__, trantor::Logger::kFatal) \ + .setIndex(index) \ + .stream() +#define LOG_SYSERR trantor::Logger(__FILE__, __LINE__, true).stream() +#define LOG_SYSERR_TO(index) \ + trantor::Logger(__FILE__, __LINE__, true).setIndex(index).stream() + +#define LOG_RAW trantor::RawLogger().stream() +#define LOG_RAW_TO(index) trantor::RawLogger().setIndex(index).stream() + +#define LOG_TRACE_IF(cond) \ + if ((trantor::Logger::logLevel() <= trantor::Logger::kTrace) && (cond)) \ + trantor::Logger(__FILE__, __LINE__, trantor::Logger::kTrace, __func__) \ + .stream() +#define LOG_DEBUG_IF(cond) \ + if ((Tensor::Logger::logLevel() <= Tensor::Logger::kDebug) && (cond)) \ + Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kDebug, __func__) \ + .stream() +#define LOG_INFO_IF(cond) \ + if ((Tensor::Logger::logLevel() <= Tensor::Logger::kInfo) && (cond)) \ + Tensor::Logger(__FILE__, __LINE__).stream() +#define LOG_WARN_IF(cond) \ + if (cond) \ + Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kWarn).stream() +#define LOG_ERROR_IF(cond) \ + if (cond) \ + Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kError).stream() +#define LOG_FATAL_IF(cond) \ + if (cond) \ + Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kFatal).stream() + +#ifdef NDEBUG +#define DLOG_TRACE \ + if (0) \ + trantor::Logger(__FILE__, __LINE__, trantor::Logger::kTrace, __func__) \ + .stream() +#define DLOG_DEBUG \ + if (0) \ + Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kDebug, __func__) \ + .stream() +#define DLOG_INFO \ + if (0) \ + Tensor::Logger(__FILE__, __LINE__).stream() +#define DLOG_WARN \ + if (0) \ + Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kWarn).stream() +#define DLOG_ERROR \ + if (0) \ + Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kError).stream() +#define DLOG_FATAL \ + if (0) \ + Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kFatal).stream() + +#define DLOG_TRACE_IF(cond) \ + if (0) \ + trantor::Logger(__FILE__, __LINE__, trantor::Logger::kTrace, __func__) \ + .stream() +#define DLOG_DEBUG_IF(cond) \ + if (0) \ + Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kDebug, __func__) \ + .stream() +#define DLOG_INFO_IF(cond) \ + if (0) \ + Tensor::Logger(__FILE__, __LINE__).stream() +#define DLOG_WARN_IF(cond) \ + if (0) \ + Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kWarn).stream() +#define DLOG_ERROR_IF(cond) \ + if (0) \ + Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kError).stream() +#define DLOG_FATAL_IF(cond) \ + if (0) \ + Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kFatal).stream() +#else +#define DLOG_TRACE \ + if (trantor::Logger::logLevel() <= trantor::Logger::kTrace) \ + trantor::Logger(__FILE__, __LINE__, trantor::Logger::kTrace, __func__) \ + .stream() +#define DLOG_DEBUG \ + if (Tensor::Logger::logLevel() <= Tensor::Logger::kDebug) \ + Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kDebug, __func__) \ + .stream() +#define DLOG_INFO \ + if (Tensor::Logger::logLevel() <= Tensor::Logger::kInfo) \ + Tensor::Logger(__FILE__, __LINE__).stream() +#define DLOG_WARN \ + Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kWarn).stream() +#define DLOG_ERROR \ + Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kError).stream() +#define DLOG_FATAL \ + Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kFatal).stream() + +#define DLOG_TRACE_IF(cond) \ + if ((trantor::Logger::logLevel() <= trantor::Logger::kTrace) && (cond)) \ + trantor::Logger(__FILE__, __LINE__, trantor::Logger::kTrace, __func__) \ + .stream() +#define DLOG_DEBUG_IF(cond) \ + if ((Tensor::Logger::logLevel() <= Tensor::Logger::kDebug) && (cond)) \ + Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kDebug, __func__) \ + .stream() +#define DLOG_INFO_IF(cond) \ + if ((Tensor::Logger::logLevel() <= Tensor::Logger::kInfo) && (cond)) \ + Tensor::Logger(__FILE__, __LINE__).stream() +#define DLOG_WARN_IF(cond) \ + if (cond) \ + Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kWarn).stream() +#define DLOG_ERROR_IF(cond) \ + if (cond) \ + Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kError).stream() +#define DLOG_FATAL_IF(cond) \ + if (cond) \ + Tensor::Logger(__FILE__, __LINE__, Tensor::Logger::kFatal).stream() +#endif + +const char *strerror_tl(int savedErrno); +} // namespace trantor diff --git a/core/containers/msg_buffer.cpp b/web_backends/drogon/trantor/utils/MsgBuffer.cc similarity index 72% rename from core/containers/msg_buffer.cpp rename to web_backends/drogon/trantor/utils/MsgBuffer.cc index b72fb19..c23535d 100644 --- a/core/containers/msg_buffer.cpp +++ b/web_backends/drogon/trantor/utils/MsgBuffer.cc @@ -1,37 +1,20 @@ - -// This file is originally from Trantor - MsgBuffer.cc - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "msg_buffer.h" +/** + * + * MsgBuffer.cc + * An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ #include -#include "core/math/math.h" +#include +#include #ifndef _WIN32 #include #include @@ -42,7 +25,10 @@ #include #include +using namespace trantor; +namespace trantor { static constexpr size_t kBufferOffset{ 8 }; +} MsgBuffer::MsgBuffer(size_t len) : head_(kBufferOffset), initCap_(len), buffer_(len + head_), tail_(head_) { @@ -94,7 +80,7 @@ void MsgBuffer::appendInt32(const uint32_t i) { append(static_cast((void *)&ii), 4); } void MsgBuffer::appendInt64(const uint64_t l) { - uint64_t ll = Math::hton64(l); + uint64_t ll = hton64(l); append(static_cast((void *)&ll), 8); } @@ -107,7 +93,7 @@ void MsgBuffer::addInFrontInt32(const uint32_t i) { addInFront(static_cast((void *)&ii), 4); } void MsgBuffer::addInFrontInt64(const uint64_t l) { - uint64_t ll = Math::hton64(l); + uint64_t ll = hton64(l); addInFront(static_cast((void *)&ll), 8); } @@ -124,7 +110,7 @@ uint32_t MsgBuffer::peekInt32() const { uint64_t MsgBuffer::peekInt64() const { assert(readableBytes() >= 8); uint64_t rll = *(static_cast((void *)peek())); - return Math::ntoh64(rll); + return ntoh64(rll); } void MsgBuffer::retrieve(size_t len) { diff --git a/core/containers/msg_buffer.h b/web_backends/drogon/trantor/utils/MsgBuffer.h similarity index 81% rename from core/containers/msg_buffer.h rename to web_backends/drogon/trantor/utils/MsgBuffer.h index 400d8b6..33c8633 100644 --- a/core/containers/msg_buffer.h +++ b/web_backends/drogon/trantor/utils/MsgBuffer.h @@ -1,35 +1,20 @@ - -// This file is originally from Trantor - MsgBuffer.h - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/** + * + * @file MsgBuffer.h + * @author An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ #pragma once - +#include +#include #include #include #include @@ -40,6 +25,8 @@ using ssize_t = long long; #endif +namespace trantor +{ static constexpr size_t kBufferDefaultLength{2048}; static constexpr char CRLF[]{"\r\n"}; @@ -48,7 +35,7 @@ static constexpr char CRLF[]{"\r\n"}; * data. * */ -class MsgBuffer +class TRANTOR_EXPORT MsgBuffer { public: /** @@ -377,11 +364,12 @@ inline void swap(MsgBuffer &one, MsgBuffer &two) noexcept { one.swap(two); } +} // namespace trantor namespace std { template <> -inline void swap(MsgBuffer &one, MsgBuffer &two) noexcept +inline void swap(trantor::MsgBuffer &one, trantor::MsgBuffer &two) noexcept { one.swap(two); } diff --git a/web_backends/drogon/trantor/utils/NonCopyable.h b/web_backends/drogon/trantor/utils/NonCopyable.h index 4483f22..5c0af62 100644 --- a/web_backends/drogon/trantor/utils/NonCopyable.h +++ b/web_backends/drogon/trantor/utils/NonCopyable.h @@ -16,6 +16,8 @@ #include +namespace trantor +{ /** * @brief This class represents a non-copyable object. * @@ -35,3 +37,5 @@ class TRANTOR_EXPORT NonCopyable NonCopyable(NonCopyable &&) noexcept(true) = default; NonCopyable &operator=(NonCopyable &&) noexcept(true) = default; }; + +} // namespace trantor diff --git a/web_backends/drogon/trantor/utils/ObjectPool.h b/web_backends/drogon/trantor/utils/ObjectPool.h new file mode 100644 index 0000000..145a355 --- /dev/null +++ b/web_backends/drogon/trantor/utils/ObjectPool.h @@ -0,0 +1,76 @@ +/** + * + * @file ObjectPool.h + * @author An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace trantor +{ +/** + * @brief This class template represents a object pool. + * + * @tparam T + */ +template +class ObjectPool : public NonCopyable, + public std::enable_shared_from_this> +{ + public: + std::shared_ptr getObject() + { + static_assert(!std::is_pointer::value, + "The parameter type of the ObjectPool template can't be " + "pointer type"); + T *p{nullptr}; + { + std::lock_guard lock(mtx_); + if (!objs_.empty()) + { + p = objs_.back(); + objs_.pop_back(); + } + } + + if (p == nullptr) + { + p = new T; + } + + assert(p); + std::weak_ptr> weakPtr = this->shared_from_this(); + auto obj = std::shared_ptr(p, [weakPtr](T *ptr) { + auto self = weakPtr.lock(); + if (self) + { + std::lock_guard lock(self->mtx_); + self->objs_.push_back(ptr); + } + else + { + delete ptr; + } + }); + return obj; + } + + private: + std::vector objs_; + std::mutex mtx_; +}; +} // namespace trantor \ No newline at end of file diff --git a/web_backends/drogon/trantor/utils/SerialTaskQueue.cc b/web_backends/drogon/trantor/utils/SerialTaskQueue.cc new file mode 100644 index 0000000..e807090 --- /dev/null +++ b/web_backends/drogon/trantor/utils/SerialTaskQueue.cc @@ -0,0 +1,49 @@ +/** + * + * SerialTaskQueue.cc + * An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#include +#include +#ifdef __linux__ +#include +#endif +namespace trantor { +SerialTaskQueue::SerialTaskQueue(const std::string &name) : + queueName_(name.empty() ? "SerailTaskQueue" : name), + loopThread_(queueName_) { + loopThread_.run(); +} +void SerialTaskQueue::stop() { + stop_ = true; + loopThread_.getLoop()->quit(); + loopThread_.wait(); +} +SerialTaskQueue::~SerialTaskQueue() { + if (!stop_) + stop(); + LOG_TRACE << "destruct SerialTaskQueue('" << queueName_ << "')"; +} +void SerialTaskQueue::runTaskInQueue(const std::function &task) { + loopThread_.getLoop()->runInLoop(task); +} +void SerialTaskQueue::runTaskInQueue(std::function &&task) { + loopThread_.getLoop()->runInLoop(std::move(task)); +} + +void SerialTaskQueue::waitAllTasksFinished() { + syncTaskInQueue([]() { + + }); +} + +} // namespace trantor diff --git a/web_backends/drogon/trantor/utils/SerialTaskQueue.h b/web_backends/drogon/trantor/utils/SerialTaskQueue.h new file mode 100644 index 0000000..04742bb --- /dev/null +++ b/web_backends/drogon/trantor/utils/SerialTaskQueue.h @@ -0,0 +1,100 @@ +/** + * + * SerialTaskQueue.h + * An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#pragma once + +#include "TaskQueue.h" +#include +#include +#include +#include +#include +#include +namespace trantor +{ +/** + * @brief This class represents a task queue in which all tasks are executed one + * by one. + * + */ +class TRANTOR_EXPORT SerialTaskQueue : public TaskQueue +{ + public: + /** + * @brief Run a task in the queue. + * + * @param task + */ + virtual void runTaskInQueue(const std::function &task); + virtual void runTaskInQueue(std::function &&task); + + /** + * @brief Get the name of the queue. + * + * @return std::string + */ + virtual std::string getName() const + { + return queueName_; + }; + + /** + * @brief Wait until all tasks in the queue are finished. + * + */ + void waitAllTasksFinished(); + + SerialTaskQueue() = delete; + + /** + * @brief Construct a new serail task queue instance. + * + * @param name + */ + explicit SerialTaskQueue(const std::string &name); + + virtual ~SerialTaskQueue(); + + /** + * @brief Check whether a task is running in the queue. + * + * @return true + * @return false + */ + bool isRuningTask() + { + return loopThread_.getLoop() + ? loopThread_.getLoop()->isCallingFunctions() + : false; + } + + /** + * @brief Get the number of tasks in the queue. + * + * @return size_t + */ + size_t getTaskCount(); + + /** + * @brief Stop the queue. + * + */ + void stop(); + + protected: + std::string queueName_; + EventLoopThread loopThread_; + bool stop_{false}; +}; +} // namespace trantor diff --git a/web_backends/drogon/trantor/utils/TaskQueue.h b/web_backends/drogon/trantor/utils/TaskQueue.h new file mode 100644 index 0000000..fb656d5 --- /dev/null +++ b/web_backends/drogon/trantor/utils/TaskQueue.h @@ -0,0 +1,58 @@ +/** + * + * @file TaskQueue.h + * @author An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#pragma once + +#include "NonCopyable.h" +#include +#include +#include +namespace trantor +{ +/** + * @brief This class is a pure virtual class that can be implemented as a + * SerialTaskQueue or a ConcurrentTaskQueue. + * + */ +class TaskQueue : public NonCopyable +{ + public: + virtual void runTaskInQueue(const std::function &task) = 0; + virtual void runTaskInQueue(std::function &&task) = 0; + virtual std::string getName() const + { + return ""; + }; + + /** + * @brief Run a task in the queue sychronously. This means that the task is + * executed before the method returns. + * + * @param task + */ + void syncTaskInQueue(const std::function &task) + { + std::promise prom; + std::future fut = prom.get_future(); + runTaskInQueue([&]() { + task(); + prom.set_value(1); + }); + fut.get(); + }; + virtual ~TaskQueue() + { + } +}; +} // namespace trantor diff --git a/core/loops/timing_wheel.cpp b/web_backends/drogon/trantor/utils/TimingWheel.cc similarity index 58% rename from core/loops/timing_wheel.cpp rename to web_backends/drogon/trantor/utils/TimingWheel.cc index 75266cf..57c46e9 100644 --- a/core/loops/timing_wheel.cpp +++ b/web_backends/drogon/trantor/utils/TimingWheel.cc @@ -1,37 +1,22 @@ +/** + * + * TimingWheel.cc + * An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ -// This file is originally from Trantor - TimingWheel.cc +#include -// Copyright (c) 2016-2021, Tao An. All rights reserved. +using namespace trantor; -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "core/loops/timing_wheel.h" - - -TimingWheel::TimingWheel(EventLoop *loop, +TimingWheel::TimingWheel(trantor::EventLoop *loop, size_t maxTimeout, float ticksInterval, size_t bucketsNumPerWheel) : diff --git a/core/loops/timing_wheel.h b/web_backends/drogon/trantor/utils/TimingWheel.h similarity index 53% rename from core/loops/timing_wheel.h rename to web_backends/drogon/trantor/utils/TimingWheel.h index 4d84176..55f7fe0 100644 --- a/core/loops/timing_wheel.h +++ b/web_backends/drogon/trantor/utils/TimingWheel.h @@ -1,37 +1,22 @@ - -// This file is originally from Trantor - TimingWheel.h - -// Copyright (c) 2016-2021, Tao An. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of Tao An nor the names of other contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/** + * + * @file TimingWheel.h + * @author An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ #pragma once -#include "core/loops/event_loop.h" -#include "core/log/logger.h" +#include +#include +#include #include #include #include @@ -45,6 +30,8 @@ #define TIMING_BUCKET_NUM_PER_WHEEL 100 #define TIMING_TICK_INTERVAL 1.0 +namespace trantor +{ using EntryPtr = std::shared_ptr; using EntryBucket = std::unordered_set; @@ -55,7 +42,7 @@ using BucketQueue = std::deque; * accuracy. This is usually used internally. * */ -class TimingWheel +class TRANTOR_EXPORT TimingWheel { public: class CallbackEntry @@ -86,7 +73,7 @@ class TimingWheel * @example Four wheels with 200 buckets per wheel means the timing wheel * can work with a timeout up to 200^4 seconds, about 50 years; */ - TimingWheel(EventLoop *loop, + TimingWheel(trantor::EventLoop *loop, size_t maxTimeout, float ticksInterval = TIMING_TICK_INTERVAL, size_t bucketsNumPerWheel = TIMING_BUCKET_NUM_PER_WHEEL); @@ -107,10 +94,11 @@ class TimingWheel std::atomic ticksCounter_{0}; - TimerId timerId_; - EventLoop *loop_; + trantor::TimerId timerId_; + trantor::EventLoop *loop_; float ticksInterval_; size_t wheelsNum_; size_t bucketsNumPerWheel_; }; +} // namespace trantor diff --git a/web_backends/drogon/trantor/utils/WindowsSupport.cc b/web_backends/drogon/trantor/utils/WindowsSupport.cc new file mode 100644 index 0000000..a3b5cb7 --- /dev/null +++ b/web_backends/drogon/trantor/utils/WindowsSupport.cc @@ -0,0 +1,45 @@ +/** + * + * WindowsSupport.cc + * An Tao + * + * Implementation of Windows support functions. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#include +#include + +// from polipo +int win32_read_socket(int fd, void *buf, int n) { + int rc = recv(fd, reinterpret_cast(buf), n, 0); + if (rc == SOCKET_ERROR) { + _set_errno(WSAGetLastError()); + } + return rc; +} + +int readv(int fd, const struct iovec *vector, int count) { + int ret = 0; /* Return value */ + int i; + for (i = 0; i < count; i++) { + int n = vector[i].iov_len; + int rc = win32_read_socket(fd, vector[i].iov_base, n); + if (rc == n) { + ret += rc; + } else { + if (rc < 0) { + ret = (ret == 0 ? rc : ret); + } else { + ret += rc; + } + break; + } + } + return ret; +} diff --git a/web_backends/drogon/trantor/utils/WindowsSupport.h b/web_backends/drogon/trantor/utils/WindowsSupport.h new file mode 100644 index 0000000..9081df8 --- /dev/null +++ b/web_backends/drogon/trantor/utils/WindowsSupport.h @@ -0,0 +1,26 @@ +/** + * + * @file WindowsSupport.h + * @author An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#pragma once + +#include +#include + +struct iovec +{ + void *iov_base; /* Starting address */ + int iov_len; /* Number of bytes */ +}; + +TRANTOR_EXPORT int readv(int fd, const struct iovec *vector, int count);