@@ -160,24 +160,15 @@ WebSocketClient::WebSocketClient(
160160WebSocketClient::~WebSocketClient () {
161161 if (market_data_websocket_) {
162162 if (market_data_websocket_->status () != Websocket::Status::DISCONNECTED ) {
163+ market_data_websocket_->reset_callbacks ();
163164 market_data_websocket_->close ();
164- if (pending_md_socket_close_.fetch_add (1 , std::memory_order_acq_rel) == 0 ) {
165- // waiting for on disconnected callback
166- auto start = std::chrono::system_clock::now ();
167- while (pending_md_socket_close_.load (std::memory_order_acquire) == 1 &&
168- (std::chrono::system_clock::now () - start) < std::chrono::seconds (2 ));
169- }
170165 }
171166 market_data_websocket_.reset ();
172167 }
173168 if (user_data_websocket_) {
174169 if (user_data_websocket_->status () != Websocket::Status::DISCONNECTED ) {
170+ user_data_websocket_->reset_callbacks ();
175171 user_data_websocket_->close ();
176- if (pending_user_socket_close_.fetch_add (1 , std::memory_order_acq_rel) == 0 ) {
177- auto start = std::chrono::system_clock::now ();
178- while (pending_user_socket_close_.load (std::memory_order_acquire) == 1 &&
179- (std::chrono::system_clock::now () - start) < std::chrono::seconds (2 ));
180- }
181172 }
182173 user_data_websocket_.reset ();
183174 }
@@ -206,55 +197,65 @@ void WebSocketClient::stop() {
206197 if (market_data_websocket_->status () != Websocket::Status::DISCONNECTED ) {
207198 market_data_websocket_->close ();
208199 }
209- market_data_websocket_.reset ();
210200 }
211201 if (user_data_websocket_) {
212202 if (user_data_websocket_->status () != Websocket::Status::DISCONNECTED ) {
213203 user_data_websocket_->close ();
214204 }
215- user_data_websocket_.reset ();
216205 }
217206}
218207
219208void WebSocketClient::subscribe (const std::vector<std::string> &product_ids, const std::vector<WebSocketChannel> &channels) {
220209 for (auto channel : channels) {
221210 auto products = product_ids_[static_cast <uint8_t >(channel)];
222211 auto subscribe_json = json{{" type" , " subscribe" }, {" product_ids" , product_ids}, {" channel" , to_string (channel)}};
223- std::shared_ptr< Websocket> websocket;
212+ Websocket* websocket;
224213 if (channel == WebSocketChannel::USER ) {
225- if (!user_data_websocket_ && !user_data_url_.empty ()) {
226- user_data_websocket_ = std::make_shared<Websocket>(
227- user_data_url_,
228- [this ]() { onUserDataConnected (); },
229- [this ]() { onUserDataDisconnected (); },
230- [this ](const char * data, std::size_t size) { onUserData (data, size); },
231- [this ](std::string err) { onUserDataError (std::move (err)); }
232- );
214+ if (!user_data_websocket_) {
215+ if (!user_data_url_.empty ()) {
216+ user_data_websocket_ = std::make_unique<Websocket>(
217+ user_data_url_,
218+ [this ]() { onUserDataConnected (); },
219+ [this ]() { onUserDataDisconnected (); },
220+ [this ](const char * data, std::size_t size) { onUserData (data, size); },
221+ [this ](std::string err) { onUserDataError (std::move (err)); }
222+ );
223+ user_data_websocket_->open ();
224+
225+ // subscribe heartbeat to keep user channel alive
226+ auto heartbeat_sub = json{{" type" , " subscribe" }, {" channel" , " heartbeats" }};
227+ heartbeat_sub[" jwt" ] = generate_coinbase_jwt (user_data_url_.c_str ());
228+ auto subscribe_str = heartbeat_sub.dump ();
229+ user_data_websocket_->send (subscribe_str.c_str (), subscribe_str.size ());
230+ }
231+ } else if (user_data_websocket_->status () > Websocket::Status::CONNECTED ) {
233232 user_data_websocket_->open ();
234- pending_user_socket_close_.store (0 , std::memory_order_release);
235233
236234 // subscribe heartbeat to keep user channel alive
237235 auto heartbeat_sub = json{{" type" , " subscribe" }, {" channel" , " heartbeats" }};
238236 heartbeat_sub[" jwt" ] = generate_coinbase_jwt (user_data_url_.c_str ());
239237 auto subscribe_str = heartbeat_sub.dump ();
240238 user_data_websocket_->send (subscribe_str.c_str (), subscribe_str.size ());
241239 }
242- websocket = user_data_websocket_;
240+ websocket = user_data_websocket_. get () ;
243241 subscribe_json[" jwt" ] = generate_coinbase_jwt (user_data_url_.c_str ());
244242 }
245243 else {
246- if (!market_data_websocket_ && !market_data_url_.empty ()) {
247- market_data_websocket_ = std::make_shared<Websocket>(
248- market_data_url_,
249- [this ]() { onMarketDataConnected (); },
250- [this ]() { onMarketDataDisconnected (); },
251- [this ](const char * data, std::size_t size) { onMarketData (data, size); },
252- [this ](std::string err) { onMarketDataError (std::move (err)); }
253- );
244+ if (!market_data_websocket_) {
245+ if (!market_data_url_.empty ()) {
246+ market_data_websocket_ = std::make_unique<Websocket>(
247+ market_data_url_,
248+ [this ]() { onMarketDataConnected (); },
249+ [this ]() { onMarketDataDisconnected (); },
250+ [this ](const char * data, std::size_t size) { onMarketData (data, size); },
251+ [this ](std::string err) { onMarketDataError (std::move (err)); }
252+ );
253+ market_data_websocket_->open ();
254+ }
255+ } else if (market_data_websocket_->status () > Websocket::Status::CONNECTED ) {
254256 market_data_websocket_->open ();
255- pending_md_socket_close_.store (0 , std::memory_order_release);
256257 }
257- websocket = market_data_websocket_;
258+ websocket = market_data_websocket_. get () ;
258259 }
259260
260261 if (websocket == nullptr ) {
@@ -269,7 +270,7 @@ void WebSocketClient::subscribe(const std::vector<std::string> &product_ids, con
269270
270271void WebSocketClient::unsubscribe (const std::vector<std::string> &product_ids, const std::vector<WebSocketChannel> &channels) {
271272 for (auto channel : channels) {
272- auto websocket = channel == WebSocketChannel::USER ? user_data_websocket_ : market_data_websocket_;
273+ auto & websocket = channel == WebSocketChannel::USER ? user_data_websocket_ : market_data_websocket_;
273274 auto unsubscribe_json = json{{" type" , " unsubscribe" }, {" product_ids" , product_ids}, {" channel" , to_string (channel)}};
274275 auto unsubscribe_str = unsubscribe_json.dump ();
275276 if (websocket == nullptr ) {
@@ -369,8 +370,6 @@ void WebSocketClient::onMarketDataDisconnected() {
369370 data_handler_->callbacks_ ->onMarketDataDisconnected (this );
370371 data_handler_->resetMarketDataSequence (this );
371372 }
372- pending_md_socket_close_.fetch_add (1 , std::memory_order_acq_rel);
373- market_data_websocket_.reset ();
374373}
375374
376375
@@ -391,8 +390,6 @@ void WebSocketClient::onUserDataDisconnected() {
391390 data_handler_->callbacks_ ->onUserDataDisconnected (this );
392391 data_handler_->resetUserDataSequence (this );
393392 }
394- pending_user_socket_close_.fetch_add (1 , std::memory_order_acq_rel);
395- user_data_websocket_.reset ();
396393}
397394
398395void WebSocketClient::onMarketData (const char * data, std::size_t size) {
0 commit comments