1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2004-2021 musikcube team
4 //
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are met:
9 //
10 // * Redistributions of source code must retain the above copyright notice,
11 // this list of conditions and the following disclaimer.
12 //
13 // * Redistributions in binary form must reproduce the above copyright
14 // notice, this list of conditions and the following disclaimer in the
15 // documentation and/or other materials provided with the distribution.
16 //
17 // * Neither the name of the author nor the names of other contributors may
18 // be used to endorse or promote products derived from this software
19 // without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 // POSSIBILITY OF SUCH DAMAGE.
32 //
33 //////////////////////////////////////////////////////////////////////////////
34
35 #include "pch.hpp"
36
37 #include <musikcore/net/RawWebSocketClient.h>
38
39 using namespace musik::core;
40 using namespace musik::core::net;
41
createSslContext()42 static inline RawWebSocketClient::SslContext createSslContext() {
43 RawWebSocketClient::SslContext ctx =
44 std::make_shared<boost::asio::ssl::context>(boost::asio::ssl::context::sslv23);
45
46 try {
47 ctx->set_options(boost::asio::ssl::context::default_workarounds |
48 boost::asio::ssl::context::no_sslv2 |
49 boost::asio::ssl::context::no_sslv3 |
50 boost::asio::ssl::context::single_dh_use |
51 boost::asio::ssl::context::verify_none);
52 }
53 catch (std::exception& e) {
54 std::cerr << "Error in context pointer: " << e.what() << std::endl;
55 }
56 return ctx;
57 }
58
RawWebSocketClient(boost::asio::io_service & io)59 RawWebSocketClient::RawWebSocketClient(boost::asio::io_service& io) {
60 websocketpp::lib::error_code ec;
61
62 plainTextClient = std::make_unique<PlainTextClient>();
63 plainTextClient->clear_access_channels(websocketpp::log::alevel::all);
64 plainTextClient->init_asio(&io, ec);
65
66 tlsClient = std::make_unique<TlsClient>();
67 tlsClient->clear_access_channels(websocketpp::log::alevel::all);
68 tlsClient->init_asio(&io, ec);
69 tlsClient->set_tls_init_handler([](Connection connection) -> SslContext {
70 return createSslContext();
71 });
72 }
73
~RawWebSocketClient()74 RawWebSocketClient::~RawWebSocketClient() {
75 }
76
SetMode(Mode mode)77 void RawWebSocketClient::SetMode(Mode mode) {
78 this->mode = mode;
79 }
80
SetOpenHandler(OpenHandler openHandler)81 void RawWebSocketClient::SetOpenHandler(OpenHandler openHandler) {
82 this->plainTextClient->set_open_handler(openHandler);
83 this->tlsClient->set_open_handler(openHandler);
84 }
85
SetFailHandler(FailHandler failHandler)86 void RawWebSocketClient::SetFailHandler(FailHandler failHandler) {
87 this->plainTextClient->set_fail_handler(failHandler);
88 this->tlsClient->set_fail_handler(failHandler);
89 }
90
SetMessageHandler(MessageHandler messageHandler)91 void RawWebSocketClient::SetMessageHandler(MessageHandler messageHandler) {
92 this->plainTextClient->set_message_handler(messageHandler);
93 this->tlsClient->set_message_handler(messageHandler);
94 }
95
SetCloseHandler(CloseHandler closeHandler)96 void RawWebSocketClient::SetCloseHandler(CloseHandler closeHandler) {
97 this->plainTextClient->set_close_handler(closeHandler);
98 this->tlsClient->set_close_handler(closeHandler);
99 }
100
SetSendMessageErrorHandler(SendMessageErrorHandler errorHandler)101 void RawWebSocketClient::SetSendMessageErrorHandler(SendMessageErrorHandler errorHandler) {
102 this->sendMessageErrorHandler = errorHandler;
103 }
104
Send(Connection connection,const std::string & message)105 void RawWebSocketClient::Send(Connection connection, const std::string& message) {
106 std::error_code ec;
107 if (mode == Mode::PlainText) {
108 this->plainTextClient->send(connection, message, websocketpp::frame::opcode::text, ec);
109 }
110 else if (mode == Mode::TLS) {
111 this->tlsClient->send(connection, message, websocketpp::frame::opcode::text, ec);
112 }
113 if (ec && sendMessageErrorHandler) {
114 sendMessageErrorHandler(ec);
115 }
116 }
117
SetPongTimeout(long timeoutMs)118 void RawWebSocketClient::SetPongTimeout(long timeoutMs) {
119 this->plainTextClient->set_pong_timeout(timeoutMs);
120 this->tlsClient->set_pong_timeout(timeoutMs);
121 }
122
Connect(const std::string & uri)123 void RawWebSocketClient::Connect(const std::string& uri) {
124 websocketpp::lib::error_code ec;
125 if (mode == Mode::PlainText) {
126 PlainTextClient::connection_ptr connection = plainTextClient->get_connection(uri, ec);
127 if (!ec) {
128 plainTextClient->connect(connection);
129 }
130 }
131 else if (mode == Mode::TLS) {
132 TlsClient::connection_ptr connection = tlsClient->get_connection(uri, ec);
133 if (!ec) {
134 tlsClient->connect(connection);
135 }
136 }
137 }
138
Run()139 void RawWebSocketClient::Run() {
140 if (mode == Mode::PlainText) {
141 plainTextClient->run();
142 }
143 else if (mode == Mode::TLS) {
144 tlsClient->run();
145 }
146 }