Fixed a crash

This commit is contained in:
WolverinDEV 2020-01-27 13:02:22 +01:00
parent aaea9b9339
commit 8acd2396d3
8 changed files with 53 additions and 15 deletions

View File

@ -171,10 +171,13 @@ std::deque<std::shared_ptr<ViewEntry>> ClientChannelView::insert_channels(shared
head = head->next; head = head->next;
continue; continue;
}; };
debugMessage(this->getServerId(), "{}[CHANNELS] Insert channel {} ({} => order {}) after {} ({})", auto now_prv = this->find_channel(entry->previousChannelId());
debugMessage(this->getServerId(), "{}[CHANNELS] Insert channel {} ({}) after {} ({}). Original view prv: {} ({}). Original prv: {} ({})",
CLIENT_STR_LOG_PREFIX_(this->owner), CLIENT_STR_LOG_PREFIX_(this->owner),
channel->channelId(), channel->name(), entry->previousChannelId(), channel->channelId(), channel->name(),
previous ? previous->channelId() : 0, previous_channel ? previous_channel->name() : "" entry->previousChannelId(), now_prv ? now_prv->channel()->name() : "",
remote_previous ? remote_previous->entry->channelId() : 0, remote_previous ? dynamic_pointer_cast<BasicChannel>(remote_previous->entry)->name() : "",
head->previous ? head->previous->entry->channelId() : 0, head->previous ? dynamic_pointer_cast<BasicChannel>(head->previous->entry)->name() : ""
); );
result.push_back(entry); result.push_back(entry);

View File

@ -338,6 +338,31 @@ bool ServerChannelTree::buildChannelTreeFromTemp() {
return true; return true;
} }
inline void walk_tree(const std::shared_ptr<TreeView::LinkedTreeEntry>& parent, std::shared_ptr<TreeView::LinkedTreeEntry> head) {
auto parent_id = parent ? parent->entry->channelId() : 0;
std::shared_ptr<TreeView::LinkedTreeEntry> previous{nullptr};
while(head) {
head->entry->setParentChannelId(parent_id);
if(head->previous != previous) {
logCritical(0, "Detect broken channel tree!");
} else if(previous) {
head->entry->setPreviousChannelId(previous->entry->channelId());
} else {
head->entry->setPreviousChannelId(0);
}
if(head->child_head)
walk_tree(head, head->child_head);
previous = head;
head = head->next;
}
}
bool ServerChannelTree::updateOrderIds() {
walk_tree(nullptr, this->head);
return true;
}
inline ssize_t count_characters(const std::string& in) { inline ssize_t count_characters(const std::string& in) {
size_t index = 0; size_t index = 0;
@ -478,6 +503,7 @@ void ServerChannelTree::loadChannelsFromDatabase() {
logMessage(this->getServerId(), "Loaded {} saved channels. Assembling...", this->tmpChannelList.size()); logMessage(this->getServerId(), "Loaded {} saved channels. Assembling...", this->tmpChannelList.size());
this->initializeTempParents(); this->initializeTempParents();
this->buildChannelTreeFromTemp(); this->buildChannelTreeFromTemp();
this->updateOrderIds();
this->validateChannelNames(); this->validateChannelNames();
this->validateChannelIcons(); this->validateChannelIcons();
//this->printChannelTree(); //this->printChannelTree();

View File

@ -62,6 +62,7 @@ namespace ts {
bool initializeTempParents(); bool initializeTempParents();
bool buildChannelTreeFromTemp(); bool buildChannelTreeFromTemp();
bool updateOrderIds();
bool validateChannelNames(); bool validateChannelNames();
bool validateChannelIcons(); bool validateChannelIcons();
int loadChannelFromData(int argc, char** data, char** column); int loadChannelFromData(int argc, char** data, char** column);

View File

@ -685,6 +685,7 @@ void ConnectedClient::sendChannelList(bool lock_channel_tree) {
*/ */
/*
std::deque<std::shared_ptr<ViewEntry>> entry_channels{pop_view_entry(channels, this->currentChannel->channelId())}; std::deque<std::shared_ptr<ViewEntry>> entry_channels{pop_view_entry(channels, this->currentChannel->channelId())};
while(entry_channels.front()) entry_channels.push_front(pop_view_entry(channels, entry_channels.front()->parentId())); while(entry_channels.front()) entry_channels.push_front(pop_view_entry(channels, entry_channels.front()->parentId()));
entry_channels.pop_front(); entry_channels.pop_front();
@ -693,8 +694,9 @@ void ConnectedClient::sendChannelList(bool lock_channel_tree) {
send_channels(this, entry_channels.begin(), entry_channels.end(), true); send_channels(this, entry_channels.begin(), entry_channels.end(), true);
this->notifyClientEnterView(_this.lock(), nullptr, "", this->currentChannel, ViewReasonId::VREASON_SYSTEM, nullptr, false); //Notify self after path is send this->notifyClientEnterView(_this.lock(), nullptr, "", this->currentChannel, ViewReasonId::VREASON_SYSTEM, nullptr, false); //Notify self after path is send
*/
send_channels(this, channels.begin(), channels.end(), false); send_channels(this, channels.begin(), channels.end(), false);
this->notifyClientEnterView(_this.lock(), nullptr, "", this->currentChannel, ViewReasonId::VREASON_SYSTEM, nullptr, false); //Notify self after path is send
this->sendCommand(Command("channellistfinished")); this->sendCommand(Command("channellistfinished"));
} }

View File

@ -96,11 +96,12 @@ void VoiceClientConnection::handle_incoming_datagram(const pipes::buffer_view& b
unique_lock queue_lock(fragment_buffer.buffer_lock); unique_lock queue_lock(fragment_buffer.buffer_lock);
auto result = fragment_buffer.accept_index(packet_parser.packet_id()); auto result = fragment_buffer.accept_index(packet_parser.packet_id());
if(result != 0) { /* packet index is ahead buffer index */ if(result != 0) { /* packet index is ahead buffer index */
debugMessage(this->client->getServerId(), "{} Dropping command packet because command assembly buffer has an {} ({}|{})", debugMessage(this->client->getServerId(), "{} Dropping command packet because command assembly buffer has an {} ({}|{}|{})",
CLIENT_STR_LOG_PREFIX_(this->client), CLIENT_STR_LOG_PREFIX_(this->client),
result == -1 ? "underflow" : "overflow", result == -1 ? "underflow" : "overflow",
fragment_buffer.capacity(), fragment_buffer.capacity(),
fragment_buffer.current_index() fragment_buffer.current_index(),
packet_parser.packet_id()
); );
if(result == -1) { /* underflow */ if(result == -1) { /* underflow */
@ -227,7 +228,8 @@ void VoiceClientConnection::execute_handle_command_packets(const std::chrono::sy
//TODO: Remove the buffer_execute_lock and use the one within the this->client->handlePacketCommand method //TODO: Remove the buffer_execute_lock and use the one within the this->client->handlePacketCommand method
unique_lock<std::recursive_timed_mutex> buffer_execute_lock; unique_lock<std::recursive_timed_mutex> buffer_execute_lock;
pipes::buffer payload{}; pipes::buffer payload{};
auto reexecute_handle = this->next_reassembled_command(buffer_execute_lock, payload); uint16_t packet_id{};
auto reexecute_handle = this->next_reassembled_command(buffer_execute_lock, payload, packet_id);
if(!payload.empty()){ if(!payload.empty()){
auto startTime = system_clock::now(); auto startTime = system_clock::now();
@ -255,7 +257,7 @@ void VoiceClientConnection::execute_handle_command_packets(const std::chrono::sy
} }
/* buffer_execute_lock: lock for in order execution */ /* buffer_execute_lock: lock for in order execution */
bool VoiceClientConnection::next_reassembled_command(unique_lock<std::recursive_timed_mutex>& buffer_execute_lock, pipes::buffer& result) { bool VoiceClientConnection::next_reassembled_command(unique_lock<std::recursive_timed_mutex>& buffer_execute_lock, pipes::buffer& result, uint16_t& packet_id) {
command_fragment_buffer_t* buffer{nullptr}; command_fragment_buffer_t* buffer{nullptr};
unique_lock<std::recursive_timed_mutex> buffer_lock; /* general buffer lock */ unique_lock<std::recursive_timed_mutex> buffer_lock; /* general buffer lock */
@ -290,9 +292,11 @@ bool VoiceClientConnection::next_reassembled_command(unique_lock<std::recursive_
pipes::buffer payload{}; pipes::buffer payload{};
/* lets find out if we've to reassemble the packet */ /* lets find out if we've to reassemble the packet */
if(buffer->slot_value(0).packet_flags & PacketFlag::Fragmented) { auto& first_buffer = buffer->slot_value(0);
uint16_t sequence_length = 1; packet_id = first_buffer.packet_id;
size_t total_payload_length{0}; if(first_buffer.packet_flags & PacketFlag::Fragmented) {
uint16_t sequence_length{1};
size_t total_payload_length{first_buffer.payload_length};
do { do {
if(sequence_length >= buffer->capacity()) { if(sequence_length >= buffer->capacity()) {
logError(this->client->getServerId(), "{} Command fragment buffer is full, and there is not fragmented packet end. Dropping full buffer which will probably cause a connection loss.", CLIENT_STR_LOG_PREFIX_(this->client)); logError(this->client->getServerId(), "{} Command fragment buffer is full, and there is not fragmented packet end. Dropping full buffer which will probably cause a connection loss.", CLIENT_STR_LOG_PREFIX_(this->client));
@ -320,7 +324,7 @@ bool VoiceClientConnection::next_reassembled_command(unique_lock<std::recursive_
pipes::buffer packet_buffer{total_payload_length}; pipes::buffer packet_buffer{total_payload_length};
char* packet_buffer_ptr = &packet_buffer[0]; char* packet_buffer_ptr = &packet_buffer[0];
size_t packet_count = 0; size_t packet_count{0};
packet_flags = buffer->slot_value(0).packet_flags; packet_flags = buffer->slot_value(0).packet_flags;
while(packet_count < sequence_length) { while(packet_count < sequence_length) {
@ -340,6 +344,7 @@ bool VoiceClientConnection::next_reassembled_command(unique_lock<std::recursive_
); );
} }
#endif #endif
payload = packet_buffer;
} else { } else {
auto packet = buffer->pop_front(); auto packet = buffer->pop_front();
packet_flags = packet.packet_flags; packet_flags = packet.packet_flags;
@ -415,7 +420,7 @@ bool VoiceClientConnection::prepare_packet_for_write(vector<pipes::buffer> &resu
string error = "success"; string error = "success";
if(packet->type().compressable() && !packet->memory_state.fragment_entry && false) { if(packet->type().compressable() && !packet->memory_state.fragment_entry) {
packet->enable_flag(PacketFlag::Compressed); packet->enable_flag(PacketFlag::Compressed);
if(!this->compress_handler.progressPacketOut(packet.get(), error)) { if(!this->compress_handler.progressPacketOut(packet.get(), error)) {
logError(this->getClient()->getServerId(), "{} Could not compress outgoing packet.\nThis could cause fatal failed for the client.\nError: {}", error); logError(this->getClient()->getServerId(), "{} Could not compress outgoing packet.\nThis could cause fatal failed for the client.\nError: {}", error);

View File

@ -102,7 +102,7 @@ namespace ts {
//Handle stuff //Handle stuff
void execute_handle_command_packets(const std::chrono::system_clock::time_point& /* scheduled */); void execute_handle_command_packets(const std::chrono::system_clock::time_point& /* scheduled */);
bool next_reassembled_command(std::unique_lock<std::recursive_timed_mutex> &buffer_execute_lock /* packet channel execute lock */, pipes::buffer & /* buffer*/); bool next_reassembled_command(std::unique_lock<std::recursive_timed_mutex> &buffer_execute_lock /* packet channel execute lock */, pipes::buffer & /* buffer*/, uint16_t& /* packet id */);
/* ---------- Write declarations ---------- */ /* ---------- Write declarations ---------- */

View File

@ -175,6 +175,6 @@ ts::command_result VoiceClient::handleCommandClientEk(Command& cmd) {
this->connection->getCryptHandler()->setupSharedSecretNew(this->crypto.alpha, this->crypto.beta, (char*) private_key.data(), client_key.data()); this->connection->getCryptHandler()->setupSharedSecretNew(this->crypto.alpha, this->crypto.beta, (char*) private_key.data(), client_key.data());
this->connection->acknowledge_handler.reset(); this->connection->acknowledge_handler.reset();
this->crypto.protocol_encrypted = true; this->crypto.protocol_encrypted = true;
this->sendAcknowledge(2); //Send the encrypted acknowledge (most the times the second packet; If not we're going into the resend loop) this->sendAcknowledge(1); //Send the encrypted acknowledge (most the times the second packet; If not we're going into the resend loop)
return ts::command_result{error::ok}; return ts::command_result{error::ok};
} }

View File

@ -112,6 +112,7 @@ namespace ts {
virtual void set_self_ref(const std::shared_ptr<Playlist>& /* playlist */); virtual void set_self_ref(const std::shared_ptr<Playlist>& /* playlist */);
std::atomic<SongId> current_id; std::atomic<SongId> current_id;
/* channel id's are here client database ids! */
std::shared_ptr<permission::PermissionManager> _permissions; std::shared_ptr<permission::PermissionManager> _permissions;
std::shared_ptr<Properties> _properties; std::shared_ptr<Properties> _properties;
std::weak_ptr<MusicBotManager> manager; std::weak_ptr<MusicBotManager> manager;