@@ -514,21 +514,24 @@ discord_client& discord_client::connect_voice(snowflake guild_id, snowflake chan
514514 return *this ;
515515 }
516516 }
517- connecting_voice_channels[guild_id] = std::make_unique<voiceconn>(this , channel_id, enable_dave);
518- /* Once sent, this expects two events (in any order) on the websocket:
519- * VOICE_SERVER_UPDATE and VOICE_STATUS_UPDATE
520- */
521- log (ll_debug, " Sending op 4 to join VC, guild " + std::to_string (guild_id) + " channel " + std::to_string (channel_id) + (enable_dave ? " WITH DAVE" : " " ));
522- queue_message (jsonobj_to_string (json ({
523- { " op" , ft_voice_state_update },
524- { " d" , {
525- { " guild_id" , std::to_string (guild_id) },
526- { " channel_id" , std::to_string (channel_id) },
527- { " self_mute" , self_mute },
528- { " self_deaf" , self_deaf },
517+ connecting_voice_channels[guild_id] = std::make_shared<voiceconn>(this , [guild_id, channel_id, self_mute, self_deaf, enable_dave](discord_client* client) {
518+ /* Once sent, this expects two events (in any order) on the websocket:
519+ * VOICE_SERVER_UPDATE and VOICE_STATUS_UPDATE
520+ */
521+ // Always honor the given client rather than this because
522+ // the owner can change after shard reconnection.
523+ client->log (ll_debug, " Sending op 4 to join VC, guild " + std::to_string (guild_id) + " channel " + std::to_string (channel_id) + (enable_dave ? " WITH DAVE" : " " ));
524+ client->queue_message (client->jsonobj_to_string (json ({
525+ { " op" , ft_voice_state_update },
526+ { " d" , {
527+ { " guild_id" , std::to_string (guild_id) },
528+ { " channel_id" , std::to_string (channel_id) },
529+ { " self_mute" , self_mute },
530+ { " self_deaf" , self_deaf },
531+ }
529532 }
530- }
531- })), false );
533+ })), false );}, guild_id, channel_id, enable_dave);
534+
532535#endif
533536 return *this ;
534537}
@@ -581,7 +584,8 @@ voiceconn* discord_client::get_voice(snowflake guild_id) {
581584}
582585
583586
584- voiceconn::voiceconn (discord_client* o, snowflake _channel_id, bool enable_dave) : creator(o), channel_id(_channel_id), voiceclient(nullptr ), dave(enable_dave) {
587+ voiceconn::voiceconn (discord_client* o, voice_connection_gateway_request_callback_t request_callback, snowflake guild_id, snowflake channel_id, bool enable_dave) : creator(o), request_callback(std::move(request_callback)), guild_id(guild_id), channel_id(channel_id), voiceclient(nullptr ), dave(enable_dave) {
588+ request ();
585589}
586590
587591bool voiceconn::is_ready () const {
@@ -594,8 +598,7 @@ bool voiceconn::is_active() const {
594598
595599voiceconn& voiceconn::disconnect () {
596600 if (this ->is_active ()) {
597- delete voiceclient;
598- voiceclient = nullptr ;
601+ voiceclient.reset ();
599602 }
600603 return *this ;
601604}
@@ -604,16 +607,31 @@ voiceconn::~voiceconn() {
604607 this ->disconnect ();
605608}
606609
607- voiceconn& voiceconn::connect (snowflake guild_id) {
610+ voiceconn& voiceconn::request () {
611+ this ->token .clear ();
612+ this ->session_id .clear ();
613+ this ->websocket_hostname .clear ();
614+ this ->voiceclient .reset ();
615+
616+ this ->request_callback (this ->creator );
617+ return *this ;
618+ }
619+
620+ voiceconn& voiceconn::connect () {
608621 if (this ->is_ready () && !this ->is_active ()) {
609622 try {
610- this ->creator ->log (ll_debug, " Connecting voice for guild " + std::to_string (guild_id) + " channel " + std::to_string (this ->channel_id ));
611- this ->voiceclient = new discord_voice_client (creator->creator , this ->channel_id , guild_id, this ->token , this ->session_id , this ->websocket_hostname , this ->dave );
623+ this ->creator ->log (ll_debug, " Connecting voice for guild " + std::to_string (this ->guild_id ) + " channel " + std::to_string (this ->channel_id ));
624+ full_reconnection_callback_t reconnection_callback = [weak_this=weak_from_this ()] {
625+ if (std::shared_ptr<voiceconn> strong_this = weak_this.lock ()) {
626+ strong_this->request ();
627+ }
628+ };
629+ this ->voiceclient = std::make_unique<discord_voice_client>(creator->creator , std::move (reconnection_callback), this ->channel_id , this ->guild_id , this ->token , this ->session_id , this ->websocket_hostname , this ->dave );
612630 /* Note: Spawns thread! */
613631 this ->voiceclient ->run ();
614632 }
615633 catch (std::exception &e) {
616- this ->creator ->log (ll_debug, " Can't connect to voice websocket (guild_id: " + std::to_string (guild_id) + " , channel_id: " + std::to_string (this ->channel_id ) + " ): " + std::string (e.what ()));
634+ this ->creator ->log (ll_debug, " Can't connect to voice websocket (guild_id: " + std::to_string (this -> guild_id ) + " , channel_id: " + std::to_string (this ->channel_id ) + " ): " + std::string (e.what ()));
617635 }
618636 }
619637 return *this ;
0 commit comments