Last active
March 28, 2022 16:56
-
-
Save nikita-petko/58ad6a781f755d09c9fe33b49f615eee to your computer and use it in GitHub Desktop.
automod.fx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* BA Client FxV103 Migrations, this is quite volatile right now, it won't be shipped until everyting is finalized. */ | |
| // written by: cj_7 because I'm lazy | |
| // date: 05/11/2021 | |
| // TODO: fix something with mutables | |
| // moved from https://git.mfdlabs.local/mfdlabs/ba/blob/master/src/lib/players/automod.fx | |
| // nothing much has changed, but it's a lot of work to make it work with the new system. | |
| #use FX 103 | |
| // set file's namespace | |
| namespace com.mfdlabs.ba.client.lib.players.moderation; | |
| // new include syntax, slow moving back to it being preprocessors | |
| #using <"com.consider"> | |
| #using <"com.mfdlabs.series_ten.moderation"> | |
| #using <"com.networking.replication"> | |
| #using <"com.gc"> | |
| #using <"com.io"> | |
| #using <"com.mfdlabs.l22.packagesv2"> | |
| #using <"com.mfdlabs.l22.diagnosticsv2"> | |
| using namespace com::mfdlabs::series_ten::moderation; | |
| enum AUTOMOD_PACKET_TYPE | |
| { | |
| REQUEST_INITIAL_DATA = 2613, | |
| REQUEST_AUDIT_DATA, | |
| BAD_PACKET_DATA, | |
| SEND_AUDIT_DATA = 6152 | |
| } | |
| NETWORKING_REPLICATION_PACKET_TYPE(AUTOMOD_PACKET_TYPE); | |
| IMMUTABLE_PACKAGE_V2 class AutoModerator | |
| : public com::mfdlabs::l22::packages::package | |
| , public com::networking::replication::reciever | |
| { | |
| private: | |
| void disconnect_deferred(com::networking::replication::connection_peer* peer, com::networking::replication::disconnect_reason reason = com::networking::replication::disconnect_bad_data); | |
| { | |
| // calls for disconnection but sends a log dump and metrics to the server | |
| peer->call_for_disconnect(reason); | |
| disconnect_cleanup(peer); | |
| } | |
| void disconnect(com::networking::replication::connection_peer* peer, com::networking::replication::disconnect_reason reason = com::networking::replication::disconnect_bad_data); | |
| { | |
| peer->immediate_disconnect(reason); | |
| disconnect_cleanup(peer); | |
| } | |
| void disconnect_cleanup(com::networking::replication::connection_peer* peer); | |
| { | |
| SYSTEM_CALL_FOR_FATALITY(com::string::format("AutoModerator: Peer '%s' disconnected", peer->get_machine_address())); | |
| peer->dispose(); | |
| URGENT_GC_NOW(this); | |
| } | |
| void send_audit(com::networking::replication::connection_peer* peer) | |
| { | |
| // safe here because it's possibly unreadable due to permissions (we should be allow to read it by default because we own the folder) | |
| const com::io::file_stream initial_data = auditing::fetch_bad_actor_detections_safe(peer); | |
| if (initial_data == NULL) { this->disconnect(peer, com::networking::replication::disconnect_permissions_conflict); return; } | |
| com::networking::replication::data_stream stream; | |
| stream << AUTOMOD_PACKET_TYPE::SEND_AUDIT_DATA << initial_data.to_buffer(); | |
| // TODO: clean up the enum references | |
| peer->send_replication_packet( | |
| stream, | |
| com::networking::replication::replication_packet_type::data_packet, | |
| com::networking::replication::replication_packet_reliability::reliable_packet, | |
| com::networking::replication::replication_packet_cacheability::no_cache, | |
| com::networking::replication::replication_packet_priority::high_priority, | |
| com::networking::replication::replication_packet_order::sequenced_packet, | |
| com::networking::replication::replication_packet_order_index::any | |
| ); | |
| return true; | |
| } | |
| public: | |
| // inferable parameter types based on the base class or symbol's type | |
| /*override*/ virtual void on_replication_packet(^packet) | |
| { | |
| // why would the packet be null? | |
| if (packet == NULL) { return; } | |
| if (!packet->is_data_packet()) { packet->next(); return; } | |
| com::networking::replication::data_stream stream(&packet->encrypted_buffer); | |
| // read the first byte, which is the type of the packet | |
| // we only want the type of the packet to be any of the following: | |
| // AUTOMOD_PACKET_TYPE::REQUEST_INITIAL_DATA -> server requests client information from the client's file system directly | |
| // AUTOMOD_PACKET_TYPE::REQUEST_AUDIT_DATA -> server requests client information for an ongoing server investigation on a possible bad actor | |
| // AUTOMOD_PACKET_TYPE::BAD_PACKET_DATA -> client sends the server a bad packet, | |
| // possibly corrupted or lost in on the upstream network, | |
| // if this happens the server will send the client a packet to tell it to repeat a resend, | |
| // if it fails to do so, the server will disconnect the client and add it's network address to a "bad actor list" | |
| // if you want to read the data, you can use the stream, but you can also use the packet directly | |
| // packet->read(count) => char[]; decrypts the buffer and returns the count of data while shifting it off the buffer | |
| char pkt_type; | |
| stream >> pkt_type; | |
| // we want to lock the source so no other processor can execute until we're done (this will exclude the metrics processors, | |
| // because they only read the data, they don't actually call any of the next processors) | |
| consider::hold_global_lock<consider::lock_kind_write>(&packet->source) | |
| .allow_read_on_components(packet->source->get_known_metrics_components()); | |
| const auto* const peer = packet->source->get_peer(this); | |
| switch (pkt_type) | |
| { | |
| case AUTOMOD_PACKET_TYPE::REQUEST_INITIAL_DATA: | |
| send_audit(peer); | |
| packet->next(); | |
| break; | |
| case AUTOMOD_PACKET_TYPE::REQUEST_AUDIT_DATA: | |
| send_audit(peer); | |
| packet->next(); | |
| break; | |
| case AUTOMOD_PACKET_TYPE::BAD_PACKET_DATA: | |
| char bad_packet_id; | |
| char bad_packet_sequence_id; | |
| bool is_call_for_disconnect; | |
| stream >> bad_packet_id >> bad_packet_sequence_id >> is_call_for_disconnect; | |
| if (is_call_for_disconnect) { this->disconnect(peer); break; } // if the server is requesting a disconnect, disconnect the client immediately | |
| com::networking::replication::packet last_auto_mod_packet; | |
| this->packet_cache.sent.try_get_last_packet_of_id_and_at_sequence(bad_packet_id, bad_packet_sequence_id, &last_auto_mod_packet); | |
| if (last_auto_mod_packet == NULL) { this->disconnect_deferred(peer); break; } // there was no packet of this id, so we can't do anything | |
| if (last_auto_mod_packet.is_unknown_packet()) { this->disconnect_deferred(peer); break; } // the packet id was unknown, so we can't do anything | |
| // we have a packet of this id and sequence, so we can send it back to the server with reattempt metrics | |
| peer->send_with_reattempt_metrics(&last_auto_mod_packet); | |
| // we assume that the packet was sent successfully, so we can call the next processor | |
| packet->next(); | |
| break; | |
| default: | |
| packet->next(); | |
| break; | |
| } | |
| // release it just in case | |
| consider::release_global_lock<consider::lock_kind_write>(&packet->source); | |
| GC_CLEAN_UNUSED_SCOPED_MEMORY(); | |
| } | |
| } | |
| // register the processor, this will automatically register the processor with the global network manager | |
| NETWORKING_REPLICATION_PACKET_PROCESSOR_DECLARE( | |
| AutoModerator, | |
| com::networking::replication::processor_priority::high, | |
| com::networking::replication::processor_order::high, | |
| com::networking::replication::processor_order_index::any, | |
| com::networking::replication::processor_flags::allow_block_on_recieve | | |
| com::networking::replication::processor_flags::allow_block_on_send | | |
| com::networking::replication::processor_flags::allow_kill_on_disconnect | | |
| com::networking::replication::processor_flags::allow_filesystem_read | | |
| com::networking::replication::processor_flags::allow_metrics_injection | | |
| com::networking::replication::processor_flags::allow_metrics_read | | |
| com::networking::replication::processor_flags::allow_metrics_read_on_components, | |
| com::networking::replication::processor_metrics::all, | |
| com::networking::replication::processor_metrics_components::all | |
| ); | |
| // register the package into the global scope | |
| PACKAGES_V2_REGISTER_PACKAGE(AutoModerator, "AutoModerator", com::mfdlabs::l22::packages::scope_global, com::mfdlabs::l22::packages::package_type::package_type_replication_reciever | com::mfdlabs::l22::packages::package_type::package_type_replication_sender); | |
| // this will gc the package on shutdown, because it's a global package, and doesn't want to be auto-gc'd for some reason | |
| DIAGNOSTICS_EVENT_BASED_DEALLOCATION($autoModeratorSingleton, com::gc::event_on_app_released); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment